标准 Windows 消息(WM_)的默认处理程序在类 CWnd
中预定义。 类库使用消息名称来命名这些处理程序。 例如, WM_PAINT 消息的处理程序声明 CWnd
为:
afx_msg void OnPaint();
afx_msg关键字通过将处理程序与其他virtual
成员函数区分开来,表明C++CWnd
关键字的效果。 但是,请注意,这些函数实际上不是虚拟的;而是通过消息映射实现它们。 消息映射仅依赖于标准预处理器宏,而不依赖于C++语言的任何扩展。 预处理后,afx_msg关键字解析为空白。
若要重写基类中定义的处理程序,只需在派生类中定义具有相同原型的函数,并为处理程序创建消息映射条目。 您的处理程序将“重写”任何类的基类中名称相同的任意处理程序。
在某些情况下,您的处理程序应当调用基类中的已重写处理程序,以便基类和 Windows 可处理消息。 在重写中调用基类处理程序的位置取决于环境。 有时您必须首先调用基类,有时最后调用。 有时,如果选择不自行处理消息,则有条件地调用基类处理程序。 有时应调用基类处理程序,然后根据基类处理程序返回的值或状态有条件地执行自己的处理程序代码。
谨慎
如果要将参数传递给基类处理程序,则修改传递到处理程序的参数是不安全的。 例如,你可能尝试修改 处理程序的 nChar 参数(例如,转换为大写)OnChar
。 此行为相当模糊,但如果需要实现此效果,请改用 CWnd
成员函数 SendMessage
。
如何确定用于重写给定消息的合适方法:当类向导为给定消息编写处理程序函数的框架时(例如,WM_CREATE 的 OnCreate
处理程序),它会按建议的重写成员函数的形式绘制。 以下示例建议处理程序首先调用基类处理程序,并仅在不返回 -1 的情况下继续。
int CMyView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFormView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
return 0;
}
按照约定,这些处理程序的名称以前缀“On”开头。其中一些处理程序不带参数,而另一些处理程序则采用多个参数。 有些还具有与void
不同的返回类型。 所有 WM_ 消息的默认处理程序记录在 MFC 引用 中,作为类 CWnd
的成员函数,其名称以“On”开头。成员 CWnd
函数声明的前缀为 afx_msg。