#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("rect demo"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if(!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("Register failure..."), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, szAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if(msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static int cxClient, cyClient; HDC hdc; PAINTSTRUCT ps; TCHAR buffer[5]; static int i; RECT rect;
switch(message) { case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); i = 0; return 0;
case WM_PAINT: hdc = GetDC(hwnd); GetClientRect(hwnd, &rect); DrawText(hdc, buffer, wsprintf(buffer, "%5d",i++), &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); ReleaseDC(hwnd, hdc); return 0;
case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }
Peekmessage和Getmessage都是向系统的消息队列中取得消息,不过性质不同。 若第一次向消息队列中取不到消息,则程序的主线程会被OS(操作系统)挂起;等到OS重新调度到该线程时,而且消息队列仍然是空的时,两者的性质不同: 若使用Getmessage(),则程序的主线程会仍被OS挂起。 若是用Peekmessage(),则程序会取得OS控制权,运行一段时间。此函数多用于处理系统的空闲时间。 getmessage and peekmessage are both get the message from send_message queue. getmessage supports 同步机制。PEEKMESSAGE SUPPORTS 异步机制。
从原因上而言:GetMessage函数从消息队列中得到消息后并在队列中删除该消息 PeekMessage函数从消息队列中得到消息后并不在队列中删除该消息 从结果上而言:GetMessage等待一个消息(就像_getch),直到拿到消息才返回 PeekMessage不是这样(就像_kbhit),查询消息队列,有就取,即使没有也立即返回。 为了实现windows的多任务,要用getmessage,因为当getmessage发现自己的消息队列里没有消息时,就会把控制权交还给系统,这样就可以让避免资源的浪费。
GetMessage函数每次调用是肯定会取回一个消息的,当消息队列为空的时候此进程会被挂起直到消息队列中有消息可取为止。 PeekMessage函数不管消息队列中是否有消息都会立即返回,返回是可以从返回的值里判断是否取到了消息,准确地说此函数是询问了一下消息队列,至于取回消息后是否从消息队列中删除此消息,由参数可以指定。 Windows3.1时很多应用程序的消息队列是由GetMessage函数构成的,而Win32以后大多数的应用程序的消息队列是由 PeekMessage函数构成的,vc和bcb好像都是这样的,基于Win32的抢先式多任务处理机制,采用PeekMessage函数构成的消息循环也不会对系统造成什么威胁。
1.PeekMessage
函数功能:该函数为一个消息检查线程消息队列,并将该消息(如果存在)放于指定的结构。 函数原型:BOOL PeekMessage(LPMSG IpMsg,HWND hWnd,UINT wMSGfilterMin,UINT wMsgFilterMax,UINT wRemoveMsg); 参数: lpMsg:接收消息信息的MSG结构指针。 hWnd:其消息被检查的窗口的句柄。 wMsgFilterMin:指定被检查的消息范围里的第一个消息。 wMsgFilterMax:指定被检查的消息范围里的最后一个消息。 wRemoveMsg:确定消息如何被处理。此参数可取下列值之一: PM_NOREMOVE:PeekMessage处理后,消息不从队列里除掉。 PM_REMOVE:PeekMessage处理后,消息从队列里除掉。 可将PM_NOYIELD随意组合到PM_NOREMOVE或PM_REMOVE。此标志使系统不释放等待调用程序空闲的线程。 缺省地,处理所有类型的消息。若只处理某些消息,指定一个或多个下列值: PM_QS_INPUT:Windows NT5.0和Windows 98:处理鼠标和键盘消息。 PM_QS_PAINT:Windows NT 5.0和Windows 98:处理画图消息。 PM_QS_POSTMESSAGE:Windows NT 5.0和Windows 98:处理所有被寄送的消息,包括计时器和热键。 PM_QS_SENDMESSAGE:Windows NT 5.0和Windows 98:处理所有发送消息。 返回值:如果消息可得到,返回非零值;如果没有消息可得到,返回值是零。 备注:和函数GetMessage不一样的是,函数PeekMesssge在返回前不等待消息被放到队列里。 PeekMesssge只得到那些与参数hWnd标识的窗口相联系的消息或被lsChild确定为其子窗口相联系的消息,并且该消息要在由参数wMsgFiterMin和wMsgFiherMax确定的范围内。如果hWnd为NULL,则PeekMessage接收属于当前调用线程的窗口的消息(PeekMessage不接收属于其他线程的窗口的消息)。如果hWnd为C1,PeekMessage只返回hWnd值为NULL的消息,该消息由函数PostThreadMessage寄送。如果wMsgFilterMin和wMsgFilterMax都为零,GetMessage返回所有可得的消息(即,无范围过滤)。 常数WM_KEYFIRST和WMKEYLAST可作为过滤值取得所有键盘消息;常数WM_MOUSEFIRST和WM_MOUSELAST可用来接收所有的鼠标消息。 PeekMessage通常不从队列里清除WM_PAINT消息。该消息将保留在队列里直到处理完毕。但如果WM_PAINT消息有一个空更新区,PeekMessage将从队列里清除WM_PAINT消息。
2.PeekMessage和GetMessage的区别 a.GetMessage将等到有合适的消息时才返回,而PeekMessage只是撇一下消息队列. b.GetMessage会将消息从队列中删除,而PeekMessage可以设置最后一个参数wRemoveMsg来决定是否将消息保留在队列中.
|