ucgui的窗体管理主要采用了WM_Obj的窗体数据结构,在该结构中采用两种方式记录窗体,一种是链表形式,一种多叉树的形式。第一种记录所有的窗口,第二种记录当前窗口和其兄弟窗口所在的位置。其结构体如下:
struct WM_OBJ_struct
{
GUI_RECT Rect; /* outer dimensions of window */
GUI_RECT InvalidRect; /* invalid rectangle */
WM_CALLBACK* cb; /* ptr to notification callback */
WM_HWIN hNextLin; /* Next window in linear list */
WM_HWIN hParent, hFirstChild, hNext;
U16 Status; /* Some status flags */
};
首先,我们看UCGUI怎么建起这棵窗口管理树的。
UCGUI每创建一个窗口是通过WM_CreateWindowAsChild函数来申请的,在这个函数中,主要是为新的窗口申请空间,初始相关的rect和回调函数等,并建立或者加入新的节点到树中和链表中,然后发送WM_CREATE到回调函数中初始化窗口。具体的代码见UCGUI源代码。
我们主要来看看窗口管理的建立与加入。
下面的图,每个子节点的hParent都有指向父节点
(1).见图1,当新建窗口其父窗体无子节点时
(2).见图2(参照图1),当新建窗口其父窗体有子节点时,子节点为WM_SF_STAYONTOP,新建窗口为WM_SF_STAYONTOP
(3).见图3,当新建窗口其窗体不为WM_SF_STAYONTOP,且父窗口子节点不为WM_SF_STAYONTOP
(4).见图4,当新建窗口其窗体不为WM_SF_STAYONTOP,其父窗口子节点为WM_SF_STAYONTOP
接着,UCGUI把所有的窗口统一放到了一个LINKLIST(结构体中hNextLin)中,用于更方便管理窗口。
OK,到这里也了解了UCGUI WM的建立和构成,看其相关函数做了什么动作。
WM_HWIN WM_GetParent(WM_HWIN hWin):
当前节点,通过其hParent获取其父节点。
WM_HWIN WM__GetFirstSibling(WM_HWIN hWin):
获取其兄弟节点,在整个水平线中的首个,即父节点的hFirstChild
WM_HWIN WM__GetPrevSibling(WM_HWIN hWin):
获取当前节点的前一个兄弟节点
WM_HWIN WM__GetLastSibling(WM_HWIN hWin):
获取当前节点的最后一个兄弟节点
void WM_BringToBottom(WM_HWIN hWin):
把当前窗口带到最底,即把窗口放到父节点的hFirstChild
void WM_BringToTop(WM_HWIN hWin):
把当前节点放到同水平线上的最后,如果是hFirstChild需重新给其父节点指定FIRST CHILD值(hFirstChild这里不画出图)
int WM_BroadcastMessage( WM_MESSAGE* pMsg):
把消息发送到每个窗口中,利用WM_OBJ中的LINKLIST,因为有WM__FirstWin,所以根据这个遍历LINKLIST,并通过WM_SendMessage调用每个窗口的回调函数。
void WM_EnableWindow(WM_HWIN hWin):
void WM_DisableWindow(WM_HWIN hWin):
这里是通过发送WM_SET_ENABLE消息,让窗口回调函数自己处理
其他都差不多,根据环境上下文操作,这里就不详细介绍!