我怎么能创建类似的结构来处理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程序员编辑器中执行此操作的代码的简要总结:
原文链接:https://www.f2er.com/windows/441502.html步骤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编辑器中使用了这种完全相同的方法.