|
達內VC++編程實例中的一部分源碼,涉及WIN32編程的C++例子源碼,其中之一的筆記節(jié)選:
一 Win32消息機制 1 消息機制 過程驅動:程序是按照我們預先定義好的順序 執(zhí)行,每執(zhí)行一步,下一步都已經按照預定 的順序繼續(xù)執(zhí)行,直到程序結束。 事件驅動:程序的執(zhí)行順序是無序的。某個時間 點所執(zhí)行的代碼,是由外界通知。由于我們 無法決定用戶執(zhí)行順序,所以代碼的執(zhí)行也是 無序。 Win32的消息機制 - 事件驅動 2 Win32消息程序 2.1 Win32窗口注冊 2.2 Win32窗口創(chuàng)建 2.3 WIn32消息循環(huán) 2.3.1 GetMessage BOOL GetMessage( LPMSG lpMsg,//存放獲取到的消息數(shù)據 HWND hWnd,//獲取消息的窗口句柄 UINT wMsgFilterMin,//消息過濾的起始消息 UINT wMsgFilterMax //消息過濾的終止消息 ); 返回值BOOL:成功獲取消息,返回TRUE,但是 當獲取到WM_QUIT消息時,返回FALSE。 可以使用PostQuitMessage向窗口發(fā)送WM_QUIT消息 MSG - 由系統(tǒng)填寫關于消息的參數(shù) hWnd- GetMessage會根據hWnd值,接收由hWnd 指定的窗口的消息。 wMsgFilterMin,wMsgFilterMax - 消息過濾器, 要求GetMessage接收指定范圍的消息。 2.3.2 TranslateMessage 就是將鍵盤消息轉換成字符消息。 1 首先檢查是否是鍵盤按鍵消息 2 如果發(fā)現(xiàn)是按鍵消息,將根據按鍵,產生 一個字符消息,在下一個GetMessage執(zhí)行 時,會收到這個消息。 3 如果未發(fā)現(xiàn)按鍵消息,不做任何處理。 2.3.3 DispatchMessage 根據消息數(shù)據內窗口句柄,找到這個窗口 的窗口處理函數(shù), 調用處理函數(shù),進行消息 處理。 如果MSG中,HWND窗口句柄為空, DispatchMessage不做任何處理。 2.4 Win32基本消息 2.4.1 WM_DESTROY 窗口銷毀時的消息,可以做退出或善后處理。 2.4.2 WM_CREATE 窗口創(chuàng)建消息,是在窗口創(chuàng)建后, 窗口處理函數(shù)收到第一條消息。 可以在這個消息內做數(shù)據初始化/創(chuàng)建子窗口等。 WPARAM wParam - 不使用 LPARAM lParam - CREATESTRUCT指針 2.4.3 WM_SIZE 當窗口大小發(fā)生變化時,會收到這個消息。 可以在這個消息中調整窗口布局。 wParam - SIZE發(fā)生變化時的標識 LOWORD(lParam); - 客戶區(qū)的寬 HIWORD(lParam); - 客戶區(qū)的高 2.4.4 WM_SYSCOMMAND 系統(tǒng)命令消息,當點擊系統(tǒng)菜單和按鈕時, 會收到。 可以在這個消息中,提示用戶保存數(shù)據等。 wParam - 系統(tǒng)命令類型 LOWORD(lParam) - 屏幕X坐標 HIWORD(lParam) - 屏幕Y坐標 2.4.5 WM_PAINT 繪圖消息 2.4.6 鍵盤消息 2.4.7 鼠標消息 2.4.8 WM_TIMER定時器消息 2.5 消息結構 MSG - 消息結構 typedef struct tagMSG { // msg HWND hwnd; //消息的窗口句柄 UINT message;//消息標示 WPARAM wParam; //消息的參數(shù),32位 LPARAM lParam; //消息的參數(shù),32位 DWORD time;//消息產生的時間 POINT pt; //消息產生時,鼠標的位置 } MSG; 2.6 消息的獲取和發(fā)送 2.6.1 獲取GetMessage/PeekMessage GetMessage 獲取消息,阻塞函數(shù) PeekMessage 獲取消息,非阻塞函數(shù) 2.6.2 發(fā)送SendMessage/PostMessage SendMessage 發(fā)送消息并等候消息 處理結束才返回。 PostMessage 發(fā)送消息后立即返回, 不關心消息處理的結果。 LRESULT SendMessage/PostMessage( HWND hWnd, //處理消息窗口 UINT Msg, //消息的ID WPARAM wParam, //消息的參數(shù) LPARAM lParam );//消息的參數(shù) 3 消息組成和分類 3.1 消息組成 窗口句柄/消息ID/消息參數(shù)(WPARAM.LPARAM) 3.2 消息分類 3.2.1 系統(tǒng)消息 - 由系統(tǒng)定義和使用的消息 例如:WM_CREATE/WM_SIZE 消息ID范圍為: 0 - 0x03FF(WM_USER-1) 3.2.2 用戶定義消息 - 應用程序可以自己定義 和使用的消息, WM_USER(0x0400) 從WM_USER的ID開始,到0x7FFF,是用戶可以 定義使用的消息. 3.2.3 其他消息范圍 WM_APP(0x8000)-0xBFFF:應用程序訪問窗口 的消息ID 0xC000-0xFFFF: 應用程序訪問消息,使用 字符串注冊系統(tǒng)產生相應消息ID 3.2.4 用戶定義消息的使用 1)定義自定義消息ID: #define WM_FIRSTMSG (WM_USER+1) 2)在窗口處理函數(shù)中,響應消息 switch( nMsg ) { case WM_FIRSTMSG: //處理函數(shù) break; } 3)SendMessage/PostMessage發(fā)送消息 SendMessage( hWnd, WM_FIRSTMSG, 0, 0 ); 4 消息隊列 4.1 消息隊列 - 用于存儲消息的內存空間, 消息在隊列中是先入先出. 4.2 消息隊列的分類 4.2.1 系統(tǒng)消息隊列 - 由系統(tǒng)維護的消息 隊列. 4.2.2 應用程序消息隊列(線程消息對列) - 屬于每個線程的各自擁有的消息隊列. 5 消息和消息隊列 5.1 根據消息和消息隊列關系,將消息分成兩種: 隊列消息 - 可以存放在消息隊列中的消息. 非隊列消息 - 發(fā)送時不進入消息隊列. 5.2 隊列消息 首先存放到消息隊列當中,然后由GetMessage /PeekMessage取出,然后進行處理. 例如: 鼠標消息/鍵盤消息/WM_PAINT/WM_QUIT WM_TIMER消息 5.3 非隊列消息 消息發(fā)送直接發(fā)送給指定的窗口,查找窗口的 處理函數(shù),返回處理結果. 6 消息的獲取 6.1 消息循環(huán) 6.1.1 GetMesssage從對列中獲取消息, 判斷是否是WM_QUIT消息,如果發(fā)現(xiàn)是 WM_QUIT消息,消息循環(huán)結束,否則繼續(xù) 下一步. 6.1.2 TranslateMessage 翻譯按鍵消息, 如果發(fā)現(xiàn)有按鍵消息,產生字符消息放入 消息對列, 繼續(xù)下一步 6.1.3 DispatchMessage 找到消息所發(fā)窗口 的處理函數(shù),處理消息.處理完成后, 返回6.1.1. 6.2 GetMesssage和PeekMessage 6.2.1 從線程消息隊列中獲取消息,如果找到 消息,就返回消息,進行消息處理. 如果未 找到消息,執(zhí)行6.2.2 6.2.2 查找系統(tǒng)消息隊列.通過向系統(tǒng)消息隊 列查詢,如果找到消息,獲取消息并返回,進行 消息處理.如果未找到消息,執(zhí)行6.2.3 6.2.3 檢查窗口需要重新繪制的范圍,如果 發(fā)現(xiàn)存在重新繪制的范圍,會產生WM_PAINT消息. 然后進行消息處理, 如果未找,執(zhí)行6.2.4 6.2.4 檢查WM_TIMER定時器消息,如果發(fā)現(xiàn) 存在已經到時的定時器,會產生WM_TIMER消息. 進行消息處理. 如果未找,執(zhí)行6.2.5 6.2.5 執(zhí)行內存管理工作. 6.2.6 根據函數(shù)不同,處理結果不同: GetMesssage - 阻塞,等候下一條消息 PeekMessage - 讓出控制權,交給后面的代碼執(zhí)行. 7 消息發(fā)送 7.1 消息發(fā)送分兩種 發(fā)送(Send)消息 - 直接發(fā)送給指定的窗口,并 等候結果. 投遞(Post)消息 - 發(fā)送到消息隊列當中,立刻 返回,由消息循環(huán)處理. 7.2 PostMessage和SendMessage PostMessage產生隊列消息,由于發(fā)送后不等候 消息處理結果,所以不能確定消息是否被處理 成功. SendMessage產生非隊列消息,可以確定消息是否 成功. 二 WM_PAINT消息 1 WM_PAINT的產生 由于窗口的互相覆蓋等,產生需要繪制 的區(qū)域,那么會產生WM_PAINT消息. 一般情況下,不直接發(fā)送WM_PAINT消息,通過API 聲明需要繪制區(qū)域,來產生WM_PAINT消息. 例如,可以使用InvalidateRect聲明一個需要重新 繪制的區(qū)域. 2 WM_PAINT的注意點 2.1 如果一個消息隊列中,有多個WM_PAINT消息, 只有最后一個WM_PAINT消息會被處理. 2.2 WM_PAINT消息處理中,要清空需要被繪制的 區(qū)域. BeginPaint 3 WM_PAINT的使用 3.1 WM_PAINT開始時,必須調用BeginPaint 3.2 繪制圖形 3.3 WM_PAINT處理后,必須調用EndPaint 三 鍵盤消息 1 鍵盤消息 按鍵消息 WM_KEYDOWN 當鍵被按下時產生 WM_KEYUP 當鍵被釋放時產生 WM_SYSKEYDOWN 當系統(tǒng)鍵被按下時產生 ALT/F10 WM_SYSKEYUP 當系統(tǒng)鍵釋放時產生 字符消息 WM_CHAR 當有字符鍵被按下時產生 TranslateMessage會將WM_KEYDOWN消息中, 可以顯示的按鍵,轉換成WM_CHAR的消息 2 消息參數(shù) WPARAM - 虛擬鍵碼 LPARAM - 相關的按鍵信息. 3 消息的使用 3.1 當有按鍵消息時,首先進入系統(tǒng)消息隊列, 然后別程序的消息循環(huán)獲取. 3.2 消息的處理 4 鍵盤消息的順序 對于可顯示字符: …… |
|
|