无窗口模式---逻辑树结构的建立
对于无窗口的模式,各种控件之间的关系需要我们自己来维护,因为我们要进行消息传递,排版布局,创建等操作时都需要沿着各种包含关系来逐个调用,这样对于窗口中的控件就形成了一个逻辑上的树形结构。我们看一下CBkPanel类,这个类的名字就表示它是一个有包含功能的类,可以有自己的子节点。这个类有一个成员CAtlList<CBkWindow *> m_lstWndChild,也就是每个CBkPanel类都有一个链表,在这个链表中存储了它的子节点控件。
那么这个链表是何时被填充的呢,我们看一下LoadChilds方法,就是在这个函数中进行的填充操作,从前面我们知道,这个函数是在用xml 初始化界面是调用的。其中对于当前节点下的所有xml子节点进行下面的处理:
CBkWindow*pNewChildWindow = _CreateBkWindowByName(pXmlChild->Value());//创建控件
if(!pNewChildWindow)
continue; //创建失败,不进行后续设置
pNewChildWindow->SetParent(m_hBkWnd); //设置父节点HBKWND
pNewChildWindow->SetContainer(m_hWndContainer); //设置容器窗口的HWND
pNewChildWindow->Load(pXmlChild); //Load这个节点的子节点
m_lstWndChild.AddTail(pNewChildWindow); //将自己加入到父节点的链表中
在CBkPanel的OnDestroy函数中进行子节点的销毁操作
POSITION pos= m_lstWndChild.GetHeadPosition();
while (pos!= NULL)
{
CBkWindow*pBkWndChild = m_lstWndChild.GetNext(pos);
pBkWndChild->BkSendMessage(WM_DESTROY);
deletepBkWndChild;
}
m_lstWndChild.RemoveAll();
之后进行消息传递,绘制,排版操作都可以使用这个树来进行处理,循环调用所有的节点。如在OnPaint函数中:
POSITION pos= m_lstWndChild.GetHeadPosition();
BOOL bDisabled= IsDisabled(), bIsChildDisabled= FALSE;
while (pos!= NULL)
{
//……此处略去
pBkWndChild->BkSendMessage(WM_PAINT,(WPARAM)(HDC)dc);
//……此处略去
}
可见也是循环向每个子节点发送WM_PAINT消息。
同时,在界面库中,还使用了BkWnds来记录所有的控件,以便可以便捷地进行获取操作:
CBkWindow类有HBKWND类型的成员变量m_hBkWnd,这是一个虚拟的窗口句柄。
BkWnds是一个控件池,创建的控件会在这里注册,并通过一个HBKWND类型变量标示,以后就可以通过控件的m_hBkWnd来获取这个控件。