Windows程序消息机制浅析
1、消息
消息是由MSG结构体来表示的。如下:
1 typedef struct tagMSG { 2 HWND hwnd; 3 UINT message; 4 WPARAM wParam; 5 LPARAM lParam; 6 DWORD time; 7 POINT pt; 8 } MSG
2、WinMain函数的定义
WinMain函数的原型声明如下:
1 int WINAPI WinMain( 2 HINSTANCE hInstance, // handle to current instance 3 HINSTANCE hPrevInstance, // handle to previous instance 4 LPSTR lpCmdLine, // command line 5 int nCmdShow // show state 6 );
3、窗口的创建:设计一个窗口类、注册窗口类、创建窗口、显示及更新窗口。
设计一个窗口:WNDCLASS结构体的定义如下:
1 typedef struct _WNDCLASS { 2 UINT style; 3 WNDPROC lpfnWndProc; 4 int cbClsExtra; 5 int cbWndExtra; 6 HINSTANCE hInstance; 7 HICON hIcon; 8 HCURSOR hCursor; 9 HBRUSH hbrBackground; 10 LPCTSTR lpszMenuName; 11 LPCTSTR lpszClassName; 12 } WNDCLASS;
注册窗口类:注册函数的原型声明如下:
1 ATOM RegisterClass( 2 CONST WNDCLASS *lpWndClass // class data 3 );
创建窗口:CreateWindow函数的原型声明如下:
1 HWND CreateWindow( 2 LPCTSTR lpClassName, // registered class name 3 LPCTSTR lpWindowName, // window name 4 DWORD dwStyle, // window style 5 int x, // horizontal position of window 6 int y, // vertical position of window 7 int nWidth, // window width 8 int nHeight, // window height 9 HWND hWndParent, // handle to parent or owner window 10 HMENU hMenu, // menu handle or child identifier 11 HINSTANCE hInstance, // handle to application instance 12 LPVOID lpParam // window-creation data 13 );
更新及更新窗口:显示窗口ShowWindow函数的原型声明如下:
1 BOOL ShowWindow( 2 HWND hWnd, // handle to window 3 int nCmdShow // show state 4 );
更新及更新窗口:更新窗口UpdateWindow函数的原型声明如下:
1 BOOL UpdateWindow(HWND hWnd);
4、消息循环:不断从消息队列中取出消息,并进行响应。
1 BOOL GetMessage( 2 LPMSG lpMsg, // message information 3 HWND hWnd, // handle to window 4 UINT wMsgFilterMin, // first message 5 UINT wMsgFilterMax // last message 6 );
Windows应用程序消息处理机制如下图所示:
-
操作系统接收到应用程序的窗口消息,将消息投递到应用程序的消息队列中。
-
应用程序在消息循环中调用GetMessage函数从消息队列中取出一条一条的消息。取出消息后,应用程序可以对消息进行一些预处理,例如,放弃对某些消息的响应,或者调用TranslateMessage产生新的消息。
-
应用程序调用DispatchMessage,将消息回传给操作系统。消息是由MSG结构体对象来表示的,其中就包含了接收消息的窗口的句柄。因此,DispatchMessage函数总能进行正确的传递。
-
系统利用WNDCLASS结构体的lpfnWndProc成员保存的窗口过程函数的指针调用窗口过程,对消息进行处理(即“系统给应用程序发送了消息”)。
5、编写窗口过程函数:窗口过程函数的声明形式如下:
1 LRESULT CALLBACK WindowProc( 2 HWND hwnd, // handle to window 3 UINT uMsg, // message identifier 4 WPARAM wParam, // first message parameter 5 LPARAM lParam // second message parameter 6 );
提示:系统通过窗口过程函数的地址(指针)来调用窗口过程函数,而不是名字。
例:WinMain.cpp
1 #include <windows.h> 2 #include <stdio.h> 3 4 LRESULT CALLBACK WinSunProc( 5 HWND hwnd, // handle to window 6 UINT uMsg, // message identifier 7 WPARAM wParam, // first message parameter 8 LPARAM lParam // second message parameter 9 ); 10 11 int WINAPI WinMain( 12 HINSTANCE hInstance, // handle to current instance 13 HINSTANCE hPrevInstance, // handle to previous instance 14 LPSTR lpCmdLine, // command line 15 int nCmdShow // show state 16 ) 17 { 18 WNDCLASS wndcls; 19 wndcls.cbClsExtra=0; 20 wndcls.cbWndExtra=0; 21 wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); 22 wndcls.hCursor=LoadCursor(NULL,IDC_CROSS); 23 wndcls.hIcon=LoadIcon(NULL,IDI_ERROR); 24 wndcls.hInstance=hInstance; 25 wndcls.lpfnWndProc=WinSunProc; 26 wndcls.lpszClassName="bedrock32"; 27 wndcls.lpszMenuName=NULL; 28 wndcls.style=CS_HREDRAW | CS_VREDRAW; 29 RegisterClass(&wndcls); 30 31 HWND hwnd; 32 hwnd=CreateWindow("bedrock32","http://www.cnblogs.com/bedrock32",WS_OVERLAPPEDWINDOW, 33 0,0,600,400,NULL,NULL,hInstance,NULL); 34 35 ShowWindow(hwnd,SW_SHOWNORMAL); 36 UpdateWindow(hwnd); 37 38 MSG msg; 39 while(GetMessage(&msg,NULL,0,0)) 40 { 41 TranslateMessage(&msg); 42 DispatchMessage(&msg); 43 } 44 return msg.wParam; 45 } 46 47 LRESULT CALLBACK WinSunProc( 48 HWND hwnd, // handle to window 49 UINT uMsg, // message identifier 50 WPARAM wParam, // first message parameter 51 LPARAM lParam // second message parameter 52 ) 53 { 54 switch(uMsg) 55 { 56 case WM_CHAR: 57 char szChar[20]; 58 sprintf(szChar,"char code is %d",wParam); 59 MessageBox(hwnd,szChar,"char",0); 60 break; 61 case WM_LBUTTONDOWN: 62 MessageBox(hwnd,"mouse clicked","message",0); 63 HDC hdc; 64 hdc=GetDC(hwnd); 65 TextOut(hdc,0,50,"我是高手",strlen("我是高手")); 66 //ReleaseDC(hwnd,hdc); 67 break; 68 case WM_PAINT: 69 HDC hDC; 70 PAINTSTRUCT ps; 71 hDC=BeginPaint(hwnd,&ps); 72 TextOut(hDC,0,0,"http://www.cnblogs.com/bedrock32",strlen("http://www.cnblogs.com/bedrock32")); 73 EndPaint(hwnd,&ps); 74 break; 75 case WM_CLOSE: 76 if(IDYES==MessageBox(hwnd,"是否真的结束?","message",MB_YESNO)) 77 { 78 DestroyWindow(hwnd); 79 } 80 break; 81 case WM_DESTROY: 82 PostQuitMessage(0); 83 break; 84 default: 85 return DefWindowProc(hwnd,uMsg,wParam,lParam); 86 } 87 return 0; 88 }