MFC消息处理与SDK消息处理

 

在MFC类实现中,采用消息映射实现对消息的响应,从而改变了在SDK中的循环结构,使得消息的流转更加隐蔽。
在SDK中有分三部分构成:

WNDCLASS wnd;
wnd.lpfnWndProc = WndProc ;  // 首先将回调函数设置好

SDK循环结构,进行消息循环
   while(GetMessage(&msg,NULL,0,0))
   {
    TranslateMessage(&msg);
    DisptachMessage(&msg);
   }
而在另一处有回调函数的实现:
LPRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_CREATE: ... break;
        case WM_PAINT: ... break;
        case WM_LBUTTONDOWN: ... break;
        case WM_LBUTTONUP:... break;
        case WM_MOUSEMOVE:... break;
        case WM_CHAR: ...   break;
        case WM_TIMER: ... break;
        case WM_CLOSE: ... break;
        case WM_DESTROYS: ... break;
        case WM_QUIT: ...  break;
        case WM_COMMAND:
          switch(LOWORD(wParam))
          {
             case ID_XXX: break;
             default: break;
           }
           break;
       default: break;
    }
    DefWindowProc(hWnd,msg,wParam,lParam);
}

消息映射中为:
在MFC类定义结构中申明一个语句:
    DECLARE_MESSAGE_MAP()
然后在全局空间实现中出现使用如下语句进行消息映射:
BEGIN_DECLARE
  ON_WM_LBUTTONDOWM()
  ON_WM_LBUTTONUP()
  ON_WM_MOUSEMOVE()
  ON_WM_PAINT()

  ON_COMMAND(ID,lpFunc)
END_DECALRE

在类成员函数的实现中,将上面的消息映射函数进行实现。常用命令有固定的消息名称:
     ON_WM_LBUTTONDOWN()映射函数为ONLBUTTONDOWN()函数,ON_WM_LBUTTONUP映射函数为LBUTTONUP()函数,ON_WM_MOUSEMOVE()映射函数为ONMOUSEMOVE()函数,ON_WM_PAINT()映射函数为ONPAINT()函数,而ON_COMMAND中的映射函数即为lpFunc函数。

     情况下,消息映射声明不通过手工进行修改,而是在ClassWizard中进行修改,这样修改,可以避免因为手工修改时遗漏某个部分或者是输入时出现的一些小bug。 

    MFC的消息流转为从当前类APP流转到CWndApp,再流转到CWndThread类,在流转到CCmdTarget类,当CCmdTarget类中消息还不符合时,在流转到CWndThread中进行消息匹配。

    虽然MFC消息比较难以理解,以及消息相对比较复杂,但是MFC消息函数的出现,使得对每个消息的实现变得很独立,比SDK中一连串的消息判断要清晰明白的多。

   深入浅出中将MFC中消息映射设置成这么一个结构: 
struct AFX_MSGMAP
{
AFX_MSGMAP* pBaseMessageMap;
AFX_MSGMAP_ENTRY* lpEntries;
};
struct AFX_MSGMAP_ENTRY // MFC 4.0 format
{
UINT nMessage; // windows message
UINT nCode; // control code or WM_NOTIFY code
UINT nID; // control ID (or 0 for windows messages)
UINT nLastID; // used for entries specifying a range of control id's
UINT nSig; // signature type (action) or pointer to message #
AFX_PMSG pfn; // routine to call (or special value)
};
typedef void (CCmdTarget::*AFX_PMSG)(void);
#define DECLARE_MESSAGE_MAP() \
static AFX_MSGMAP_ENTRY _messageEntries[]; \
static AFX_MSGMAP messageMap; \
virtual AFX_MSGMAP* GetMessageMap() const;
其中的AFX_MSGMAP_ENTRY 又是另一个数据结构:
其中的AFX_PMSG 定义为函数指针:
然后我们定义一个宏:
#define DECLARE_MESSAGE_MAP() \
static AFX_MSGMAP_ENTRY _messageEntries[]; \
static AFX_MSGMAP messageMap; \
这个数据结构的填充有三个宏来实现:
#define BEGIN_MESSAGE_MAP(theClass, baseClass) \
AFX_MSGMAP* theClass::GetMessageMap() const \
{ return &theClass::messageMap; } \
AFX_MSGMAP theClass::messageMap = \
{ &(baseClass::messageMap), \
(AFX_MSGMAP_ENTRY*) &(theClass::_messageEntries) }; \
AFX_MSGMAP_ENTRY theClass::_messageEntries[] = \
{
#define ON_COMMAND(id, memberFxn) \
{ WM_COMMAND, 0, (WORD)id, (WORD)id, AfxSig_vv, (AFX_PMSG)memberFxn },
#define END_MESSAGE_MAP() \
{ 0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
rtual AFX_MSGMAP* GetMessageMap() const;
};

/*
*
* Copyright (c) 2011 Ubunoon.
* All rights reserved.
*
* email: netubu#gmail.com replace '#' to '@'
* http://www.cnblogs.com/ubunoon
* 欢迎来邮件定制各类验证码识别,条码识别,图像处理等软件
* 推荐不错的珍珠饰品,欢迎订购 * 宜臣珍珠(淡水好珍珠) */
原文地址:https://www.cnblogs.com/ubunoon/p/2058940.html