天天看點

[Effective WX] 了解wxWindow中增加和去除/銷毀子視窗的過程

wxWindow中增加和去除/銷毀子視窗的過程:

a) 增加一個子視窗

void wxWindowBase::AddChild(wxWindowBase *child)
{
    wxCHECK_RET( child, wxT("can't add a NULL child") );


    // this should never happen and it will lead to a crash later if it does
    // because RemoveChild() will remove only one node from the children list
    // and the other(s) one(s) will be left with dangling pointers in them
    wxASSERT_MSG( !GetChildren().Find((wxWindow*)child), _T("AddChild() called twice") );


    GetChildren().Append((wxWindow*)child);
    child->SetParent(this);
}
           

b) 銷毀所有的子視窗

bool wxWindowBase::DestroyChildren()
{
    wxWindowList::compatibility_iterator node;
    for ( ;; )
    {
        // we iterate until the list becomes empty
        node = GetChildren().GetFirst();
        if ( !node )
            break;


        wxWindow *child = node->GetData();


        // note that we really want to call delete and not ->Destroy() here
        // because we want to delete the child immediately, before we are
        // deleted, and delayed deletion would result in problems as our (top
        // level) child could outlive its parent
        delete child;


        wxASSERT_MSG( !GetChildren().Find(child),
                      wxT("child didn't remove itself using RemoveChild()") );
    }


    return true;
}
           

上面直接delete一個子視窗的指針。它會觸發子視窗的析構。

// reset the dangling pointer our parent window may keep to us
    if ( m_parent )
    {
        m_parent->RemoveChild(this);
    }
           

析構過程中會調用父視窗的RemoveChild函數,用來去除該子視窗,從父視窗的子視窗連結清單中。

void wxWindowBase::RemoveChild(wxWindowBase *child)
{
    wxCHECK_RET( child, wxT("can't remove a NULL child") );


    GetChildren().DeleteObject((wxWindow *)child);
    child->SetParent(NULL);
}
           

c) wxWindows的reparent

如果沒有指定parent,那麼就将這個視窗添加到全局的toplevel windows清單中。

bool wxWindowBase::Reparent(wxWindowBase *newParent)
{
    wxWindow *oldParent = GetParent();
    if ( newParent == oldParent )
    {
        // nothing done
        return false;
    }


    // unlink this window from the existing parent.
    if ( oldParent )
    {
        oldParent->RemoveChild(this);
    }
    else
    {
        wxTopLevelWindows.DeleteObject((wxWindow *)this);
    }


    // add it to the new one
    if ( newParent )
    {
        newParent->AddChild(this);
    }
    else
    {
        wxTopLevelWindows.Append((wxWindow *)this);
    }


    return true;
}
           

繼續閱讀