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;
}