到OnCommand()进行处理。
LRESULT OnCommand(WPARAM wParam, LPARAM lParam);
此时,一个WM_COMMAND消息既可以是命令消息,也可以是一个控件通知。OnCommand( )查看lParam是不是一个有效的窗口句柄,如果是,则OnCommand( )以控件通知处理该消息,这里lParam是控件的句柄,并且将消息反射到发送它的窗口。
消息反射
前面已提及,当控件状态发生变化时,控件通知被发送到父窗口。因此,控件通知提供给父窗口有限的能力,用来定制和补充控件工作的方式。例如,当一个组合框下拉时,父窗口通过修改下拉列表内容作出反应。
然而,把这项功能交给父窗口违背了面向对象编程的意图,因为它要求每个对象都应该包括所有属于它自己的功能。在上面的例子中,每次组合框移到一个新的父窗口中,则下拉功能也要移到新的父窗口。因此,将控件通知处理功能交给控件会更可取。因为每个控件已经有一个可以通过重载添加其他功能的MFC类,所以若能按照那列表来处理控件通知的话将会是非常好的。这样,每当把控件移到一个新的父窗口时,不必考虑必须把哪些代码拷贝到新的父窗口。MFC用一个叫做“消息映射”的过程来支持该项功能。无论什么时候,当MFC窗口刚刚接收到一个控件通知时,它知道该通知有一个控件窗口在某处,并且很可能有一个MFC派生类在控制它,因此,MFC窗口试图将那通知映射回到
MFC派生类,并给它处理该通知的机会。用这种方法可以将任何一个控件的所有功能放到一个井然有序的类包里。
46
如果控件不想该消息返回,OnCommand( )如处理通用消息一样处理该消息,并调用OnCmdMsg( )。
6.OnNotify( )
WM_NOTIFY消息被发送到OnNotify( )函数。
BOOL OnNotify(WPARAM wParam , LPARAM lParam, LRESULT &lResult);任何发送到这里的消息都自动地被认为是一个控件通知,并且消息被反射。如果控件类不想该消息返回,则OnNotify( )调用OnCmdMsg( )。
OnCommand( )和OnNotify( )都调用ReflectLastMsg( ),以提供一个控件通知返回到它的控件窗口。ReflectLastMsg( )获取控件窗口的窗口句柄,并在它的消息
映
像
中
寻
找
WM_COMMAND+WM_REFLECT_BASE
或
WM_NOTIFY+WM_REFLECT_BASE和通知代码。
7.OnCmdMsg()
如果一个控件通知被它的控件窗口拒绝,则OnCommand( )和OnNotify( )通过调用下面的函数,像处理命令消息一样处理它: BOOL
OnCmdMsg(UINT
nID,
int
nCode
,void*pExtra,
AFX_CMDHANDLERINFO * pHandlerInfo);
接着,在一个称为命令传递的过程中,命令消息和控件通知被提供给一些类。 命令传递
OnCmdMsg( )实际上是CCmdTarget的成员函数,而不是CWnd的成员函数。
47
认识这一点很重要,因为它允许任何从CCmdTarget派生的类接收一个命令消息,即使那些没有一个窗口的类也可以。例如,文档类没有相关联的窗口,它依赖视图类显示它的文档。但是一个文档类是处理一个装载或保存命令的最好的地方,因此,虽然一个文档类不能处理类似于WM_CREATE或WM_DESTROY的命令消息。但OnCmdMsg( )允许它处理类似于WM_COMMAND和WM_NOTIFY的命令消息。CWnd本身是从CCmdTarget派生而来的,因此,它也能支持命令消息。
在所有的主应用程序类(应用程序、框架、视图和文档类)中,MFC通过重载OnCmdMsg()执行命令传递。例如,视图类重载OnCmdMsg(),使它能为文档类提供命令和控件通知消息;文档类重载OnCmdMsg(),使它能为文档模板类提供命令消息。传递效果具有累积性。被发送到CMDIFrameWnd的命令消息,首先被提供给有效的CMDIFrameWnd中的消息映像,接着给有效的CView、有效CView的CDocument、那个文档的CDocTemplate、CMDIFrameWnd自身的消息映像,最后给CWinApp。
一旦OnCmdMsg()找到一个消息处理函数,命令传递就停止。在前面的例子中,如果OnCmdMsg()在CDocument中找到一个处理函数,它将用命令消息调用该处理函数并返回结果,而不用继续传递给CDocTemplate。
消息映像宏
虽然命令消息和控件通知被传递的方法是相同的,但是它们预定义的消息映像宏却是不同的。命令消息采用的形式为:
ON_COMMAND()
而控件通知采用的一般形式为:
ON_CONTROL()为WM_COMMAND通知 ON_NOTIFY()为WM_NOTIFY通知
48
第四章COM基础
一、COM概念
1、COM
COM(Component Object Model),组件对象模型,是一组以组件为发布单元的对象模型,这种模型使各种软件组件可以用一种统一的方式交互。
2、COM与C++
2.1 软件分发与C++
为了理解软件分发带来的问题,我们来看下一个例子: //faststring.h class FastString {
char * m_psz; public:
FastString(const char * psz); ~FastString(); int Length();
int Find(const char* psz) const; };
//faststring.cpp
#include \#include \
FastString::FastString(const char *psz) :m_psz(new char[strlen(psz)+1]) {
strcpy(m_psz,psz); }
FastString::~FastString() {
delete[] m_psz; }
int FastString::Length() const {
return strlen(m_psz);
49
}
int FastString::Find(const char *psz) {
//代码从简 }
从传统的意义上讲,C++的分发一直是以源代码的形式进行的,类库的用户一般是将源代码加入他们的工程中,然后用编译器编译源代码。这样,类库的可执行代码将成为客户应用中不可分割的一部分。如下图:
应用程序A FastString.obj
应用程序B FastString.obj
应用程序C FastString.obj
这种情况会造成一个问题,一旦类FastString发现了缺陷,那么没有任何方法可以替换客户文件中的实习代码,客户不得不重新编译他们的应用程序,所以一旦生成了最终的可执行代码后,FastString类的模块化特征就没有了。
2.2动态链接与C++
解决上面问题的一种技术是把FastString类以动态链接库(DLL,Dynamic Link Library)的形式包装起来。Microsoft C ++编译器为这种方法提供了__declspec(dllexport)关键字:
class __declspec(dllexport)FastString {
char * m_psz; public:
FastString(const char * psz); ~FastString(); int Length();
int Find(const char* psz) const; };
在使用这项技术的时候,FastString的所有方法都将被加到FastString.DLL的引出表中,允许在运行时把每个方法的名字解析到内存中对应的地址,客户程序通知装载器动态装载FastString.DLL,并且把所有被引入的符号解析到内存中相应的位置上。当FastString从DLL中引出时,他的机器码在硬盘上只用保留一份就可以了,当有多个客户程序访问库中的代码时,操作系统的装载器可以很灵活的让所有的客户程序共享同一份“FastString”的可执行代码。这样,一旦发现FastString中的错误后,可以给客户一个新的DLL,从而同时修正所有客户的错误。
50
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库基于MO的GIS程序设计与开发讲义(2008).doc在线全文阅读。
相关推荐: