原文链接:http://kwun.blogbus.com/logs/4272601.html


用惯了MFC的自动代码生成模版, 就不会去管这些东西. 不过有时候看到那个奇怪的定义, 还是会奇怪唔, 怎么工作的?

今天看了一下源代码, 大概了解了一下. 嗯, 一起来看看. 首先是类声明中用到的 DECLARE_MESSAGE_MAP():

#define DECLARE_MESSAGE_MAP()                            \
protected:                                               \
    static const AFX_MSGMAP* PASCAL GetThisMessageMap(); \
    virtual const AFX_MSGMAP* GetMessageMap() const;     \

这个宏很直观了, 声明了两个函数. 注意GetMessageMap()是一个虚函数. 这两个函数在后面的定义中会用到.

其次是.CPP中的BEGIN_MESSAGE_MAPEND_MESSAGE_MAP:

#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

好像比较抽象的样子. 其实展开来看就清楚了, 以ON_WM_SIZE()为例

BEGIN_MESSAGE_MAP(CCrossbowTestDlg, CDialog)
    ON_WM_SIZE()
END_MESSAGE_MAP()

展开并精简之后得到如下形式:

const AFX_MSGMAP* CTestDialog::GetMessageMap() const
{
    return GetThisMessageMap();
}

const AFX_MSGMAP* PASCAL CTestDialog::GetThisMessageMap()
{
    static const AFX_MSGMAP_ENTRY _messageEntries[] =
    {
        {WM_SIZE, 0, 0, 0, AfxSig_vwii, &CTestDialog::OnSize},
        {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0}
    };

    static const AFX_MSGMAP messageMap =
    {&CDialog::GetThisMessageMap, &_messageEntries[0]};
    return &messageMap;
}

具体的函数使用流程还没有去看, 不过看这个定义以及逻辑上的处理结果, 应该是: 当一个消息被解析时, 对于GetMessageMap()中(通过GetThisMessageMap())返回的messageMap, 首先检测_messageEntries中是否有匹配的消息响应函数(通过MESSAGE ID), 若有则执行相应函数, 否则(_messageEntries检测到达最末一个成员, 其MESSAGE ID为0)通过调用基类的GetThisMessageMap()获得基类的messageMap, 并重复上述动作, 直到消息被解析为止.



Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐