消息處理html
例子:窗口點擊windows
好的,如今咱們已經獲得一個窗口了,但咱們什麼也作不了除了DefWindowProc()容許窗口大小被調整,最大最小化等。。。這不是很激動人心啊數組
在接下來的一小節中我將向你展現如何修改現有的程序,讓它作一些新的事情,這樣我就能夠告訴你,「處理消息而後這樣作。。。」,我會明白個人意思是什麼而且在不須要看完完整的栗子的基礎上完成它。因此無論怎樣,集中注意力緩存
OK,對初學者來講拿最近的一個窗口程序的代碼,保證編譯經過而且正常運行,而後你就能夠在這份代碼的基礎上進行一些小修改,或者把代碼複製到新的一個項目中進行修改。函數
咱們要添加一項功能,只要用戶點擊窗口,就顯示咱們程序的名字。這不是很激動人心,基本上是經過獲取處理消息的句柄實現的,讓咱們看看WndProc()中有什麼ui
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; }
若是咱們想處理鼠標點擊事件,咱們須要添加一個WM_LBUTTONDOWN的處理器(或者 WM_RBUTTONDOWN, WM_MBUTTONDOWN分別對應鼠標右擊和中擊)spa
若是我或其餘人提處處理一個消息,意思是在窗口類的WndProc()中添加相應的處理消息處理程序,以下所示:翻譯
1 LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 2 { 3 switch(msg) 4 { 5 case WM_LBUTTONDOWN: // <- 6 // <- 咱們只是添加了這個東西
7 break; // <-
8 case WM_CLOSE: 9 DestroyWindow(hwnd); 10 break; 11 case WM_DESTROY: 12 PostQuitMessage(0); 13 break; 14 default: 15 return DefWindowProc(hwnd, msg, wParam, lParam); 16 } 17 return 0; 18 }
你處理消息的順序是很重要的,確保你有在每一個case結尾加上break;,你能夠看到咱們在switch()中添加了另外一個case,如今咱們但願當代碼跑到這個的時候有些事情發生。指針
首先我會展現咱們要添加的代碼(向用戶顯示咱們程序的文件名),而後我會把這些代碼集合到咱們的程序中。接下來我可能只會向你展現這些代碼而且讓你本身集合到程序中去,這對我來講是好的由於不須要說太多廢話,對你來講也是好的,這樣你就能夠把代碼嵌入到任何你想加入的程序中去而不只僅只是我呈現給你們的這個栗子。若是你不肯定怎麼作,看看ZIP樣例代碼文件中關於這一小節的內容。code
1 GetModuleFileName(hInstance, szFileName, MAX_PATH); 2 MessageBox(hwnd, szFileName, "This program is:", MB_OK | MB_ICONINFORMATION);
如今這段代碼不能表明它自己,它不能被插入咱們舊代碼中的任何位置。咱們明確地想讓它在用戶點擊窗口時運行,因此這就是我想整合進咱們的骨骼程序中的一點代碼。
1 LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 2 { 3 switch(msg) 4 { 5 case WM_LBUTTONDOWN: 6 // BEGIN NEW CODE
7 { 8 char szFileName[MAX_PATH]; 9 HINSTANCE hInstance = GetModuleHandle(NULL); 10
11 GetModuleFileName(hInstance, szFileName, MAX_PATH); 12 MessageBox(hwnd, szFileName, "This program is:", MB_OK | MB_ICONINFORMATION); 13 } 14 // END NEW CODE
15 break; 16 case WM_CLOSE: 17 DestroyWindow(hwnd); 18 break; 19 case WM_DESTROY: 20 PostQuitMessage(0); 21 break; 22 default: 23 return DefWindowProc(hwnd, msg, wParam, lParam); 24 } 25 return 0; 26 }
注意花括號,當咱們在switch()中聲明一個新的變量的時候就須要加上花括號,這應該是C語言的基礎知識,但我想我應該指出你正在作的全部事情。
因此你添加那段代碼,而後編譯它,若是它正常運行,點擊窗口,而後你會看到一個現實你可執行文件的消息盒。
你會注意到在這裏添加了兩個變量,hInstance和szFileName。查閱一下GetModuleFileName()函數,你會發現第一個參數是一個HINSTANCE跟可執行模塊相關(咱們的程序,.exe可執行文件),咱們從哪裏獲得這個參數呢?答案是經過GetModuleHandle(),GetModuleHandle()的參考文獻中指明當傳入一個NULL時,會返回「建立調用進程的文件的句柄」,這剛好是咱們所須要的,剛纔提到的那個HINSTANCE。把這些信息都放在一塊兒咱們能夠獲得如下聲明:
1 HINSTANCE hInstance = GetModuleHandle(NULL);
如今輪到二次個參數,再次轉向咱們可靠的參考手冊,咱們能夠看到它是「一個指向接收指定的模塊的路徑和文件的緩衝區的指針」,數據類型是LPTSTR(或者LPSTR若是你的參考手冊是老的)。由於LPSTR跟char*是相同的咱們能夠像下面那樣聲明一個字符數組:
1 char szFileName[MAX_PATH];
MAX_PATH是一個經過<windows.h>頭文件中定義好的一個宏,這個宏用來定義存儲一個win32下的文件名的緩衝區的最大長度,咱們也把MAX_PATH傳遞給GetModuleFileName()這樣它就會知道緩衝區的大小。
在GetModuleFileName()被調用以後,szFileName變量的緩存將會被填充,填充的內容就是咱們可執行文件的文件名,咱們把這個值傳遞給MessageBox(),經過這個簡單的方式把它顯示給用戶。
若是你插入代碼後不能正常地運行,這裏是程序的完整的代碼提供參考,跟它進行對比而後看看會你哪些地方犯了錯誤。
1 #include <windows.h>
2
3 const char g_szClassName[] = "myWindowClass"; 4
5 LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 6 { 7 switch(msg) 8 { 9 case WM_LBUTTONDOWN: 10 { 11 char szFileName[MAX_PATH]; 12 HINSTANCE hInstance = GetModuleHandle(NULL); 13
14 GetModuleFileName(hInstance, szFileName, MAX_PATH); 15 MessageBox(hwnd, szFileName, "This program is:", MB_OK | MB_ICONINFORMATION); 16 } 17 break; 18 case WM_CLOSE: 19 DestroyWindow(hwnd); 20 break; 21 case WM_DESTROY: 22 PostQuitMessage(0); 23 break; 24 default: 25 return DefWindowProc(hwnd, msg, wParam, lParam); 26 } 27 return 0; 28 } 29
30 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 31 LPSTR lpCmdLine, int nCmdShow) 32 { 33 WNDCLASSEX wc; 34 HWND hwnd; 35 MSG Msg; 36
37 wc.cbSize = sizeof(WNDCLASSEX); 38 wc.style = 0; 39 wc.lpfnWndProc = WndProc; 40 wc.cbClsExtra = 0; 41 wc.cbWndExtra = 0; 42 wc.hInstance = hInstance; 43 wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); 44 wc.hCursor = LoadCursor(NULL, IDC_ARROW); 45 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 46 wc.lpszMenuName = NULL; 47 wc.lpszClassName = g_szClassName; 48 wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); 49
50 if(!RegisterClassEx(&wc)) 51 { 52 MessageBox(NULL, "Window Registration Failed!", "Error!", 53 MB_ICONEXCLAMATION | MB_OK); 54 return 0; 55 } 56
57 hwnd = CreateWindowEx( 58 WS_EX_CLIENTEDGE, 59 g_szClassName, 60 "The title of my window", 61 WS_OVERLAPPEDWINDOW, 62 CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, 63 NULL, NULL, hInstance, NULL); 64
65 if(hwnd == NULL) 66 { 67 MessageBox(NULL, "Window Creation Failed!", "Error!", 68 MB_ICONEXCLAMATION | MB_OK); 69 return 0; 70 } 71
72 ShowWindow(hwnd, nCmdShow); 73 UpdateWindow(hwnd); 74
75 while(GetMessage(&Msg, NULL, 0, 0) > 0) 76 { 77 TranslateMessage(&Msg); 78 DispatchMessage(&Msg); 79 } 80 return Msg.wParam; 81 }
PS.因爲本人英文水平所限,只能翻譯到這個程度了,有紕漏還望多多指出,附上本篇翻譯的英文原版教程地址:http://www.winprog.org/tutorial/window_click.html