父子視窗分屬不同訊息迴圈在WinXP和WinCE的差異

來源:互聯網
上載者:User

//=====================================================================
//TITLE:
//    父子視窗分屬不同訊息迴圈在WinXP和WinCE的差異
//AUTHOR:
//    norains
//DATE:
//    Monday 19- April-2010
//ENVIRONMENT:
//    WINDOWS CE 5.0
//    WINDOWS XP SP3
//=====================================================================

    老實說,這題目起的有點拗口,讀起來不太滑溜;但更有意思的是,本文所說的情況比較特殊,並不一定大家都能碰上。不過,如果碰上了,估計找起來還特別費勁,特別是對於代碼是從WinCE遷移到WinXP上的朋友而言。

 

    在開始進行本文的討論之前,先確定如下特殊條件:

     1. 主線程建立父視窗。
     2. 建立一個線程,並在該線程中建立子視窗,且該線程有子視窗的訊息迴圈。
     3. 進入到父視窗的訊息迴圈。

 

    可能用文字描述有點抽象,我們來看看具體的代碼:

#include <string></p><p>#ifdef UNICODE<br /> #ifndef TSTRING<br /> #define TSTRING std::wstring<br /> #endif<br />#else<br /> #ifndef TSTRING<br /> #define TSTRING std::string<br /> #endif<br />#endif //#ifdef UNICODE</p><p>HWND g_hWndParent = NULL;<br />HANDLE hEventNotify = NULL;<br />LRESULT CALLBACK WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)<br />{<br /> return DefWindowProc(hWnd,wMsg,wParam,lParam);<br />}<br />BOOL MyRegisterClass(const TSTRING &strClassName)<br />{<br /> WNDCLASS wc;<br /> wc.style = 0;<br /> wc.lpfnWndProc = WndProc;<br /> wc.cbClsExtra = 0;<br /> wc.cbWndExtra = 0;<br /> wc.hInstance = GetModuleHandle(NULL);<br /> wc.hIcon = NULL;<br /> wc.hCursor = LoadCursor(NULL, IDC_ARROW);<br /> wc.lpszMenuName = NULL;<br /> wc.lpszClassName = strClassName.c_str();<br /> wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);<br /> return RegisterClass(&wc);<br />}<br />HWND MyCreateWindow(const TSTRING &strClassName,const TSTRING &strWndName,HWND hWndParent,DWORD dwStyle,DWORD dwExStyle)<br />{<br /> RECT rcArea = {0};<br /> SystemParametersInfo(SPI_GETWORKAREA, 0, &rcArea, 0);<br /> return CreateWindowEx(dwExStyle,<br /> strClassName.c_str(),<br /> strWndName.c_str(),<br /> dwStyle,<br /> rcArea.left,<br /> rcArea.top,<br /> rcArea.right - rcArea.left,<br /> rcArea.bottom - rcArea.top,<br /> hWndParent,<br /> NULL,<br /> GetModuleHandle(NULL),<br /> 0);</p><p>}<br />DWORD WINAPI ThreadCreateWnd(LPVOID pArg)<br />{<br /> if(MyRegisterClass(TEXT("CHILD_CLASS")) == FALSE)<br /> {<br /> return 0x10;<br /> }<br /> if(MyCreateWindow(TEXT("CHILD_CLASS"),TEXT("CHILD_NAME"),g_hWndParent,WS_CHILD|WS_VISIBLE,0) == NULL)<br /> {<br /> return 0x20;<br /> }</p><p> OutputDebugString(TEXT("Finish Create child window/r/n"));<br /> SetEvent(hEventNotify);<br /> //The message loop<br /> MSG msg;<br /> while(GetMessage(&msg,NULL,0,0))<br /> {<br /> TranslateMessage(&msg);<br /> DispatchMessage(&msg);<br /> }<br /> return 0;<br />}</p><p>#ifdef _WIN32_WCE<br /> int WINAPI WinMain( HINSTANCE hInstance,<br /> HINSTANCE hPrevInstance,<br /> LPTSTR lpCmdLine,<br /> int nCmdShow)<br />#else<br /> int APIENTRY _tWinMain(HINSTANCE hInstance,<br /> HINSTANCE hPrevInstance,<br /> LPTSTR lpCmdLine,<br /> int nCmdShow)<br />#endif //#ifdef _WIN32_WCE<br />{ </p><p> if(MyRegisterClass(TEXT("PARENT_CLASS")) == FALSE)<br /> {<br /> return 0x10;<br /> }<br /> g_hWndParent = MyCreateWindow(TEXT("PARENT_CLASS"),TEXT("PARENT_NAME"),NULL,WS_POPUP|WS_VISIBLE,0);<br /> if(g_hWndParent == NULL)<br /> {<br /> return 0x20;<br /> }</p><p> HANDLE hEventNotify = CreateEvent(NULL,FALSE,FALSE,NULL);</p><p> CreateThread(NULL,NULL,ThreadCreateWnd,FALSE,FALSE,NULL);<br /> WaitForSingleObject(hEventNotify,INFINITE);</p><p> MSG msg;<br /> while(GetMessage(&msg,NULL,0,0))<br /> {<br /> TranslateMessage(&msg);<br /> DispatchMessage(&msg);<br /> }</p><p> return 0;<br />}<br />

    我承認,為了突出文章的主題,這代碼寫得有點崢嶸,實在不好理解。所以,就以流程圖說一下流程:


 
    如果你是WinCE環境下,剛剛的那段代碼跑的非常順暢,一點問題都沒有;但如果是在WinXP,那麼一切都會改變,你會發現,程式沒有響應,被卡死了。仔細追蹤,你會發現出問題的是在流程圖中的"建立子視窗"這一項,具體來說,是CreateWindowEx函數根本沒有返回!

 

    解決方式也非常簡單,在調用CreateWindowEx函數的時候,傳入一個WinCE所不具備的WS_EX_NOPARENTNOTIFY即可。當你傳入該數值時,CreateWindowEx就會如你所願,順順噹噹返回。

 

    由此我們或多或少可以知道WinXP和WinCE在訊息處理上的小小差異:如果沒有WS_EX_NOPARENTNOTIFY,那麼子視窗建立時,需要等待父視窗的回應。而在我們樣本的代碼中,父視窗還沒有進入訊息迴圈,無法正常響應子視窗的動作,於是便造成了死結。而WinCE則沒有這方面的問題,子視窗根本就不必等待父視窗的回應,相應的建立完畢後,直接返回。從這個意義上來說,我們一刀切地認為(可能實際底層代碼並不一定如此),雖然WinCE不具備WS_EX_NOPARENTNOTIFY這個數值,但實際上卻預設具備了該數值的屬性。

相關關鍵詞:
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.