DirectUI是一種策略而不是一種技術(shù),所謂的DirectUI應(yīng)該是繞開Windows的一套HWND的管理而是自己管理窗口。自己的Event機(jī)制,自己的繪圖策略等等等,,,
CWindowWnd::__WndProc;
代碼對(duì)錯(cuò)誤檢測(cè)有冗余,使用ASSERT在測(cè)試階段盡可能的暴露bug,但是release一樣能對(duì)bug敏感!
HWND CWindowWnd::Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, int x, int y, int cx, int cy, HMENU hMenu)
{
if( GetSuperClassName() != NULL && !RegisterSuperclass() ) return NULL;
if( GetSuperClassName() == NULL && !RegisterWindowClass() ) return NULL;
m_hWnd = ::CreateWindowEx(dwExStyle, GetWindowClassName(), pstrName, dwStyle, x, y, cx, cy, hwndParent, hMenu, CPaintManagerUI::GetResourceInstance(), this);
ASSERT(m_hWnd!=NULL);
return m_hWnd;
}
創(chuàng)建窗口之前首先檢查有沒有父窗口,如果有記錄他的部分信息,如果沒有注冊(cè)默認(rèn)窗口類。
然后調(diào)用CreateWindow執(zhí)行創(chuàng)建窗口的工作。
然后其它都是在API上做一下簡(jiǎn)單的包裝,,,
接下來看看兩個(gè)窗口回調(diào)函數(shù):
LRESULT CALLBACK CWindowWnd::__WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CWindowWnd* pThis = NULL;
if( uMsg == WM_NCCREATE ) {
LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
pThis = static_cast<CWindowWnd*>(lpcs->lpCreateParams);
pThis->m_hWnd = hWnd;
::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(pThis));
}
else {
pThis = reinterpret_cast<CWindowWnd*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
if( uMsg == WM_NCDESTROY && pThis != NULL ) {
LRESULT lRes = ::CallWindowProc(pThis->m_OldWndProc, hWnd, uMsg, wParam, lParam);
::SetWindowLongPtr(pThis->m_hWnd, GWLP_USERDATA, 0L);
if( pThis->m_bSubclassed ) pThis->Unsubclass();
pThis->m_hWnd = NULL;
pThis->OnFinalMessage(hWnd);
return lRes;
}
}
if( pThis != NULL ) {
return pThis->HandleMessage(uMsg, wParam, lParam);
}
else {
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
LRESULT CALLBACK CWindowWnd::__ControlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CWindowWnd* pThis = NULL;
if( uMsg == WM_NCCREATE ) {
LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
pThis = static_cast<CWindowWnd*>(lpcs->lpCreateParams);
::SetProp(hWnd, "WndX", (HANDLE) pThis);
pThis->m_hWnd = hWnd;
}
else {
pThis = reinterpret_cast<CWindowWnd*>(::GetProp(hWnd, "WndX"));
if( uMsg == WM_NCDESTROY && pThis != NULL ) {
LRESULT lRes = ::CallWindowProc(pThis->m_OldWndProc, hWnd, uMsg, wParam, lParam);
if( pThis->m_bSubclassed ) pThis->Unsubclass();
::SetProp(hWnd, "WndX", NULL);
pThis->m_hWnd = NULL;
pThis->OnFinalMessage(hWnd);
return lRes;
}
}
if( pThis != NULL ) {
return pThis->HandleMessage(uMsg, wParam, lParam);
}
else {
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
::SetProp(hWnd, "WndX", (HANDLE) pThis);
SetProp為窗口添加一個(gè)新的屬性,,,偶覺得沒有必要用這么奇淫的技巧,,,
當(dāng)工作在Wnd模式時(shí)直接全部是調(diào)用自己的窗口回調(diào),當(dāng)工作在Control模式是調(diào)用super回調(diào)函數(shù)。
這里的實(shí)際上是通過控件的子例化間接的hook了窗口消息。
在創(chuàng)建窗口的時(shí)候完成的子例化窗口類。
回到分析之前的那個(gè)問題:HWND 和 窗口對(duì)象是如何關(guān)聯(lián)起來的?
LPVOID lpParam // window-creation data
使用CreateWindowEx的時(shí)候會(huì)有一個(gè)機(jī)會(huì)提供創(chuàng)建參數(shù),回調(diào)中的WM_NCCREATE會(huì)響應(yīng)它,,,然后在這里把窗口句柄摳出來,再使用SetWindowLog關(guān)聯(lián)到窗口句柄上,,,