1、消息映射的现实
// 下面为MFC中定义的一些宏,可自行查看相应的头文件
#ifdef _ATL_ENABLE_PTM_WARNING
#define PTM_WARNING_DISABLE
#define PTM_WARNING_RESTORE
#else
#define PTM_WARNING_DISABLE \
__pragma(warning( push )) \
__pragma(warning( disable : 4867 ))
#define PTM_WARNING_RESTORE \
__pragma(warning( pop ))
#endif //_ATL_ENABLE_PTM_WARNING
// pointer to afx_msg member function
#ifndef AFX_MSG_CALL
#define AFX_MSG_CALL
#endif
typedef void (AFX_MSG_CALL CCmdTarget::*AFX_PMSG)(void);
// like 'AFX_PMSG' but for CWnd-derived classes only
typedef void (AFX_MSG_CALL CWnd::*AFX_PMSGW)(void);
// like 'AFX_PMSG' but for CWinThread-derived classes only
typedef void (AFX_MSG_CALL CWinThread::*AFX_PMSGT)(void);
struct AFX_MSGMAP_ENTRY
{
UINT nMessage; // windows message
UINT nCode; // control code or WM_NOTIFY code
UINT nID; // control ID (or 0 for windows messages)
UINT nLastID; // used for entries specifying a range of control id's
UINT_PTR nSig; // signature type (action) or pointer to message #
AFX_PMSG pfn; // routine to call (or special value)
};
struct AFX_MSGMAP
{
const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
const AFX_MSGMAP_ENTRY* lpEntries;
};
// 这里即息映射宏的主体
#define BEGIN_MESSAGE_MAP(theClass, baseClass) \
PTM_WARNING_DISABLE \
const AFX_MSGMAP* theClass::GetMessageMap() const \
{ return GetThisMessageMap(); } \
const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() \
{ \
typedef theClass ThisClass; \
typedef baseClass TheBaseClass; \
static const AFX_MSGMAP_ENTRY _messageEntries[] = \
{
#define END_MESSAGE_MAP() \
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
}; \
static const AFX_MSGMAP messageMap = \
{ &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \
return &messageMap; \
} \
PTM_WARNING_RESTORE
#define ON_WM_SYSCOMMAND() \
{ WM_SYSCOMMAND, 0, 0, 0, AfxSig_vwl, \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< void (AFX_MSG_CALL CWnd::*)(UINT, LPARAM) > ( &ThisClass :: OnSysCommand)) },
// 根据上面的宏定义,可将下面的宏进行展开
BEGIN_MESSAGE_MAP(CTestDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_BN_CLICKED(IDC_BUTTON_MESSAGE, &CTestDlg::OnBnClickedButtonMessage)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST, &CTestDlg::OnLvnItemchangedList)
END_MESSAGE_MAP()
const AFX_MSGMAP* theClass::GetMessageMap() const
{
return GetThisMessageMap();
}
const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap()
{
typedef theClass ThisClass;
typedef baseClass TheBaseClass;
static const AFX_MSGMAP_ENTRY _messageEntries[] =
{
{ WM_SYSCOMMAND, 0, 0, 0, AfxSig_vwl, (AFX_PMSG)(AFX_PMSGW)(static_cast<void (AFX_MSG_CALL CWnd::*)(UINT, LPARAM)>(&ThisClass::OnSysCommand)) },
{ WM_PAINT, 0, 0, 0, AfxSig_vv, (AFX_PMSG)(AFX_PMSGW)(static_cast<void (AFX_MSG_CALL CWnd::*)(void)>(&ThisClass::OnPaint)) },
{ WM_COMMAND, (WORD)wNotifyCode, (WORD)id, (WORD)id, AfxSigCmd_v, (static_cast<AFX_PMSG>(memberFxn)) },
{ WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)id, AfxSigNotify_v, (AFX_PMSG)(static_cast<void (AFX_MSG_CALL CCmdTarget::*)(NMHDR*, LRESULT*)>(memberFxn)) },
{ 0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 }
};
static const AFX_MSGMAP messageMap =
{
&TheBaseClass::GetThisMessageMap,
&_messageEntries[0]
};
return &messageMap;
}
2、扩展(自定义)消息
// afxmsg_.h
// User extensions for message map entries
// for Windows messages
#define ON_MESSAGE(message, memberFxn) \
{ message, 0, 0, 0, AfxSig_lwl, \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) > \
(memberFxn)) },
// for Registered Windows messages
#define ON_REGISTERED_MESSAGE(nMessageVariable, memberFxn) \
{ 0xC000, 0, 0, 0, (UINT_PTR)(UINT*)(&nMessageVariable), \
/*implied 'AfxSig_lwl'*/ \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) > \
(memberFxn)) },
// for Thread messages
#define ON_THREAD_MESSAGE(message, memberFxn) \
{ message, 0, 0, 0, AfxSig_vwl, \
(AFX_PMSG)(AFX_PMSGT) \
(static_cast< void (AFX_MSG_CALL CWinThread::*)(WPARAM, LPARAM) > \
(memberFxn)) },