BEGIN_MSG_MAP宏产生一个类函数,窗口函数会调用这个类函数。 调试的时候会发现当消息来的时候,调试器会跟踪到BEGIN_MSG_MAP和END_MSG_MAP()块之间。另外还有个宏更好用,它是BEGIN_MSG_MAP_EX
MESSAGE_HANDLER可以截获消息
COMMAND_ID_HANDLER可以截获WM_COMMAND消息
CHAIN_MSG_MAP可以将消息转到别的类
BEGIN_MSG_MAP(CMainFrame)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
END_MSG_MAP()
但是对于WM_IDLE消息,是只能主窗口得到,而其他窗口无法得到。
除此之外,如果其他窗口想截获主窗口的消息,该如何实现呢?
方法一:
使用CMessageLoop。CMessageLoop提供重要函数AddMessageFilter和AddIdleHandler。
WTL为了其他窗口能得到主窗口的消息,构造了CMessageLoop。CMessageLoop的对象被藏在_Module里。
将CMessageLoop对象加入_Module:
_Module.AddMessageLoop(&theLoop);
得到CMessageLoop的对象:
CMessageLoop* pLoop = _Module.GetMessageLoop();
得到CMessageLoop对象后,可以添加Filter或Idle函数。
pLoop->AddMessageFilter(this);//截获主窗口消息
pLoop->AddIdleHandler(this);//截获IDLE消息
对于所有传递给主窗口的消息,都会进入主窗口的PreTranslateMessage。主窗口如果改写了PreTranslateMessage,则可以让消息传递到其他窗口的函数中,如:
virtual BOOL PreTranslateMessage(MSG* pMsg)
{
if(CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg))
return TRUE;
return m_view.PreTranslateMessage(pMsg);//传递给其他窗口函数。
}
PreTranslateMessage的返回值如果是FALSE,则由窗口函数处理,否则不处理。
PreTranslateMessage只能截获PostMessage,而不能截获SendMessage。
这是因为只有PostMessage才会放入队列,而SendMessageBox直接调用窗口函数。
只有在队列里,才可能去调用PreTranslateMessage。
if(!PreTranslateMessage(&m_msg))
{
::TranslateMessage(&m_msg);
::DispatchMessage(&m_msg);
}
有了过滤函数,可以实现Frame的WM)IDLE传递到View里。
方法二:
像MFC那样,在主窗口的WM_COMMAND的处理的地方,调用其他窗口的处理。