本站首页    管理页面    写新日志    退出


«July 2025»
12345
6789101112
13141516171819
20212223242526
2728293031


公告

☆★☆★☆★☆★☆★☆
生活的点点记录,以及一些体会...........

喜欢是淡淡的爱,爱是深深的喜欢.

时间会见证一切.......................

欢迎大家指出错误,共同进步..........

期待中..............................

☆★☆★☆★☆★☆★☆


我的分类(专题)

日志更新

最新评论

留言板

链接

世纪音频

 

 


Blog信息
blog名称:
日志总数:162
评论数量:312
留言数量:0
访问次数:940608
建立时间:2005年5月17日




[work]Windows消息处理机制
文章收藏

oceanblue 发表于 2008/11/11 22:23:22

消息队列中的本窗口大量消息并不会被自动取出,也没有自动地调用WinProc函数对消息加以处理,但是,Window系统提供了三个API函数给我们,让我们自己去完成这件事。看吧!GetMessage( …);TranslateMessage(…);DispatchMessage(…);    下面就让我分别对这三个函数解释解释。1 GetMessage( …)原型如下:BOOL GetMessage(    LPMSG lpMsg,    HWND hWnd ,    UINT wMsgFilterMin,    UINT wMsgFilterMax);功能:这个API函数用来从消息队列中“摘取”一个消息信息放到lpMsg所指的变量里。(注:如果所取窗口的消息队列中没有消息,则程序会暂停在GetMessage(…) 函数里,不会返回。)参数及返回值:    LPMSG lpMsg:是传出参数。消息结构MSG的指针。如果该函数执行成功,则从消息队列中“摘”取的一个消息信息会放入lpMsg所指的MSG结构变量中。    在Winuser.h中有定义如下:typedef struct tagMSG {    HWND        hwnd;    UINT        message;    WPARAM      wParam;    LPARAM      lParam;    DWORD       time;    POINT       pt;} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;    其中的成员变量message里才是我所说的WM_SIZE、WM_COMMAND、WM_QUIT等等消息标识。    hwnd中是这个消息所在的窗口句柄。    好了,其它成员变量我就暂时省略不说。    HWND hWnd:传入参数。你要获取你程序中哪个窗口的消息,那就把相应的窗口句柄代入其中。    UINT wMsgFilterMin,UINT wMsgFilterMax:这两个参数我就不介绍。你只要用0值代入就可了。    返回值:如果取的是WM_QUIT消息,则返回值为0,如果取的是其它消息,返回值为非0值。WM_QUIT消息是退出程序的消息。当我们想让程序退出时,我们就可以发一个WM_QUIT消息,让GetMessage返回0值。2 TranslateMessage(…)    原型:BOOL TranslateMessage( CONST MSG *lpMsg);    功能:对GetMessage取得的MSG消息结构中的信息进行必要的预处理(你可不用管它做了什么。)。    参数:    CONST MSG *lpMsg:它是用来对你取的消息结构MSG变量进行必要的预处理。GetMessage函数取得的消息,要经过TranslateMessage处理一下,然后才可以传给DispatchMessage函数,因此,TranslateMessage必放在GetMessage与DispatchMessage之间。    返回值:它虽然有一个返回值,我们总是忽略它,所以我也就不说了。3 DispatchMessage(…)    原型: LONG DispatchMessage( CONST MSG *lpMsg);    功能:用来完成调用WinPro回调函数并把由GetMessage取得的消息结构MSG变量中的信息传递给WinPro回调函数:(原型如下)    参数及返回值:    MSG *lpMsg :传入参数,MSG消息结构体类型指针,指向你已经取出的消息结构体变量。    返回值:同上,我们总是忽略它。四 Come on,行动起来吧!    看我添加的代码(粗体部分):LRESULT CALLBACK WinProc(HWND hwnd,                         UINT msg,                         WPARAM wparam,                         LPARAM lparam){//这里可以添加你的消息处理代码   return DefWindowProc(hwnd, msg, wparam, lparam);}int WINAPI WinMain(HINSTANCE hinstance,                  HINSTANCE hprevinstance,                 LPSTR lpcmdline,                 int ncmdshow){       HWND hWnd;    MSG msg;    WNDCLASSEX wndclass;     //……  这里省略了前面所述的注册窗口类的过程   //    hWnd=CreateWindowEx(NULL,WND_CLS_NAME,                "这是我的第一个窗口",                WS_OVERLAPPEDWINDOW|WS_VISIBLE ,                CW_USEDEFAULT, 0,                400,400,                NULL,                NULL,                hinstance,                NULL );    if (!hWnd)        return 0;    ShowWindow(hWnd, ncmdshow);       while(GetMessage(&msg, NULL, 0, 0)) //获取一个消息,成功后会放在msg中。    {             TranslateMessage(&msg); //消息进行必要的处理转换。            DispatchMessage(&msg); //调用WinProc,将msg的各项信息传递给WinProc    }   return 0;    }    看清楚了:这是一个消息循环。只有当GetMessage(…)收到一个WM_QUIT时返回0值,程序才会退出。五 程序流程分析(粗体部分)    1. 当用户进行如调整窗口大小,移动窗口位置等等的操作时。会产生不同的消息。(当然包括了ShowWindow( )函数产生的若干个消息。    2. Window系统会将这些消息排入本线程的消息队列中。(在操作系统中完成)    3. 只要该窗口消息队列中有消息,我们的GetMessage(&msg,NULL,0,0)就会从消息队列中摘取一个消息的信息,填入msg结构体变量中,如果不是WM_QUIT则返回非零值,就执行循环体。(注意:如果消息队列中没有任何消息可取时,则程序会停在GetMessage函数里,直到消息队列中有了消息,GetMessage函数才会取一个消息信息并返回。)    4. 用TranslateMessage(&msg)对msg中的数据进行预处理(你先不必知道它具体做了什么,但不要忘记这个函数。)。    5. 然后是调用DespatchMessage(&msg),这个函数里会调用WinProc,并将msg中的数据通过WinProc的参数传递给WinProc;    6. 程序转入执行WinProc回调函数体内的代码。    7. 看代码处,WinProc此时只有一句 return DefWindowProc(hwnd, msg, wparam, lparam);这里,我们只是将WinProc传入的参数原样地传给了API函数DefWindowProc。所有的消息都让DefWindowProc进行缺省默认的处理。(你不用理会DefWindowProc都做了些什么。)    8. DefWindowProc完成一个消息处理后,返回消息处理的结果。    9. 我们的WinProc也原样地将DefWindowProc返回值返回。    10. WinProc执行完成后,程序又返回到DispatchMessage(&msg)函数体内。(因为是在DispathMessage( )中调用WinProc的。)    11. 退出DispatchMessage(&msg);函数后程序又执行下一个循环。即while(GetMessage(&msg, NULL, 0, 0))     又取下一个消息,进行下一个消息的处理。    12. 直到GetMessage “摘取”到了退出程序的消息WM_QUIT,返回零值,退出循环,结束程序。    (哦,整个流程是通过我们的程序与Window系统相互协作来完成的。你可要多加理解罗!)六 调试这个程序    不设任何断点,按F5运行程序,    看来一切正常。可以移动窗口;可以调整窗口大小;可以最大化最小化;总之可以进行窗口的基本的操作了。(这些动作都是由DefWindowProc来完成的噢!)    哈!我们可是渐入佳境啦!这就是Window系统消息处理机制带给我们的成果。    不过……只是……有一个问题。    你有没有注意到,点击窗口右上角的关闭按钮时,窗口是关闭了,但程序并没有退出(看来点击关闭按钮时并没有产生WM_QUIT的消息。)。    你只能点击VC菜单的:Debug->Stop Debugging来退出程序了。   (欲知此为如何,请听下回分解!) 


阅读全文(2711) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.031 second(s), page refreshed 144755725 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号