VC 如何用代码实现消息映射

       QT,C#可在代码中关联事件和事件函数,且关联可取,极其方便。反观VC,只能用宏关联,且需程序一开始就关联消息和消息函数,运行中不可取消关联。MFC如此包装很不优雅。在用代码创建控件和菜单,或想用一个消息函数处理多个消息时,我更愿意在代码中作消息映射。VC虽已老朽,但仍有不少公司在用,且还有旧VC项目需维护,因此有必要在此分享“如何用代码实现消息映射”。

       MFC的消息机制,有的博主写得非常详细,这里就不赘述。简单说MFC是利用宏(BEGIN_MESSAGE_MAP,END_MESSAGE_MAP等)将消息和消息函数的关联放在一个数组中,但这个数组是static const类型,无法对数组内容作改动,因此就无法在代码中向该数组添加消息映射。

       如需手动关联,我的做法是,取消消息映射宏,自行消息映射宏向代码中添加的函数,并自定义一个数组,用于保存消息映射,步骤如下:

     1.在头文件中声明一个静态数组
        static std::vector< AFX_MSGMAP_ENTRY> _messageEntries;

     2.在实现文件中定义这个静态数组
        std::vector< AFX_MSGMAP_ENTRY> CDialog_MsgTest::_messageEntries;

     3.将实现文件中那段宏BEGIN_MESSAGE_MAP,END_MESSAGE_MAP删除

     4.实现GetMessageMap函数
      const AFX_MSGMAP* CDialog_MsgTest::GetMessageMap() const 
      {
          return GetThisMessageMap(); 
      }

     5.实现GetThisMessageMap函数
     const AFX_MSGMAP* PASCAL CDialog_MsgTest::GetThisMessageMap()
     {   
        typedef CDialog TheBaseClass;
        if(_messageEntries.size() == 0)    
        {
            AFX_MSGMAP_ENTRY entry = {1, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } ;
            _messageEntries.insert(_messageEntries.begin(),entry);
        }; 

        static AFX_MSGMAP messageMap;
        messageMap.pfnGetBaseMap = &TheBaseClass::GetThisMessageMap;
        messageMap.lpEntries = &_messageEntries[0];    
    
        return &messageMap; 
     }

    6.添加你的消息处理函数,以按钮点击为例
    头文件中加入afx_msg void OnBnClickedButton1();
    并在实现文件实现该函数

    7.实现消息映射
          AFX_MSGMAP_ENTRY entry = { nMessage, nCode, nID, nLastID, nSig, pfn};    
         _messageEntries.insert(_messageEntries.begin(),entry);

        entry中各值如何填,需要参考MFC的消息映射宏的定义,比如ON_COMMAND的定义如下:
       #define ON_COMMAND(id, memberFxn) \
       { WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_v, \
        static_cast<AFX_PMSG> (memberFxn) },
     
      则代码实现消息映射应如下填,以按钮点击为例,
      AFX_MSGMAP_ENTRY entry = { WM_COMMAND, (WORD)BN_CLICKED, (WORD)IDC_BUTTON1, (WORD)IDC_BUTTON1, AfxSigCmd_v,(static_cast< AFX_PMSG > (&CDialog_MsgTest::OnBnClickedButton1)};    
      _messageEntries.insert(_messageEntries.begin(),entry);

   8.取消消息映射
   以上述entry中的各值为条件,在_messageEntries中找到该映射并作移除即可

  作者邮箱:zztolll@163.com

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值