MFC消息映射的实现.docx
- 文档编号:2124752
- 上传时间:2022-10-27
- 格式:DOCX
- 页数:16
- 大小:30.40KB
MFC消息映射的实现.docx
《MFC消息映射的实现.docx》由会员分享,可在线阅读,更多相关《MFC消息映射的实现.docx(16页珍藏版)》请在冰豆网上搜索。
MFC消息映射的实现
MFC之消息映射的实现
(1)
分类:
Window编程2012-01-0923:
3860人阅读评论(0)收藏举报
Windows应用程序的输入由Windows系统以消息的形式发送给应用程序的窗口。
这些窗口通过窗口过程来接收和处理消息,然后把控制返还给Windows。
1.消息的分类
1.队列消息和非队列消息
从消息的发送途径上看,消息分两种:
队列消息和非队列消息。
队列消息送到系统消息队列,然后到线程消息队列;非队列消息直接送给目的窗口过程。
这里,对消息队列阐述如下:
Windows维护一个系统消息队列(Systemmessagequeue),每个GUI线程有一个线程消息队列(Threadmessagequeue)。
鼠标、键盘事件由鼠标或键盘驱动程序转换成输入消息并把消息放进系统消息队列,例如WM_MOUSEMOVE、WM_LBUTTONUP、WM_KEYDOWN、WM_CHAR等等。
Windows每次从系统消息队列移走一个消息,确定它是送给哪个窗口的和这个窗口是由哪个线程创建的,然后,把它放进窗口创建线程的线程消息队列。
线程消息队列接收送给该线程所创建窗口的消息。
线程从消息队列取出消息,通过Windows把它送给适当的窗口过程来处理。
除了键盘、鼠标消息以外,队列消息还有WM_PAINT、WM_TIMER和WM_QUIT。
这些队列消息以外的绝大多数消息是非队列消息。
2.系统消息和应用程序消息
从消息的来源来看,可以分为:
系统定义的消息和应用程序定义的消息。
系统消息ID的范围是从0到WM_USER-1,或0X80000到0XBFFFF;应用程序消息从WM_USER(0X0400)到0X7FFF,或0XC000到0XFFFF;WM_USER到0X7FFF范围的消息由应用程序自己使用;0XC000到0XFFFF范围的消息用来和其他应用程序通信,为了ID的唯一性,使用:
:
RegisterWindowMessage来得到该范围的消息ID。
2.消息结构和消息处理
1.消息的结构
为了从消息队列获取消息信息,需要使用MSG结构。
例如,:
:
GetMessage函数(从消息队列得到消息并从队列中移走)和:
:
PeekMessage函数(从消息队列得到消息但是可以不移走)都使用了该结构来保存获得的消息信息。
MSG结构的定义如下:
typedefstructtagMSG{//msg
HWNDhwnd;
UINTmessage;
WPARAMwParam;
LPARAMlParam;
DWORDtime;
POINTpt;
}MSG;
该结构包括了六个成员,用来描述消息的有关属性:
接收消息的窗口句柄、消息标识(ID)、第一个消息参数、第二个消息参数、消息产生的时间、消息产生时鼠标的位置。
2.应用程序通过窗口过程来处理消息
如前所述,每个“窗口类”都要登记一个如下形式的窗口过程:
LRESULTCALLBACKMainWndProc(
HWNDhwnd,//窗口句柄
UINTmsg,//消息标识
WPARAMwParam,//消息参数1
LPARAMlParam//消息参数2
)
应用程序通过窗口过程来处理消息:
非队列消息由Windows直接送给目的窗口的窗口过程,队列消息由:
:
DispatchMessage等派发给目的窗口的窗口过程。
窗口过程被调用时,接受四个参数:
1.awindowhandle(窗口句柄);
2.amessageidentifier(消息标识);
3.two32-bitvaluescalledmessageparameters(两个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在派生类中添加一个消息映射条目,用同样的原型定义一个函数,然后实现该函数。
这个函数覆盖派生类的任何基类的同名处理函数。
3.消息结构和消息处理
1.MFC处理的三类消息
根据处理函数和处理过程的不同,MFC主要处理三类消息:
*Windows消息,前缀以“WM_”打头,WM_COMMAND例外。
Windows消息直接送给MFC窗口过程处理,窗口过程调用对应的消息处理函数。
一般,由窗口对象来处理这类消息,也就是说,这类消息处理函数一般是MFC窗口类的成员函数。
*控制通知消息,是控制子窗口送给父窗口的WM_COMMAND通知消息。
窗口过程调用对应的消息处理函数。
一般,由窗口对象来处理这类消息,也就是说,这类消息处理函数一般是MFC窗口类的成员函数。
Win32使用新的WM_NOFITY来处理复杂的通知消息。
WM_COMMAND类型的通知消息仅仅能传递一个控制窗口句柄(lparam)、控制窗ID和通知代码(wparam)。
WM_NOTIFY能传递任意复杂的信息。
*命令消息,这是来自菜单、工具条按钮、加速键等用户接口对象的WM_COMMAND通知消息,属于应用程序自己定义的消息。
通过消息映射机制,MFC框架把命令按一定的路径分发给多种类型的对象(具备消息处理能力)处理,如文档、窗口、应用程序、文档模板等对象。
能处理消息映射的类必须从CCmdTarget类派生。
2.MFC消息映射的实现方法
依靠以下几个宏
1.DECLARE_MESSAGE_MAP宏:
#ifdef_AFXDLL
#defineDECLARE_MESSAGE_MAP()/
private:
/
staticconstAFX_MSGMAP_ENTRY_messageEntries[];/
protected:
/
staticAFX_DATAconstAFX_MSGMAPmessageMap;/
staticconstAFX_MSGMAP*PASCAL_GetBaseMessageMap();/
virtualconstAFX_MSGMAP*GetMessageMap()const;/
#else
#defineDECLARE_MESSAGE_MAP()/
private:
/
staticconstAFX_MSGMAP_ENTRY_messageEntries[];/
protected:
/
staticAFX_DATAconstAFX_MSGMAPmessageMap;/
virtualconstAFX_MSGMAP*GetMessageMap()const;/
#endif
DECLARE_MESSAGE_MAP定义了两个版本,分别用于静态或者动态链接到MFCDLL的情形。
2.BEGIN_MESSAE_MAP宏
#ifdef_AFXDLL
#defineBEGIN_MESSAGE_MAP(theClass,baseClass)/
constAFX_MSGMAP*PASCALtheClass:
:
_GetBaseMessageMap()/
{return&baseClass:
:
messageMap;}/
constAFX_MSGMAP*theClass:
:
GetMessageMap()const/
{return&theClass:
:
messageMap;}/
AFX_DATADEFconstAFX_MSGMAPtheClass:
:
messageMap=/
{&theClass:
:
_GetBaseMessageMap,&theClass:
:
_messageEntries[0]};/
constAFX_MSGMAP_ENTRYtheClass:
:
_messageEntries[]=/
{/
#else
#defineBEGIN_MESSAGE_MAP(theClass,baseClass)/
constAFX_MSGMAP*theClass:
:
GetMessageMap()const/
{return&theClass:
:
messageMap;}/
AFX_DATADEFconstAFX_MSGMAPtheClass:
:
messageMap=/
{&baseClass:
:
messageMap,&theClass:
:
_messageEntries[0]};/
constAFX_MSGMAP_ENTRYtheClass:
:
_messageEntries[]=/
{/
#endif
#defineEND_MESSAGE_MAP()/
{0,0,0,0,AfxSig_end,(AFX_PMSG)0}/
};/
对应地,BEGIN_MESSAGE_MAP定义了两个版本,分别用于静态或者动态链接到MFCDLL的情形。
END_MESSAGE_MAP相对简单,就只有一种定义。
3.END_MESSAGEP_MAP宏
{0,0,0,0.Af
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- MFC 消息 映射 实现