本文主要介紹幾種Windows常見的訊息的處理,在《Win32 SDK基礎(8)- Windows訊息機制》中,我們介紹了WM_CREATE訊息的處理,在視窗建立之前,我們利用訊息處理函數彈出了一個MessageBox,本文在此基礎之上,介紹WM_DESTROY、WM_SYSCOMMAND、WM_QUIT、WM_SIZE等其它常見的Windows訊息。首先,我們引進在《Win32 SDK基礎(8)- Windows訊息機制》文中的程式碼,後續的實驗都在此程式碼的基礎之上。
#include "stdafx.h" #include "MessageTs.h" HINSTANCE g_hInstance = 0; //窗口处理函数 LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: PostQuitMessage(0);//可以使GetMessage返回0 break; case WM_CREATE: MessageBox(NULL,"WM_CREATE消息被处理了","消息处理",MB_OK); default: break; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } //注册窗口类 BOOL Register(LPSTR lpClassName, WNDPROC wndProc) { WNDCLASSEX wce = { 0 }; wce.cbSize = sizeof(wce); wce.cbClsExtra = 0; wce.cbWndExtra = 0; wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wce.hCursor = NULL; wce.hIcon = NULL; wce.hIconSm = NULL; wce.hInstance = g_hInstance; wce.lpfnWndProc = wndProc; wce.lpszClassName = lpClassName; wce.lpszMenuName = NULL; wce.style = CS_HREDRAW | CS_VREDRAW; ATOM nAtom = RegisterClassEx(&wce); if (nAtom == 0) return FALSE; return true; } //创建主窗口 HWND CreateMain(LPSTR lpClassName, LPSTR lpWndName) { HWND hWnd = CreateWindowEx(0, lpClassName, lpWndName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, g_hInstance, NULL); return hWnd; } //显示窗口 void Display(HWND hWnd) { ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); } //消息循环 void Message() { MSG nMsg = { 0 }; while (GetMessage(&nMsg, NULL, 0, 0)) { TranslateMessage(&nMsg); DispatchMessage(&nMsg); } } int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { // TODO: Place code here. g_hInstance = hInstance; BOOL nRet = Register("Main", WndProc); if (!nRet) { MessageBox(NULL, "注册失败", "Infor", MB_OK); return 0; } HWND hWnd = CreateMain("Main", "window"); Display(hWnd); Message(); return 0; }
我們還是要再介紹下WM_CREATE訊息。因為在上一文中我們只透過彈出MessageBox驗證了WM_CREATE訊息的產生時機,卻沒有介紹它另外一個很重要的構成-WPARAM和LPARAM參數。我們在發送訊息時,往往可以透過這兩個參數攜帶一些訊息。 WM_CREATE訊息是我們在建立視窗時由系統自動發送的訊息,同樣也會利用這兩個參數來攜帶訊息。 LPARAM攜帶了我們建立視窗的CreateWindowEx的12個參數訊息,WPARAM沒有被使用,下面我們在處理WM_CREATE訊息時,在彈出的對話方塊上顯示視窗類別和視窗名稱。
//窗口处理函数 LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: PostQuitMessage(0);//可以使GetMessage返回0 break; case WM_CREATE: { CREATESTRUCT crt = *((CREATESTRUCT*)lParam); char buf[256] = {0}; sprintf(buf,"创建的窗口类名称是%s,窗口名称是%s",crt.lpszClass,crt.lpszName); MessageBox(NULL, buf, "消息处理", MB_OK); } default: break; } return DefWindowProc(hWnd, uMsg, wParam, lParam); }
運行程序,我們發現在視窗建立之前我們成功捕獲了視窗的註冊視窗類別名稱和視窗名稱,並在對話框上顯示出來:
這訊息在先前的文章中我們其實早已經解除過。他是Windows視窗關閉時發送的一個訊息,簡單點說就是,當你點擊Windows視窗的關閉按鈕時,會發出這個訊息。我們在之前的程式碼中,處理這個訊息的操作是PostQuitMessage(0),這其實是我們發送了一個接下來要介紹的WM_QUIT訊息用來結束程式的進程。 WM_DESTORY訊息的LPARAM和WPARAM都沒被使用,它一般被用來做一些視窗關閉前資源的回收和記憶體的釋放工作等等,我們呼叫的PostQuitMessage(0)就是一個很常見的用法。
前面我們已經介紹過,這是我們使用PostQuitMessage(0)傳送的一個訊息,用來結束程式進程,它的WMPARAM是PostQuitMessage中傳遞的參數,LPARAM參數未被使用。通常情況下我們發送了WM_QUIT後,會引起訊息循環中的GetMessage函數返回,從而使得進程退出。 WM_QUIT訊息是無法傳遞到我們自己的視窗處理函數中的。但是我們可以從側面驗證有這麼一個訊息:我們先在程式碼中增加對WM_QUIT訊息的處理。
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DESTROY: PostQuitMessage(0);//可以使GetMessage返回0 break; case WM_CREATE: { CREATESTRUCT crt = *((CREATESTRUCT*)lParam); char buf[256] = {0}; sprintf(buf,"创建的窗口类名称是%s,窗口名称是%s",crt.lpszClass,crt.lpszName); MessageBox(NULL, buf, "消息处理", MB_OK); } case WM_QUIT: { int param = (int)wParam; char buf[256]; sprintf(buf, "进程退出,退出码:%d", param); MessageBox(NULL, buf, "消息处理", MB_OK); } default: break; } return DefWindowProc(hWnd, uMsg, wParam, lParam); }
執行程序,在關閉處理WM_CREATE訊息的對話方塊後,發現彈出了我們驗證WM_QUIT訊息的對話方塊。
這是因為,則由彈出的處理WM_CREATE訊息MessageBox也是一個視窗,但它屬於我們的流程。每個視窗都有一個訊息循環,但是訊息佇列一個行程卻只有一個,當MessageBox的視窗關閉時,它的視窗處理函數也呼叫PostQuitMessage(0)傳送了一個WM_QUIT訊息。它的訊息循環中GetMessage接收到WM_QUIT訊息後返回並退出。而這個消息又會被我們的消息循環捕獲到,但是由於它不是我們的窗口發出的消息,所以不會導致我們的GetMessage返回結束循環,反而被傳給我們的窗口處理函數匯總進行處理,所以出現了上面截圖顯示的對話框。
系統指令訊息,當我們點選最大化、最小化和關閉指令時會觸發這個訊息(這麼說來點選關閉按鈕時會同時觸發WM_DESTROY和WM_SYSCOMMAND兩個消息哦)。它的wParam參數攜帶了具體的視窗操作:
關閉:SC_CLOSE
最大化: SC_MAXIMIZE
最小化:SC_MINIMIZE
这里只列举了三种常见的WM_SYSCOMMAND携带的参数宏,其它的可以参照MSDN。WM_SYSCOMMAND的lParam携带的是产生该消息的鼠标的位置,位置的X和Y坐标分别被存放在lParam的低位和高位字中,我们用下面的代码来验证在窗口最大化时,我们鼠标的位置:
case WM_SYSCOMMAND: { if (wParam == SC_MAXIMIZE) { short x = LOWORD(lParam); short y = HIWORD(lParam); char buf[256]; sprintf(buf, "窗口最大化,x坐标:%d,y坐标:%d", x,y); MessageBox(NULL, buf, "消息处理", MB_OK); } }
当我们点击窗口的最大化按钮时,出现下面的提示:
每当我们调整窗口的大小时,都会触发WM_SIZE消息。它的wParam参数携带的是该消息产生的原因:
SIZE_RESTORED —— 重新调整窗口大小
SIZE_MAXIMIZED —— 最大化显示
SIZE_ MINIMIZED —— 最小化显示
其他参数宏详见MSDN
它的lParam参数携带的是重新调整大小后的窗口的高和宽,其中低字节代表宽,高字节代表高,这里我们通过代码验证,当窗口最大化后窗口的高和宽:
case WM_SIZE: { if (wParam == SIZE_MAXIMIZED) { short width = LOWORD(lParam); short hight = HIWORD(lParam); char buf[256]; sprintf(buf, "窗口最大化,高度:%d,宽度:%d", hight, width); MessageBox(NULL, buf, "消息处理", MB_OK); } }
运行程序,最大化时可以显示最大化后的窗口高度和宽度:
以上是Win32 SDK基礎(十)之詳解幾種常見的Windows訊息處理的範例程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!