CDialog的派生类中OnOK()函数和virtual的关系
- 插入一个对话框后,建立一个名为CMyDialog的类,从CDialog派生;
- 由于添加对话框资源时,会自动产生一个ID为IDOK的按钮,我们可以给它添加一个默认为OnOK()的处理函数;
- OnOK()在MyDialog.h中的声明为 virtual void OnOK();
- 如果我们在对话框上增加一个按钮,默认ID为IDC_BUTTON1,我们可以给它添加一个默认为OnButton1()的处理函数;
- OnButton1()在MyDialog.h中的声明为 afx_msg void OnButton1();
- 并且在MyDialog.cpp中有一个消息映射宏:ON_BN_CLICKED(IDC_BUTTON1,OnButton1)
为什么同样是按钮的消息映射函数,OnButton1()和OnOK()的实现方式有这么大的区别?因为对于ID为IDOK的按钮,CDialog是作为一个特殊的按钮使用的,特殊之处在于要在其中实现数据的交换,即要调用DoDataExchange()。(这是另外一个有趣的话题,根据我的经验,不少人对于DoDataExchange()是知其然,不知其所以然,在以后的帖子中有时间的话另外讨论)。
但是实际上,对于IDOK的按钮的消息映射还是遵循了和普通按钮IDC_BUTTON1一样的处理途径:
- 如果跟踪CDialog::OnOK(),我们进入了DlgCore.cpp,这是CDialog的实现文件,可以在其中发现CDialog的消息映射表中就有ON_COMMAND(IDOK, OnOK),实际上ON_BN_CLICKED消息映射宏也是处理了WM_COMMAND的消息,所以两者的作用是一样的;
- 再进入AfxWin.h,这是CDialog的声明文件,在其中可以发现CDialog中声明了virtual void OnOK();
啊哈!我们终于知道了OnOK()的来龙去脉!即在基类中使用普通消息映射的方式实现,只是基类中声明其为virtual函数,所以可以调用CMyDialog中的OnOK()函数!
小Tips:
- 如何进入进入AfxWin.h?在VC程序中输入CDialog,鼠标右键点击,选择弹出菜单中的Go To Definition of CDialog,或者键盘光标定位在CDialog的任何位置,按下<F12>;
- 为什么 afx_msg void OnButton1()的声明有afx_msg,而OnOK()没有??请大家使用F12的方法跟踪afx_msg这个奇怪的函数修饰符的声明:
#ifndef afx_msg
#define afx_msg // intentional placeholder
#endif
啊,原来它什么都不是?!在所有的消息映射函数的声明前添加这个东东,据说是为了以后的扩展,可能以后这个东东就是一个特别的表示消息映射函数的符号了。但是C#既出,.Net Framework Library替代MFC的趋势似乎不可避免……,以后我们的afx_msg还会有更新的一天吗?