windows消息循环标准实例

来源:互联网 发布:style js order-color 编辑:程序博客网 时间:2024/06/05 20:38
#include <windows.h> LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); int WINAPI WinMain(HINSTANCE hINstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow) { static char szAppName[]="xianshi"; HWND hwnd; MSG msg; WNDCLASS wndclass; if(! hPrevInstance) { 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=(HBRUSH)GetStockObject(LTGRAY_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; RegisterClass(&wndclass); } hwnd=CreateWindow( szAppName, "The XianShi", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, NULL, NULL, hINstance, NULL); ShowWindow(hwnd,nCmdShow); UpdateWindow(hwnd); while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg);} return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc;PAINTSTRUCT ps; RECT rect; static LOGFONT lf; HFONT hnewFont;//**********HFONT holdFont;//**********switch(message) { case WM_CREATE: return 0; case WM_PAINT: lf.lfHeight=-64; lf.lfWeight=500; lf.lfPitchAndFamily=DEFAULT_PITCH & FF_DONTCARE; lf.lfCharSet=GB2312_CHARSET; strcpy(lf.lfFaceName,"黑体"); hnewFont=CreateFontIndirect(&lf); hdc=BeginPaint(hwnd,&ps); GetClientRect(hwnd,&rect); GetClientRect(hwnd,&rect); holdFont=(HFONT)SelectObject(hdc,hnewFont); SetTextColor(hdc,RGB(255,0,0)); SetBkColor(hdc,RGB(255,255,0)); DrawText(hdc, "VC中显示字体与背景", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); SelectObject(hdc,holdFont); DeleteObject(hnewFont); EndPaint(hwnd,&ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd,message,wParam,lParam); }

一 Windows中有一个系统消息队列,对于每一个正在执行的Windows应用程序,系统为其建立一个“消息队列”,即应用程序队列,用来存放该程序可能创建的各种窗口的消息。应用程序中含有一段称作“消息循环”的代码,用来从消息队列中检索这些消息并把它们分发到相应的窗口函数中。

o_windowsmessage2.jpg

二 Windows为当前执行的每个Windows程序维护一个「消息队列」。在发生输入事件之后,Windows将事件转换为一个「消息」并将消息放入程序的消息队列中。程序通过执行一块称之为「消息循环」的程序代码从消息队列中取出消息:
while(GetMessage (&msg, NULL, 0, 0))       
{        
    TranslateMessage (&msg) ;        
    DispatchMessage (&msg) ;       
}

msg变量是型态为MSG的结构,型态MSG在WINUSER.H中定义如下:
typedef struct tagMSG       
{       
    HWND   hwnd ;        
    UINT   message ;        
    WPARAM wParam ;        
    LPARAM lParam ;        
    DWORD  time ;        
    POINT  pt ;       
}       
MSG, * PMSG ;
      
POINT数据型态也是一个结构,它在WINDEF.H中定义如下:
typedef struct tagPOINT       
{       
    LONG  x ;       
    LONG  y ;       
}       
POINT, * PPOINT;
TranslateMessage(&msg); 将msg结构传给Windows,进行一些键盘转换。(关于这一点,我们将在第六章中深入讨论。)
DispatchMessage(&msg);又将msg结构回传给Windows。然后,Windows将该消息发送给适当的窗口消息处理程序,让它进行处理。这也就是说,Windows将呼叫窗口消息处理程序。在HELLOWIN中,这个窗口消息处理程序就是WndProc函数。处理完消息之后,WndProc传回到Windows。此时,Windows还停留在DispatchMessage呼叫中。在结束DispatchMessage呼叫的处理之后,Windows回到HELLOWIN程序中,并且接着从下一个GetMessage呼叫开始消息循环。
        
三 队列化消息与非队列化消息
    
消息能够被分为「队列化的」和「非队列化的」。队列化的消息是由Windows放入程序消息队列中的。在程序的消息循环中,重新传回并分配给窗口消息处理程序。非队列化的消息在Windows呼叫窗口时直接送给窗口消息处理程序。也就是说,队列化的消息被「发送」给消息队列,而非队列化的消息则「发送」给窗口消息处理程序。任何情况下,窗口消息处理程序都将获得窗口所有的消息--包括队列化的和非队列化的。窗口消息处理程序是窗口的「消息中心」。

队列化消息基本上是使用者输入的结果,以击键(如WM_KEYDOWN和WM_KEYUP消息)、击键产生的字符(WM_CHAR)、鼠标移动(WM_MOUSEMOVE)和鼠标按钮(WM_LBUTTONDOWN)的形式给出。队列化消息还包含时钟消息(WM_TIMER)、更新消息(WM_PAINT)和退出消息(WM_QUIT)。

非队列化消息则是其它消息。在许多情况下,非队列化消息来自呼叫特定的Windows函数。例如,当WinMain呼叫CreateWindow时,Windows将建立窗口并在处理中给窗口消息处理程序发送一个WM_CREATE消息。当WinMain呼叫ShowWindow时,Windows将给窗口消息处理程序发送WM_SIZE和WM_SHOWWINDOW消息。当WinMain呼叫UpdateWindow时,Windows将给窗口消息处理程序发送WM_PAINT消息。键盘或鼠标输入时发出的队列化消息信号,也能在非队列化消息中出现。例如,用键盘或鼠标选择了一个菜单项时,键盘或鼠标消息就是队列化的,而说明菜单项已选中的WM_COMMAND消息则可能就是非队列化的。

四 SendMessage()与PostMessage()之间的区别是什么?
它们两者是用于向应用程序发送消息的。PostMessagex()将消息直接加入到应用程序的消息队列中,不等程序返回就退出;而SendMessage()则刚好相反,应用程序处理完此消息后,它才返回。我想下图能够比较好的体现这两个函数的关系:

o_postmessage.gif


五 函数peekmessage和getmessage的区别?

两个函数主要有以下两个区别:
1.GetMessage将等到有合适的消息时才返回,而PeekMessage只是撇一下消息队列。
2.GetMessage会将消息从队列中删除,而PeekMessage可以设置最后一个参数wRemoveMsg来决定是否将消息保留在队列中。


原创粉丝点击