一、实现过程
1. 使用宏定义消息ID,例如:
#define WM_OCRRESULT (WM_USER+101)
其中WM_USER为系统消息和用户自定义消息的分界线,小于WM_USER的消息被系统所占用,如:WM_LBUTTONDOWN消息,大于WM_USER的消息为用户自定义消息;
2. 在类声明AFX_MSG块中声明消息响应函数的原型,例如:
afx_msg void OnOcrResult(WPARAM wParam, LPARAM lParam); 函数可以有返回值,也可以无返回值; 函数原型可以有参数,也可以无参数,如果无参数,经常导致在debug下正常运行,release下程序就奔溃了。
class CDlgOCRMain : public CDialog { protected: // Generated message map functions //{{AFX_MSG(CDlgOCRMain) virtual BOOL OnInitDialog(); afx_msg void OnDestroy(); afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg BOOL OnEraseBkgnd(CDC *pDC); afx_msg void OnPaint(); afx_msg void OnOcrResult(WPARAM wParam, LPARAM lParam); //}}AFX_MSG DECLARE_MESSAGE_MAP()
}
3. 在用户类的消息块中,使用ON_MESSAGE宏指令将消息映射到消
息处理函数中,格式为:ON_MESSAGE(MsgID,MsgFun)
注意:ON_MESSAGE一定要放到AFX_MSG_MAP之后,END_MESSAGE_MAP()之前
BEGIN_MESSAGE_MAP(CDlgOCRMain, CDialog) //{{AFX_MSG_MAP(CDlgOCRMain) ON_WM_DESTROY() ON_WM_SIZE() ON_WM_ERASEBKGND() ON_WM_PAINT() //}}AFX_MSG_MAP ON_MESSAGE(WM_OCRRESULT, OnOcrResult) END_MESSAGE_MAP()
4. 实现消息处理函数
void CDlgOCRMain::OnOcrResult(WPARAM wParam, LPARAM lParam) { //........................ }
二、自定义消息出错
如果我们消息响应函数原型为: afx_msg void OnXXXX(); 则在经常导致在debug下正常运行,release下程序就奔溃了。
解决方法:
将afx_msg void OnXXXX()改为afx_msg void OnXXXX(WPARAM wParam, LPARAM lParam);
原因:
当有自定义的消息产生时,系统会调用自定义消息处理函数,系统想当然的认为这个函数有两个参数,分别是WPARAM wParam和LPARAM lParam。系统在调用函数时,会把这两个参数压栈。 然而函数自身并没有参数。在release优化的情况下,在返回上一级函数时,依据的是这个函数的自动变量,参数等信息,于是这两个参数被系统留了下来,也就是说参数仍然保存在栈中,这样就产生了冲突,所以程序就崩溃了。
在debug下,每调用一个函数时,系统会把当前函数在堆栈中的位置保存在一个寄存器中(SP),当函数执行完毕后返回上一级函数时,SP指针返回到函数调用前SP指针指向的位置。也就是说保证了入栈和出栈的一致性。