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六大核心机制

我们选择了C++,主要是因为它够艺术、够自由,使用它我们可以实现各种想法,而MFC将多种可灵活使用的功能封装起来,我们岂能忍受这种“黑盒”操作?于是研究分析MFC的核心机制成为必然。        ...
  • ligand
  • ligand
  • 2015年11月15日 12:32
  • 3869

MFC六大机制之三:消息映射机制

上篇我们通过重写WindowProc函数来处理消息,今天我们采用下面的方法实现同样的功能  1.建一个win32简单应用程序,不要认为这样就不能写出MFC程序,因为是不是MFC程序取决于调没调MFC...
  • meetings
  • meetings
  • 2015年06月28日 23:12
  • 2116

VS2013/MFC编程入门之四(MFC消息映射机制概述)

上一讲为大家简单分析了MFC应用程序框架,这一讲是关于MFC消息映射机制的内容。        前面已经说过,Windows应用程序是消息驱动的。在MFC软件开发中,界面操作或者线程之间通信都会...
  • zhaoyinhui0802
  • zhaoyinhui0802
  • 2016年11月23日 11:00
  • 1824

MFC的六大核心机制概述

这一篇主要讲解一下MFC中的6个主要的关键技术,整个Application Framework其实从本质上来说都是建立在这6个关键技术上的。所以能够了解它们的原理对理解MFC整个框架和程序设计有非常大...
  • cytj129
  • cytj129
  • 2015年04月24日 17:39
  • 1275

MFC的消息处理机制及相关的宏

这段话是我在中文维基的“类成员函数指针”词条写的: MFC类体系中,Windows消息传递处理机制是基于CCmdTarget类及其派生类的静态数据成员与静态成员函数GetThisMessageMap(...
  • ligand
  • ligand
  • 2015年11月15日 08:42
  • 1358

MFC消息映射机制详解

Windows程序和MFC程序是靠消息驱动的,他们对于消息的处理本质上是相同的。只是Windows程序对于消息处理的过程十分清晰明了,MFC程序则掩盖了消息处理的过程,以消息映射的方式呈现在开发者面前...
  • tercel_zhang
  • tercel_zhang
  • 2015年10月21日 13:57
  • 1179

MFC---理解Windows消息循环机制

 理解消息循环和整个消息传送机制对Windows编程来说非常重要。如果对消息处理的整个过程不了解,在windows编程中会遇到很多令人困惑的地方。 什么是消息(Message) 每个...
  • gggg_ggg
  • gggg_ggg
  • 2014年08月22日 14:30
  • 1202

透过宏定义了解MFC的消息响应机制

消息系统是MFC的重要组成部分。MFC的消息响应机制并不复杂,而且MFC的开发环境 Visual Studio来供了非常好的自动化工具,自动生成代码。MFC也定义了丰富的宏来简化消息响应的代码。这使得...
  • wzy198852
  • wzy198852
  • 2014年03月21日 17:40
  • 612

MFC(五)运行时类信息机制 动态创建机制 序列化机制

世上的事,会则不难,难则不会~ WIN32学习起来也并不简单,而到了MFC,框架6大机制相当复杂,学习就更加困难。 迎着困难向上~其实也就没有那么难了~......
  • baidu_24190413
  • baidu_24190413
  • 2015年11月08日 15:48
  • 658

Windows消息传递机制详解

Windows是一个消息(Message)驱动系统。Windows的消息提供了应用程序之间、应用程序与Windows系统之间进行通信的手段。应用程序想要实现的功能由消息来触发,并且靠对消息的响应和处理...
  • Evankaka
  • Evankaka
  • 2015年03月19日 13:44
  • 5374
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:MFC的消息映射机制
举报原因:
原因补充:

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