对于一条MFC消息响应函数,一般会有三处相关信息。
1. 消息响应函数声明
project1Dlg.h (如何多doc文档则是xxxView.h)
class Cproject1Dlg : public CDialog
{
// 构造
public:
Cproject1Dlg(CWnd* pParent = NULL); // 标准构造函数
// 对话框数据
enum { IDD = IDD_PROJECT1_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedOk(); //函数声明,声明了是消息响应函数
};
2. 消息响应函数定义
project1Dlg.cpp
void Cproject1Dlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
OnOK();
}
3. 书写消息映射宏,表示遇到该宏对应消息时,将消息与消息响应函数关联,调用消息响应函数
BEGIN_MESSAGE_MAP(Cproject1Dlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDOK, OnBnClickedOk)
END_MESSAGE_MAP()
ON_BN_CLICKED(IDOK, OnBnClickedOk)与OnBnClickedOk() 通过参数对应的关系显得很清晰。而原有的VC机制常用ON_WM_LBUTTONDOWN与响应函数OnLButtonDown()对应,这对书写有严格要求,不能错,因为VC中存在了一个消息映射表这样的东西,对每个消息宏(如ON_WM_LBUTTONDOWN)都预定义了消息映射函数(如OnLButtonDown())这样的虚函数,使用时定义一下就可以,但必须按映射表的原函数书写才能关联消息宏。
如何消息映射表中没有该消息及响应函数,想自定义一个。
转一个MFC自定义消息的实现
1).在相关类的头文件顶部添加如下所示的字串(以CMyDlg类为例):
在CMyDlg.h中添加#define WM_MY_MESSAGE (WM_USER+100) 注意:在源文件(。cpp)也可以的。
1 2
其中1位置处的消息名可以自定,位置2处是确保消息在程序中唯一性,所以用(WM_USER+数值)的形式来表示,数值不可为负.
2).在消息定义完成后,需要转到相应类的源程序文件CMyDlg.cpp中,在如下所示的固定结构间添加消息与函数的映射.
BEGIN_MESSAGE_MAP(CTestdisockDlg, CDialog)
//{{AFX_MSG_MAP(CTestdisockDlg)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
例如要添加上面已经定义好的消息,添加后的结构如下:
BEGIN_MESSAGE_MAP(CTestdisockDlg, CDialog)
//{{AFX_MSG_MAP(CTestdisockDlg)
ON_MESSAGE(WM_NOTIFY_MESSAGE, OnMyMessage) //3
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
其中3所示的行即是添加的内容.要注意自定义消息是以ON_MESSAGE()的形式映射,第一个参数是上面已经定义好的消息名,第二个参数是该消息的映射函数,消息是函数的触发条件.无消息到达时该函数永远不被执行.
3).上面的完成后,需要转到CMyDlg.h文件中,也就是定义类的文件中,在如下的结构中申明刚才映射好的函数.
//{{AFX_MSG(CTestdisockDlg)
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP() //找位置的时候,以该行出现的地方为准.
添加函数后的结构如下,与普通的申明稍有区别.
//{{AFX_MSG(CTestdisockDlg)
virtual BOOL OnInitDialog();
afx_msg OnMyMessage(); //4
//}}AFX_MSG
DECLARE_MESSAGE_MAP() //找位置的时候,以该行出现的地方为准,添加函数后的结构如下,与普通的申明稍有区别.
位置4对应的行是加上的函数申明,如果有参数就写带参的形式,其中afx_msg 头是所有与消息有关的函数必须加的标识.
最后一步就是到源文件CMyDlg.cpp中写函数的实现部分,也就是具体的编程.
消息的触发是靠SendMessage()或PostMessage()函数完成的,它们的第一个参数就是指定把消息发往那个窗口,发送成功后,映射函数就会被调用执行。
小白特别提示: 在很多动态菜单自定义函数问题上,ON_MESSAGE会无效,推荐用ON_COMMAND
ON_COMMAND 对应的都是WM_COMMAND消息,是用户自定义消息的较好发布者
两者区别非常理论
窗口消息(Window Message)一般与窗口的内部运作有关,如创建窗口、绘制窗口和销毁窗等。通常,消息是从系统发送到窗口,或从窗口发送到窗口。
若需要窗口消息的完全的列表,请参考M F C文档。
命令消息
命令消息一般与处理用户请求相关,当用户单击一个菜单项或工具栏时,命令消息产生,并被发送到能处理该请求的类对象(如,装载文件、编辑文本和保存选项等)。
控件通知
通常,控件通知在某些重要事件发生时,由控件窗口发送到父窗口,如打开一个组合框。
控件通知为父窗口进一步控制子窗口提供了机会。例如,打开一个组合框时,父窗口可以用组合框初建时得不到的消息填充它。
ON_COMMAND 和ON_MESSAGE都是将消息处理函数加入消息路由表中,但是ON_COMMAND对应的消息ID一直都是WM_COMMAND,而ON_MESSAGE的消息ID为ON_COMMAND的第一个参数
转载于:https://blog.51cto.com/alittle/556399