在Win32 No-MFC中的消息映射 [英] Message Map in Win32 No-MFC

查看:108
本文介绍了在Win32 No-MFC中的消息映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



在MFC中;



如何创建类似的结构来处理Win32消息, pre> BEGIN_MESSAGE_MAP(CSkinCtrlTestDlg,CDialog)
// {{AFX_MSG_MAP(CSkinCtrlTestDlg)
ON_BN_CLICKED(IDC_BROWSE,OnBrowse)
ON_BN_CLICKED(IDC_DEFAULTSKIN,OnChangeSkin)
ON_WM_DRAWITEM()
ON_WM_MEASUREITEM()
ON_WM_COMPAREITEM()
ON_BN_CLICKED(IDC_CHECK3,OnCheck3)
//}} AFX_MSG_MAP
END_MESSAGE_MAP()

BEGIN_MESSAGE_MAP宏处理此行为。如何做纯Win32?

解决方案

这是我在 =http://www.zeusedit.com =noreferrer>宙斯程序员编辑:



步骤1:定义几个消息结构以保存Windows消息详细信息:

  typedef struct 
{
MSG味精;
LRESULT lResult;
} xMessage;

struct xWM_COMMAND
{
HWND hwnd;
UINT消息;
WORD ItemID;
WORD NotifyCode;
HWND Ctl;
LRESULT lResult;
};

// - 解包消息缓冲区
#define MSG_UNPACK(var,id,msg)x ## id * var =(x ## id *)(msg);

步骤2:使用几种特殊方法定义基类窗口类:

  class xWindow 
{
protected:
// - windows回调函数
static LRESULT CALLBACK wndProc(HWND hwnd,UINT msg,
WPARAM wParam,
LPARAM lParam);

// - 一个消息分派方法
void dispatch(HWND hwnd,UINT uMessageID,WPARAM wParam,
LPARAM lParam,LRESULT& Result);

// - 命令消息分派的方法
virtual void dispatchToCmdMap(xMessage * pMessage);

// - Windows消息分派的方法
virtual void dispatchToMsgMap(xMessage * pMessage);
};

步骤3:定义几个宏来执行Windows的调度消息:

  #define BEGIN_MSG_MAP \ 
protected:\
virtual void dispatchToMsgMap(xMessage * )\
{\
if(msg-> msg.message == WM_NULL)\
{\
return; \
}

#define MSG_HANDLER(meth,wm_msg)\
else if(msg-> msg.message == wm_msg)\
{ \
this-> meth(msg); \
返回; \
}

#define END_MSG_MAP(base)\
else if(msg-> msg.message == WM_COMMAND)\
{\
this-> dispatchToCmdMap(msg); \
return; \
} \
else if(msg-> msg.message == WM_NOTIFY)\
{\
this-> dispatchToNotifyMap(msg); \
return; \
} \
\
base :: dispatchToMsgMap(msg); \
};

#define BEGIN_CMD_MAP \
virtual void dispatchToCmdMap(xMessage * msg)\
{\
MSG_UNPACK(Cmd,WM_COMMAND,msg); \
\
if(Cmd-> ItemID == 0)\
{\
/ *不允许* / \
}

#define CMD_HANDLER(meth,cmd_id)\
else if(Cmd-> ItemID == cmd_id)\
{\
this->甲基(CMD->的ItemID); \
}

#define END_CMD_MAP(base)\
else \
{\
base :: dispatchToCmdMap(msg); \
} \
};

步骤4:定义调度方法:

  void xWindow :: dispatch(HWND,UINT uMessageID,WPARAM wParam,
LPARAM lParam,LRESULT& Result)
{
x消息消息;

// - 建立一个消息包
message.msg.message = uMessageID;
message.msg.wParam = wParam;
message.msg.lParam = lParam;
message.lResult = 0;

// - 发送消息
this-> dispatchToMsgMap(& message);
}

步骤5:定义静态窗口过程方法(注意:此类方法将被用作窗口类的窗口过程,当该类首次注册时):

  LRESULT CALLBACK xWindow :: wndProc(HWND hwnd,UINT msg,
WPARAM wParam,
LPARAM lParam)
{
LRESULT lResult = 0;

// - 查找创建消息
if(msg == WM_NCCREATE)
{
CREATESTRUCT * pCreateData =(CREATESTRUCT *)lParam;

// - 获取
中的窗口对象xWindow * pWindow =(xWindow)pCreateData-> lpCreateParams;

if(pWindow)
{
// - 将窗口对象附加到hwnd
SetWindowLong(hwnd,pWindow);

// - 让窗口对象调度消息
pWindow-> dispatch(hwnd,msg,wParam,lParam,lResult);
}
else
{
// - 将消息留给Windows
lResult = DefWindowProc(hwnd,msg,wParam,lParam);
}
}
else if(hwnd)
{
// - 获取附加到hwnd的对象
xWindow * pWindow =(xWindow * )GetWindowLong(HWND);

// - 检查我们是否有一个对象窗口附加到句柄
if(pWindow)
{
// - 让窗口对象发送消息
pWindow-> dispatch(hwnd,msg,wParam,lParam,lResult);
}
else
{
// - 将消息留给Windows
lResult = :: DefWindowProc(hwnd,msg,wParam,lParam);
}
}

return lResult;
}

现在,使用这个基类可能是定义一个新的窗口类,如下所示:

  class MyWindow:public xWindow 
{
protected:
// - WM_COMMAND消息处理程序
virtual void onAdd(int);
virtual void onDelete(int);

// - WM_CLOSE消息处理程序
virtual void onClose(xMessage * pMessage);

// - WM_SIZE消息处理程序
virtual void onSize(xMessage * pMessage);

public:
// - ctor和dtor
MyWindow();
virtual〜MyWindow();

BEGIN_MSG_MAP
// - 命令消息处理程序
CMD_HANDLER(onAdd,IDPB_ADD)
CMD_HANDLER(onDelete,IDPB_DELETE)

// - 其他消息处理
MSG_HANDLER(onClose,WM_CLOSE)
MSG_HANDLER(onSize,WM_SIZE)
END_MSG_MAP(xWindow)
};

编辑:此代码的工作原理。



了解这段代码如何工作的秘诀是记住 xWindow 类中的 wndProc ,只不过是一个 Win32 Win32窗口注册时,窗口过程传递给 RegisterClassEx



现在,如果您查看 wndProc 代码,您将看到它有一些设置和检查,但通常它只发送Windows消息到调度方法。



调度方法更简单,因为它只是将Windows消息打包成易于移动的 结构,然后将其发送到 dispatchToMsgMap 方法。



现在看看您将看到的 MyWindow 类这个代码:

  BEGIN_MSG_MAP 
// - 命令消息处理程序
CMD_HANDLER(onAdd,IDPB_ADD)
CMD_HANDLER(onDelete,IDPB_DELETE)

// - 其他消息处理
MSG_HANDLER(onClose,WM_CLOSE)
MSG_HANDLER(onSize,WM_SIZE)
END_MSG_MAP xWindow)

这段代码只是使用前面定义的宏。如果仔细看看这些宏,您将看到上面的代码实际上是创建一个 dispatchToMsgMap 方法。这是由 dispatch 方法调用的完全相同的 dispatchToMsgMap 方法。



我知道这种处理Windows消息的方法可以正常工作,因为在 Zeus for Windows 编辑器。


How could I create similar structure to handle Win32 Messages like it is in MFC?

In MFC;

BEGIN_MESSAGE_MAP(CSkinCtrlTestDlg, CDialog)
    //{{AFX_MSG_MAP(CSkinCtrlTestDlg)
    ON_BN_CLICKED(IDC_BROWSE, OnBrowse)
    ON_BN_CLICKED(IDC_DEFAULTSKIN, OnChangeSkin)
    ON_WM_DRAWITEM()
    ON_WM_MEASUREITEM()
    ON_WM_COMPAREITEM()
    ON_BN_CLICKED(IDC_CHECK3, OnCheck3)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

BEGIN_MESSAGE_MAP macro handles this behaviour. What to do for pure Win32?

解决方案

Here is a breif summary of the code I use to do this in the Zeus programmer's editor:

Step 1: Define a couple of message structure to hold the Windows message details:

typedef struct
{
  MSG     msg;
  LRESULT lResult;
} xMessage;

struct xWM_COMMAND
{
  HWND hwnd;
  UINT Msg;
  WORD ItemID;
  WORD NotifyCode;
  HWND Ctl;
  LRESULT lResult;
};

//-- unpack a message buffer
#define MSG_UNPACK(var, id, msg) x##id *var = (x##id *)(msg);

Step 2: Define a base window class with a few special methods:

class xWindow
{
protected:
  //-- windows callback function
  static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, 
                                  WPARAM wParam, 
                                  LPARAM lParam);

  //-- a message dispatch method
  void dispatch(HWND hwnd, UINT uMessageID, WPARAM wParam, 
                LPARAM lParam, LRESULT &Result);

  //-- method for command message dispatching
  virtual void dispatchToCmdMap(xMessage *pMessage);

  //-- method for windows message dispatching
  virtual void dispatchToMsgMap(xMessage *pMessage);
};

Step 3: Define a few macros to do the dispatching of the Windows messages:

#define BEGIN_MSG_MAP                          \
   protected:                                  \
   virtual void dispatchToMsgMap(xMessage *msg)\
   {                                           \
     if (msg->msg.message == WM_NULL)          \
     {                                         \
       return;                                 \
     }

#define MSG_HANDLER(meth, wm_msg)              \
     else if (msg->msg.message == wm_msg)      \
     {                                         \
       this->meth(msg);                        \
       return;                                 \
     }

#define END_MSG_MAP(base)                      \
     else if (msg->msg.message == WM_COMMAND)  \
     {                                         \                       
       this->dispatchToCmdMap(msg);            \                       
       return;                                 \                       
     }                                         \                       
     else if (msg->msg.message == WM_NOTIFY)   \                       
     {                                         \                       
       this->dispatchToNotifyMap(msg);         \                       
       return;                                 \                       
     }                                         \                       
                                               \                       
     base::dispatchToMsgMap(msg);              \                       
   };

#define BEGIN_CMD_MAP                          \
   virtual void dispatchToCmdMap(xMessage *msg)\
   {                                           \                              
     MSG_UNPACK(Cmd, WM_COMMAND, msg);         \                              
                                               \                              
     if (Cmd->ItemID == 0)                     \                              
     {                                         \                              
        /* not allowed */                      \                              
     }                                                                        

#define CMD_HANDLER(meth, cmd_id)              \
     else if (Cmd->ItemID == cmd_id)           \
     {                                         \                                
       this->meth(Cmd->ItemID);                \                                
     }                                                                          

#define END_CMD_MAP(base)                      \
     else                                      \                              
     {                                         \                              
       base::dispatchToCmdMap(msg);        \                              
     }                                         \                              
   };

Step 4: Define the dispatcher method:

void xWindow::dispatch(HWND, UINT uMessageID, WPARAM wParam, 
                       LPARAM lParam, LRESULT &Result)
{
  xMessage message;

  //-- build up a message packet
  message.msg.message = uMessageID;
  message.msg.wParam  = wParam;
  message.msg.lParam  = lParam;
  message.lResult     = 0;

  //-- dispatch the message
  this->dispatchToMsgMap(&message);
}

Step 5: Define the static window procedure method (NOTE: this method will need to be used as the Window procedure of the window class when the class is first registered):

LRESULT CALLBACK xWindow::wndProc(HWND hwnd, UINT msg, 
                                  WPARAM wParam, 
                                  LPARAM lParam)
{
  LRESULT lResult = 0;

  //-- look for the creation message
  if (msg == WM_NCCREATE)
  {
    CREATESTRUCT *pCreateData = (CREATESTRUCT*)lParam;

    //-- get the window object passed in
    xWindow *pWindow = (xWindow)pCreateData->lpCreateParams;

    if (pWindow)
    {
      //-- attach the window object to the hwnd
      SetWindowLong(hwnd, pWindow);

      //-- let the window object dispatch the message
      pWindow->dispatch(hwnd, msg, wParam, lParam, lResult);
    }
    else
    {
      //-- leave the message to windows
      lResult = DefWindowProc(hwnd, msg, wParam, lParam);
    }
  }
  else if (hwnd)
  {
    //-- get the object attached to the hwnd
    xWindow *pWindow = (xWindow *)GetWindowLong(hwnd);

    //-- check to see if we have an object window attached to the handle
    if (pWindow)
    {
      //-- let the window object dispatch the message
      pWindow->dispatch(hwnd, msg, wParam, lParam, lResult);
    }
    else
    {
      //-- leave the message to windows
      lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
    }
  }

  return lResult;
}

Now, using this base class it is possible to define a new window class that will look like this:

class MyWindow : public xWindow
{
protected:  
  //-- the WM_COMMAND message handlers
  virtual void onAdd(int);
  virtual void onDelete(int);

  //-- the WM_CLOSE message handler
  virtual void onClose(xMessage *pMessage);

  //-- the WM_SIZE message handler
  virtual void onSize(xMessage *pMessage);

public:
  //-- ctor and dtor
  MyWindow();
  virtual ~MyWindow();

  BEGIN_MSG_MAP
    //-- command message handlers
    CMD_HANDLER(onAdd   , IDPB_ADD   )
    CMD_HANDLER(onDelete, IDPB_DELETE)

    //-- other message handling
    MSG_HANDLER(onClose , WM_CLOSE)
    MSG_HANDLER(onSize  , WM_SIZE )
  END_MSG_MAP(xWindow)
};

Edit: How this code works.

The secret to understanding how this code works is to remember the wndProc in the xWindow class is nothing but a Win32 Window procedure passed to RegisterClassEx when the Win32 Window is registered.

Now if you look at the wndProc code you will see it does a bit of setting up and checking but generally it does nothing more than send the Windows message to the dispatch method.

The dispatch method is even simpler as it does nothing more than pack the Windows message into an easy to move structure and then sends it off to the dispatchToMsgMap method.

Now look at the MyWindow class an you will see this code:

BEGIN_MSG_MAP    
   //-- command message handlers    
   CMD_HANDLER(onAdd   , IDPB_ADD   )    
   CMD_HANDLER(onDelete, IDPB_DELETE)    

   //-- other message handling    
   MSG_HANDLER(onClose , WM_CLOSE)    
   MSG_HANDLER(onSize  , WM_SIZE )  
END_MSG_MAP(xWindow)

This code is just using the macros defined earlier. If you take a close look at these macros you will see the code above is in fact creating a dispatchToMsgMap method. This is the exact same dispatchToMsgMap method that was called by the dispatch method.

I know this method of handling Windows messages does work as I use this exact same approach in the Zeus for Windows editor.

这篇关于在Win32 No-MFC中的消息映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆