在分流器那篇文章中说到窗口子类化什么的就造成了要使用不同的宏,我一直没看明白为什么说在对话框中要那样做.
原文地址
http://blog.csdn.net/hopkins9961629/archive/2006/01/25/588184.aspx 原文不懂的地方如下:
以上四重,是消息分离器的基本使用,但,这不完整,消息分离器主要应用在对话框消息处理中。
这里,窗口子类化是我们经常使用的手段,这也可以通过消息分流器实现,
第五重
LRESULT CALLBACK Dlg_Proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
HANDLE_MSG(hwnd, WM_INITDIALO , Cls_OnInitDialog); // 不能直接使用HANDLE_MSG宏
HANDLE_MSG(hwnd, WM_COMMAND, Cls_OnCommand); // 不能直接使用HANDLE_MSG宏
}
return false;
}
由于是窗口子类化,所以,最后,返回的是false,以表明,如果没有约定响应的消息,
则返回父亲窗口false,如果有,则返回ture,这是与前四重不同的地方。
一般情况下,对话框过程函数应该在处理了消息的情况下返回TRUE,如果没有处理,则返回FALSE。
如果对话框过程返回了FALSE,那么对话框管理器为这条消息准备默认的对话操作。
但是,这其中有错误,因为有的消息,需要单独处理。单独处理的消息列表见SetDlgMsgResult宏。
为什么不能使用?
查阅msdn发现在对话框的过程函数和window窗口有个不一样地方是在返回值上面。如果消息被处理,那么它将返回true,而如果没有处理,那么将返回false,让对话框管理器(DialogBox Manager)处理。如果想有自己的返回值的话,那么使用子类化SetWindowLong函数中的DWL_MSGRESULT标识符改变,但是之后还是要返回true。但是有一些消息不遵守上诉约定,而直接返回他们的返回值,这些消息如下:
WM_CHARTOITEM
WM_COMPAREITEM
WM_CTLCOLORBTN
WM_CTLCOLORDLG
WM_CTLCOLOREDIT
WM_CTLCOLORLISTBOX
WM_CTLCOLORSCROLLBAR
WM_CTLCOLORSTATIC
WM_INITDIALOG
WM_QUERYDRAGICON
WM_VKEYTOITEM
了解了这些之后看看那些定义的分流器宏
消息处理宏:
#define HANDLE_MSG(hwnd, message, fn) \
case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))
WM_COMMAND宏的消息分流器定义:
#define HANDLE_WM_COMMAND(hwnd, wParam, lParam, fn) \
((fn)((hwnd), (int)(LOWORD(wParam)), (HWND)(lParam), (UINT)HIWORD(wParam)), 0L)
我们可以看到如果在对话框的过程函数中直接使用HANDLE_MSG的话,我们使用WM_COMMAND消息,那么根据HANDLE_WM_COMMAND宏,我们可以知道它会返回0L,0在windef.h中定义为false,那么我们明明处理这个wm_command消息,但是我们告诉对话框管理器是没有处理,让对话框管理器处理。所以如果这里直接使用HANDLE_MSG是不可行的,那么我们就使用一个宏改进它
#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))
这样就可以解决这个问题了
像Jeffrey Richter 高手自己也定义了一个宏:
#define chHANDLE_DLGMSG(hWnd, message, fn) \
case (message): return (SetDlgMsgResult(hWnd, uMsg, \
HANDLE_##message((hWnd), (wParam), (lParam), (fn))))
这样可以更方便的在对话框过程函数中使用消息分流器了!
posted on 2009-11-27 21:34
Mr.Johnson 阅读(469)
评论(0) 编辑 收藏 引用 所属分类:
Windows编程