添加消息处理函数或重载MFC类

来源:互联网 发布:理想论坛金钻指标源码 编辑:程序博客网 时间:2024/05/30 19:33

目标
在类中,添加一个消息处理函数或者重载一个M F C成员函数。
策略
首先,用Class Wi z a r d自动地添加一个消息处理函数或重载成员函数;然后,讨论当需要
的处理函数或重载函数在Class Wi z a r d指令系统的外面时,怎样手工完成该工作。
步骤
1. 利用Class Wi z a r d添加消息处理函数或重载类
1) 单击Developer Studio的View/Class Wi z a r d菜单命令,打开Class Wi z a r d。确定想添加消
息处理函数或重载函数的类,并从Class name组合框中选取。在Object IDs列表框中,选取类
的名称(其他项是菜单和工具栏命令I D,这些在例1 3中已讨论)。此时, M e s s a g e s列表框显示
该类的大多数(若不是全部的话)可重载成员函数和窗口消息。类重载显示在列表的上部,以实
际虚构成员函数的大小写字母来表示。其他为窗口消息,以大写字母出现,描述了实际窗口
所能响应的消息I D。为了添加所需的重载函数或处理函数,单击Add Function 按钮。C l a s s
Wi z a r d将添加该函数到它维护的源代码的表中,并附简单注释

2) 若在M e s s a g e列表中找不到所要的消息或重载函数,则可以选取Class Wi z a r d上C l a s s
I n f o标签以扩展消息列表。在该页中,找到Message Filter组合框,可以改变首页中M e s s a g e s
列表框中的选项。例如,选择Not a Wi n d o w,将从消息列表中去掉所有的窗口消息(从技术上
讲,只有窗口能接收消息,因此没必要添加消息处理函数);选择Select Wi n d o w会显示所有的
窗口消息。
注意若在Messages列表框中没有找到相应的处理函数或重载函数,那可能是该处理函
数或重载函数对类是无效的。然而,有时C l a s s Wi z a r d会简单地忽略一些消息,因为它
们根本就很少用。

要删除一个处理函数或重载函数,从M e s s a g e列表中选中它并单击Delete Function按钮。
实际上,所有C l a s s Wi z a r d能删除的都是在它所维护的源文件表中处于{[ ]}括号之间的条目,因此,有必要把该函数的其他代码删掉。即使临时地添加一个处理函数,并立即用
C l a s s Wi z a r d删除它,也必须定位到该空函数,并手动地删除它。2. 手动地添加消息处理函数
如果C l a s s Wi z a r d并没有列出想要处理的消息,该消息可能是被系统忽略掉或者是你自己
创建的,这时,必须自己手工添加处理函数。一个消息处理函数需要对类作三处编辑:声明
和实现处理函数、进入类的消息映像中的处理函数。
1) 在类的. h文件中添加处理函数的声明,紧接在/ / } } A F X _ M S G行之后加入声明,这是类
的. h文件中的消息映像区,通过添加之后,看起来应该如下所示(本例中消息处理函数称为
“O n D e s t r o y ( )”):
// Generated message map functions
p r o t e c t e d :
/ / { { A F X _ M S G ( C W z d C l a s s )
/ / } } A F X _ M S G
afx_msg void OnDestroy(); <<<< add declarations after "}}"
D E C L A R E _ M E S S A G E _ M A P ( )
通常,添加处理函数声明的最好的地方是源代码中C l a s s Wi z a r d维护的表下面,但是在它
标记其领域的{{}}括弧外面。这些括弧中的任何东西都将会被C l a s s Wi z a r d销毁。
2) 接着,在用户类的. c p p文件中的消息映像区中,添加一个消息映像宏。定位
/ / } } A F X _ M S G _ M A P行,紧接在它之后加入宏。
BEGIN_MESSAGE_MAP(CWzdClass, CClass)
/ / { { A F X _ M S G _ M A P ( C W z d C l a s s )
/ / } } A F X _ M S G _ M A P
ON_WM_DESTROY() //<<<< add macros after "}}"
E N D _ M E S S A G E _ M A P ( )

3) 然后,可以在该文件中添加消息处理函数的实体。
void CWzdClass::OnDestroy()
{
}
对于一特定的消息映像宏,参见附录B中有关详细的调用语法。
3. 手动地添加一个类重载函数
1) 要想手工添加一个重载函数,只须对文件进行两处编辑。由于是从其基类直接获取控
制,而基类可能自身正对消息进行处理,所以不必在消息映像中添加任何内容。首先,在. h文件中C l a s s Wi z a r d维护的表处添加重载函数的声明。(本例中,重载函数P r e C r e a t e Window( )。)
// Overrides
// ClassWizard generated virtual function overrides
/ / { { A F X _ V I RT U A L ( C W z d C l a s s )
p u b l i c :
: : :
/ / } } A F X _ V I RT U A L
public: << make sure to match virtual
<< function’s protection
virtual BOOL PreCreateWi n d o w ( C R E ATESTRUCT& cs);
2) 然后,在相应的. c p p文件中加入重载函数实体,如例所示。当然,也可以有选择地调
用基类的函数。
BOOL CWzdClass::PreCreateWi n d o w ( C R E ATESTRUCT& cs)
{
return CClass::PreCreateWi n d o w ( c s ) ;
}
说明
■ 实际上,有许多种方法激发C l a s s Wi z a r d。通常,用鼠标右击类的资源文件,将打开
C l a s s Wi z a r d并显示该类。也可以通过单击To o l s / C u s t o m i z e菜单命令,打开环境的
C u s t o m i z e对话框以创建一个工具栏按钮。在C o m m a n d s标签下,有一个C a t e g o r i e s列表
框,在列表框中选择Vi e w。C l a s s Wi z a r d是此处所列的按钮之一,可以把它拖进任何一
个已存在的工具栏,或者拖进一个空档处以创建一个新的工具栏。
■ 当添加自己的消息处理函数,或者使用过滤器以展开可以添加的消息处理函数列表时,
这个类可能没有权利接收该消息。这就是说,即使C l a s s Wi z a r d允许添加某个消息处理
函数,但是类可能没有资格接收该消息。

■ 当手工添加一个重载函数到用户类时,其基类必须有相应的被重载的函数。好在如果
不能重载,编译器会立即告诉你的。但是对消息处理函数就不一定如此,只有当运行
测试时,你才可能发现他添加了一个消息处理函数到一个根本不接收该消息的类中。
■ 如果没有被文档化, C l a s s Wi z a r d将不列出即使是可重载的函数。可以在M F C提供的源
代码中找到这些未文档化的重载函数。然而,既然它们没有被文档化,微软公司在以
后的M F C发行版本中也不会支持这些重载函数。若必须要使用未文档化的重载函数,
当移植到M F C的下一个版本时,就无法再访你所写的代码。
■ 当使用C l a s s Wi z a r d添加一个消息处理函数到自己的类中时, C l a s s Wi z a r d一般会加入调
用基类相应函数的代码,并且把用户消息处理函数接收到的参数传递给它。
void CAppView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
C View::OnLButtonDown(nFlags, point);
}
不要嫌烦改变这些参数以影响基类的行为。这些参数放在这儿只不过添加麻烦而已。当基类获取这些参数时,它不会对此置之不理,相反,它将使用最开始传给你的消息。
在消息未被基类处理之前,若确实想修改这个消息或者修改缺省的窗口进程,则需要重
新构造原来的消息,修改其中的参数w P a r a m和l P a r a m,不是调用基类函数,而是直接调用
D e f WindowProc( )。要想知道如何构造关于D e f WindowProc( )函数的消息参数,参见M F C的
关于该消息的说明文档。在本例中,可以用:
D e f WindowProc (WM_LBUTTONDOWN, nFlags, Point);
■ 为了获取基类当前正在处理的消息,用户可以使用如下语句:
MSG msg=CWnd::GetCurrentMessage( );
这里,M S G是如下形式的一个消息结构:
typedef struct tagMSG {
HWND hwnd;
UINT message;
W PARAM wParam;
L PARAM lParam;
DWORD time;
POINT pt;
} MSG;
■ 然后,可以用获取的值调用D e f WindowProc( )。
MSG msg=CWnd::GetCurrentMessage();
msg.wParam = ...changed...
D e f Wi n d o w P r o c ( m s g . m e s s a g e , m s g . w P a r a m , m s g . l P a r a m ) ;