转自 http://blog.csdn.net/blueln/article/details/7631096
1.消息的结构
为了从消息队列获取消息信息,需要使用MSG结构。例如,::GetMessage函数(从消息队列得到消息并从队列中移走)和::PeekMessage函数(从消息队列得到消息但是可以不移走)都使用了该结构来保存获得的消息信息。
MSG结构的定义如下:
- typedef struct tagMSG { // msg
- HWND hwnd;
- UINT message;
- WPARAM wParam;
- LPARAM lParam;
- DWORD time;
- POINT pt;
- } MSG;
该结构包括了六个成员,用来描述消息的有关属性:
接收消息的窗口句柄、消息标识(ID)、第一个消息参数、第二个消息参数、消息产生的时间、消息产生时鼠标的位置。
2.应用程序通过窗口过程来处理消息
每个“窗口类”都要登记一个如下形式的窗口过程
- LRESULT CALLBACK MainWndProc (
- HWND hwnd,// 窗口句柄
- UINT msg,// 消息标识
- WPARAM wParam,//消息参数1
- LPARAM lParam//消息参数2
- )
应用程序通过窗口过程来处理消息:非队列消息由Windows直接送给目的窗口的窗口过程,队列消息由::DispatchMessage等派发给目的窗口的窗口过程。窗口过程被调用时,接受四个参数:
a window handle(窗口句柄);
a message identifier(消息标识);
two 32-bit values called message parameters(两个32位的消息参数);
需要的话,窗口过程用::GetMessageTime获取消息产生的时间,用::GetMessagePos获取消息产生时鼠标光标所在的位置。
在窗口过程里,用switch/case分支处理语句来识别和处理消息。
3.应用程序通过消息循环来获得对消息的的处理
每个GDI应用程序在主窗口创建之后,都会进入消息循环,接受用户输入、解释和处理消息。
消息循环的结构如下:
- while (GetMessage(&msg, (HWND) NULL, 0, 0)) {//从消息队列得到消息
- if (hwndDlgModeless == (HWND) NULL ||
- !IsDialogMessage(hwndDlgModeless, &msg) &&
- !TranslateAccelerator(hwndMain, haccel, &msg)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg); //发送消息
- }
- }
消息循环从消息队列中得到消息,如果不是快捷键消息或者对话框消息,就进行消息转换和派发,让目的窗口的窗口过程来处理。
当得到消息WM_QUIT,或者::GetMessage出错时,退出消息循环。
4.MFC消息处理
使用MFC框架编程时,消息发送和处理的本质也如上所述。但是,有一点需要强调的是,所有的MFC窗口都使用同一窗口过程,我们不必去设计和实现自己的窗口过程,而是通过MFC提供的一套消息映射机制来处理消息。因此,MFC简化了我们编程时处理消息的复杂性。
所谓消息映射,简单地讲,就是让我们指定要某个MFC类(有消息处理能力的类)处理某个消息。MFC提供了工具ClassWizard来帮助实现消息映射,在处理消息的类中添加一些有关消息映射的内容和处理消息的成员函数。我们将完成消息处理函数,实现所希望的消息处理能力。
如果派生类要覆盖基类的消息处理函数,就用ClassWizard在派生类中添加一个消息映射条目,用同样的原型定义一个函数,然后实现该函数。这个函数覆盖派生类的任何基类的同名处理函数。
浙公网安备 33010602011771号