winapi – Win32 No-MFC中的消息映射

前端之家收集整理的这篇文章主要介绍了winapi – Win32 No-MFC中的消息映射前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我怎么能创建类似的结构来处理Win32消息,就像在MFC中一样?

在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宏处理此行为.怎么做纯Win32?

以下是我在 Zeus程序员编辑器中执行此操作的代码的简要总结:

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

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);

第2步:使用一些特殊方法定义基本窗口类:

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,LPARAM lParam,LRESULT &Result);

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

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

步骤3:定义一些宏来分派Windows消息:

#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);        \                              
     }                                         \                              
   };

第4步:定义调度程序方法

void xWindow::dispatch(HWND,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);
}

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

LRESULT CALLBACK xWindow::wndProc(HWND hwnd,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,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,lResult);
    }
    else
    {
      //-- leave the message to windows
      lResult = ::DefWindowProc(hwnd,lParam);
    }
  }

  return lResult;
}

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

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)
};

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

理解这段代码如何工作的秘诀是要记住xWindow类中的wndProc只是在注册Win32窗口时传递给RegisterClassEx的Win32 Window程序.

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

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

现在看看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)

代码仅使用前面定义的宏.如果你仔细看看这些宏,你会发现上面的代码实际上是在创建一个dispatchToMsgMap方法.这与dispatch方法调用的dispatchToMsgMap方法完全相同.

我知道这种处理Windows消息的方法确实有效,因为我在Zeus for Windows编辑器中使用了这种完全相同的方法.

原文链接:https://www.f2er.com/windows/441502.html

猜你在找的Windows相关文章