Windows的消息分流器

一重:

LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

{

switch(msg)

{

   case WM_CREATE:

   return HANDLE_WM_CREATE(hwnd, wParam, lParam, Cls_OnCreate);

   case WM_PAINT:

   return HANDLE_WM_PAINT(hwnd, wParam, lParam, Cls_OnPaint);

   case WM_DESTROY:

   return HANDLE_WM_DESTROY(hwnd, wParam, lParam, Cls_OnDestroy);

}

return DefWindowProc(hwnd, msg, wParam, lParam);

}

这里的HANDLE_WM_CREATE,HANDLE_WM_PAINT,HANDLE_WM_DESTROY就是消息分流器。

与消息不同之处就是在前面增加了“HANDLE_”字符,windows的消息分流器就是这样的模样。

它的本质就是宏定义。

其中的四个参数有三个都是从本函数的入口参数中直接得到的,即为hwnd, wParam, lParam。

只有第四的参数是表明调用的函数。

消息分流器是在windowsx.h文件中定义的。由此,可以看出第四个参数是调用的函数,其定义如下:

#define HANDLE_WM_CREATE(hwnd, wParam, lParam, fn) ((fn)((hwnd), (LPCREATESTRUCT)(lParam)) 0L (LRESULT)-1L)

#define HANDLE_WM_PAINT(hwnd, wParam, lParam, fn) ((fn)(hwnd), 0L)

#define HANDLE_WM_DESTROYCLIPBOARD(hwnd, wParam, lParam, fn) ((fn)(hwnd), 0L)

 

二重:

更进一步我们可以将这些相近的消息分流器统一为一个宏HANDLE_MSG

HANDLE_MSG也是一个宏,它在windowsx.h中定义,如下:

#define HANDLE_MSG(hwnd, message, fn)  \

case (message): return HANDLE_##message \

((hwnd), (wParam), (lParam), (fn))

 

三重:

上面这样的HANDLE_MSG写法是可能导致错误的,这是因为DialogProc与WndProc不同,前者要返回True或者False,后者成功时返回0

 

在对话框的窗口子类化的过程,有些特定的消息会需要一个特定的返回值,msdn中对于对话框消息处理过程的返回值有如下说明:

  一般情况下,对话框过程函数应该在处理了消息的情况下返回TRUE,如果没有处理,则返回FALSE。如果对话框过程返回了FALSE,那么对话框管理器为这条消息准备默认的对话操作。

例如我们的WM_COMMAND消息,我们的Cls_OnCommand由于是个void型的函数,是没有返回值的,因此windows默认这种消息处理过程必须返回一个0值,而返回0值不就表示我们的消息过程不处理这个消息么?这个矛盾是HANDLE_MSG无法解决的。怎么办才能使消息过程在处理完WM_COMMAND消息之后正确的返回一个TRUE呢? 答案是使用另一个windowsx.h中的宏:SetDlgMsgResult(hwnd, msg, result)

#define     SetDlgMsgResult(hwnd, msg, result) (( /
        (msg) == WM_CTLCOLORMSGBOX      || /
        (msg) == WM_CTLCOLOREDIT        || /
        (msg) == WM_CTLCOLORLISTBOX     || /
        (msg) == WM_CTLCOLORBTN         || /
        (msg) == WM_CTLCOLORDLG         || /
        (msg) == WM_CTLCOLORSCROLLBAR   || /
        (msg) == WM_CTLCOLORSTATIC      || /
        (msg) == WM_COMPAREITEM         || /
        (msg) == WM_VKEYTOITEM          || /
        (msg) == WM_CHARTOITEM          || /
        (msg) == WM_QUERYDRAGICON       || /
        (msg) == WM_INITDIALOG             /
    ) ? (BOOL)(result) : (SetWindowLongPtr((hwnd), DWLP_MSGRESULT, (LPARAM)(LRESULT)(result)), TRUE))

一旦我们设计的消息不是该函数提供的消息列表中的一个,如WM_COMMAND,它就会通过SetWindowLongPtr来修改它的返回值,让它正确的返回true(对于API SetWindowLongPtr怎么来修改这个返回值还无法理解

 

四重:

综上所述,我们可以采用一个大牛Jeffrey写出来的一个宏chHANDLE_DLGMSG来作为我们的对话框消息分流器:

#define chHANDLE_DLGMSG(hwnd, message, fn) \

case (message) : return                                             \

 (SetDlgMsgResult (hwnd,uMsg,HANDLE_##message((hwnd),    \

         (wParam), (lParam), (fn)))))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值