MFC的消息映射

来源:互联网 发布:遗传算法与蚁群算法 编辑:程序博客网 时间:2024/06/05 19:49

Windows操作系统采用消息驱动机制,即以消息来驱动应用程序的运行。如果说窗口是用户操作的接口,消息就是流过这个接口的血液。MFC的消息映射与处理机制是其精华所在,相比之下其他语言如c#、VB等提供给开发者的消息处理方式显得格外局促和僵化。

MFC中的窗口封装类CWnd为各种窗口消息定义了对应的虚拟函数(如OnkeyDown(),Onpaint()等),而一个消息处理调度函数WindowProc()为响应各种窗口消息,调用相应的虚拟函数进行处理,例如WM_KEYDOWN消息到来,就调用Onkeydown()虚函数进行处理。如果派生类需要特殊处理某个消息(系类的处理不能满足需要),重载相应的虚函数即可。这种消息处理机制在MFC没有诞生之前,被认为是显而易见的。

但这种处理机制存在明显的缺陷。因为如果基类定义了虚拟函数,系统要为基类和每个派生类分别建立一张虚拟函数表,其中每个虚拟函数有4字节的入口地址,无论派生类是否重载了某个虚函数。要为100个以上的窗口消息都定义相应的虚函数,成本是可观的。另外,不可能为所有菜单、按钮的命令消息都定义处理函数,并且控件的通知消息、反射消息也是不可以预知的。在这种机制下,处理不可预知的命令和通知消息,只能像WIN32API编程那样,使用繁琐的switch-case语句。所以,由于以上种种原因,MFC没有采用虚拟函数机制,而是新创了所谓的消息映射机制。

消息映射就是在基类中建立一张窗口消息和消息处理函数的映射表(以数组形式存储),将大部分窗口消息和处理消息的对应关系存储在该表中。注意,这些处理函数虽然也是基类为每个窗口消息分别定义的,但是他们并不是虚函数。基类(如CWnd)为大部分窗口消息定义了处理函数,并建立了二者之间的映射关系,这些处理函数通常对消息进行常规处理或默认处理。而派生类的初始消息映射表是空的,如果派生类需要对某个消息进行特殊处理,它可以定义一个新的消息处理函数,并在自己的映射表中添加一项,存储该消息和该函数的对应关系。这里也有一个消息处理跳读函数,它是CWnd::OnWndMsg()。针对某个消息,该函数首先在当前派生类的消息映射表中寻找对应的处理函数,不成功就向上寻找父类的映射表,直到成功或者搜索完基类为止。如果最终没有发现对应的处理函数,则执行系统级的默认处理。

基类没有为命令、通知等不可预知的消息定义处理函数,但是能够根据需要,将他们添加在派生类的消息映射表中。当消息到来时,存储在该表中的相应处理函数的入口地址(函数指针)就被提取、调用。
虽然建立消息映射表的方法显得机械,但这些机械的工作可以由类向导来完成,类向导不仅能够建立消息映射项目,还能为消息处理函数生成框架。只有少数类向导不支持的窗口消息或自定义消息,才必须劳烦程序员动手。

原创粉丝点击