who*_*hoi 5 winapi message map
我怎么能创建类似的结构来处理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()
Run Code Online (Sandbox Code Playgroud)
BEGIN_MESSAGE_MAP宏处理此行为.怎么做纯Win32?
jus*_*sij 13
以下是我在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);
Run Code Online (Sandbox Code Playgroud)
第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, 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);
};
Run Code Online (Sandbox Code Playgroud)
步骤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); \
} \
};
Run Code Online (Sandbox Code Playgroud)
第4步:定义调度程序方法:
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);
}
Run Code Online (Sandbox Code Playgroud)
步骤5:定义静态窗口过程方法(注意:首次注册类时,此方法需要用作窗口类的Window过程):
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;
}
Run Code Online (Sandbox Code Playgroud)
现在,使用这个基类可以定义一个如下所示的新窗口类:
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)
};
Run Code Online (Sandbox Code Playgroud)
编辑:此代码的工作原理.
秘密理解这个代码是如何工作的是要记住的WndProc在Xwindow的类也不过是Win32的传递给窗口过程RegisterClassEx当Win32的窗口登记.
现在,如果您查看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)
Run Code Online (Sandbox Code Playgroud)
此代码仅使用前面定义的宏.如果你仔细看看这些宏,你会发现上面的代码实际上是在创建一个dispatchToMsgMap方法.这与dispatch方法调用的dispatchToMsgMap方法完全相同.
我知道这种处理Windows消息的方法确实有效,因为我在Zeus for Windows编辑器中使用了这种完全相同的方法.