现在的位置: 首页 > 综合 > 正文

WTL消息映射

2011年07月13日 ⁄ 综合 ⁄ 共 1692字 ⁄ 字号 评论关闭

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的处理的地方,调用其他窗口的处理。

抱歉!评论已关闭.