MFC的消息映射机制

原创 2015年07月07日 18:36:15

MFC的消息映射机制其实还是挺简单的, 下面用一个小的程序来演一下其工作原理.

/*----------------------------------------------------------------------------
                            MFC 消息映射机制的演示程序
    作者:Ning 2014/02/28
    备注:
    审核:

----------------------------------------------------------------------------*/
typedef int MessageID;
#define afx_msg

/*===========================================================================

    功能:  定义消息映射结构体  2014/02/28

===========================================================================*/
class CmdTarget;
typedef void (CmdTarget::*MemberFunc)();

// 定义一个消息结构, 关联消息ID与消息响应函数
struct MsgMap
{
    MessageID m_Msg;
    MemberFunc m_pFunc;
};

typedef MsgMap* MsgMapPtr;

struct MessageChain
{
    const MessageChain* m_pParent;
    MsgMapPtr m_MessageEntries;
};

/*===========================================================================

    功能: 消息映射基类  2014/02/28

===========================================================================*/
class CmdTarget
{
public:
    void MessageHandler(MessageID A_Msg);

protected:
    virtual const MessageChain* GetMsgChain() = 0;

private:
    static const MessageChain m_MsgChain;
};//end CmdTarget
const MessageChain CmdTarget::m_MsgChain = {NULL, NULL};

/*----------------------------------------------------------------------------
    2014/02/28 功能:  在消息映射数组中搜索与ID对应的消息处理函数并执行
----------------------------------------------------------------------------*/
void CmdTarget::MessageHandler(MessageID A_Msg)
{
    // 从当前窗口中获取消息映射数组, 查找是否有对应的消息处理函数
    const MessageChain* pMsgChain = GetMsgChain();
    while(pMsgChain != NULL)
    {
        MsgMapPtr pEntries = pMsgChain->m_MessageEntries;
        if(pEntries != NULL)
        {
            for(int i = 0; ; i++)
            {
                if(pEntries[i].m_Msg == 0)
                    break;

                if(pEntries[i].m_Msg == A_Msg)
                {
                    // 调用消息处理函数(这句稍稍有点复杂)
                    (this->*pEntries[i].m_pFunc)(); 
                    return;
                }
            }
        }
        // 子类没有消息函数, 再从父类中查找
        pMsgChain = pMsgChain->m_pParent;
    }
}

/*----------------------------------------------------------------------------
    2014/02/28 功能:  类中声明消息映射相关的变量与函数
----------------------------------------------------------------------------*/
#define MY_DECLARE_MESSAGE_MAP()    \
    private:\
        static MsgMap m_MsgMap[];\
        static const MessageChain m_MsgChain;\
    protected:\
        virtual const MessageChain* GetMsgChain();

/*----------------------------------------------------------------------------
    2014/02/28 功能:  开始建立消息映射数组
----------------------------------------------------------------------------*/
#define  MY_BEGIN_MESSAGE_MAP(derived_class, base_class)    \
    const MessageChain MyWindow::m_MsgChain = {&CmdTarget::m_MsgChain, \
    &MyWindow::m_MsgMap[0]};    \
    const MessageChain* MyWindow::GetMsgChain() \
    {return &MyWindow::m_MsgChain;} \
    MsgMap MyWindow::m_MsgMap[] = { 

/*----------------------------------------------------------------------------
    2014/02/28 功能:  结束消息映射数组
    从C++指针中不能获取数组的尺寸,所以把最近一个元素定义成0,就可以明确定位数组结束的位置.
----------------------------------------------------------------------------*/
#define  MY_END_MESSAGE_MAP()   \
        {0, NULL}   \
    };

/*----------------------------------------------------------------------------
    2014/02/28 功能:  添加数组元素的宏
----------------------------------------------------------------------------*/
#define MY_ON_CONTROL(id, func)     {id, (MemberFunc)&func},

/*===========================================================================

    功能:  模拟一个用户定义的窗口  2014/02/28

===========================================================================*/
#define ID_PAINT        0x00000001
#define ID_BUTTON       0xFFFF0001

class MyWindow : public CmdTarget
{
protected:
    //{{AFX_MSG(Derived)
    afx_msg void OnButtonDown();
    afx_msg void OnPaint();
    //}}AFX_MSG
    MY_DECLARE_MESSAGE_MAP() // 声明消息映射相关的成员
};

MY_BEGIN_MESSAGE_MAP(MyWindow, CmdTarget)
//{{AFX_MY_BEGIN_MESSAGE_MAP
    MY_ON_CONTROL(ID_BUTTON, OnButtonDown)  // 成员函数与控件绑定
    MY_ON_CONTROL(ID_PAINT, OnPaint)        // 成员函数与窗口消息绑定
//}}AFX
MY_END_MESSAGE_MAP()

void MyWindow::OnButtonDown()
{
    printf("ButtonDown\n");
}

void MyWindow::OnPaint()
{
    printf("Paint\n");
}

/*===========================================================================

    功能:  主函数  2014/02/28

===========================================================================*/
int main(int argc, char* argv[])
{
    MyWindow oDerived;
    // 模拟由系统消息泵向窗口发送消息
    oDerived.MessageHandler(ID_BUTTON);
    oDerived.MessageHandler(ID_PAINT);
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

[原创]MFC消息映射机制

MFC程序是靠消息映射驱动的,当用户执行鼠标/键盘、移动窗口等操作时,windows系统基于这些动作生成消息并存入系统消息队列。MFC程序执行消息循环,取出属于自己的消息并执行这些消息。MFC处理消息...

MFC中消息映射机制分析

  • 2011-08-03 15:40
  • 46KB
  • 下载

孙鑫MFC消息映射机制的剖析

一,消息映射机制 1,消息响应函数:(例:在CDrawView类响应鼠标左键按下消息)  1)在头文件(DrawView.h)中声明消息响应函数原型。 //{{AFX_MSG(CDrawVi...

MFC消息映射机制的剖析

  • 2012-10-23 22:37
  • 24.26MB
  • 下载

MFC 消息映射机制剖析

MFC的类非常多,继承关系复杂,如何完成MFC巨大的类层次之间消息的传递是一个技术难点,最简单的就是采用虚函数机制,每继承一个类,就覆盖父类的函数,但问题来了,MFC有上百个类,如果使用虚函数,那么每...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)