WTL 控件的消息反射






4.08/5 (5投票s)
2001年1月26日

63989

989
为 Windows 控件的 WTL 包装器实现消息反射。
引言
最近我需要创建一个WTL控件,使其所有功能都在控件内部处理,就像标准的MFC控件一样。
在MFC中,要做到这一点,控件应该通过消息反射从其父窗口接收到自己的通知,这在TN061-TN062中有描述。我没有在当前版本的WTL中找到类似的功能,所以决定自己实现它。我创建了两个宏:第一个宏执行反射——它将收到的某些通知消息发送回其源窗口,第二个宏位于控件包装器中,处理这些消息。也许这种方法有点粗糙,但到目前为止,它有效且简单……;)
这是第一个宏,“reflector”。
#define WM_NOTIFY_REFLECTOR()\ if(uMsg == WM_NOTIFY)\ {\ UINT code = ((LPNMHDR)lParam)->code;\ switch(code)\ {\ case NM_SETCURSOR:\ break;\ default:\ if ((NULL != lParam) &&\ (NULL != ((LPNMHDR)lParam)->hwndFrom))\ {\ BOOL bHandled = ::SendMessage(((LPNMHDR)lParam)->hwndFrom, \ WM_NOTIFY + WM_REFLECT_BASE, wParam, lParam);\ if(bHandled) \ return TRUE; \ };\ };\ }\
要使用它,只需将其放置在任何想要反射WM_NOTIFY
消息的窗口的消息映射中即可。
这是第二个宏,“handler”。
#define NOTIFY_REFLECT_CODE_HANDLER(cd, func) \ { \ if (((WM_NOTIFY + WM_REFLECT_BASE) == uMsg) && \ (NULL != lParam) && \ (cd == ((LPNMHDR)lParam)->code)) \ {\ bHandled = FALSE;\ lResult = func((int)wParam, (LPNMHDR)lParam, bHandled);\ if(bHandled)\ return TRUE;\ }\ }
像使用通常的MESSAGE_HANDLER
或NOTIFY_HANDLER
一样,将其放置在控件的消息映射中。
BEGIN_MSG_MAP(CCusomTreeCtrl) NOTIFY_REFLECT_CODE_HANDLER(TVN_ITEMEXPANDING, OnExpand) END_MSG_MAP() LRESULT OnExpand(int idCtrl, LPNMHDR pnmh, BOOL& bHandled) { // disable expanding LPNMTREEVIEW pnmtv = (LPNMTREEVIEW) pnmh; if (pnmtv->action == TVE_EXPAND) { bHandled = TRUE; return 1; } return 0; }
别忘了将包含宏的头文件包含到stdafx.h中。
我怀疑在这个实现中遗漏了很多重要的东西,但对于我的需求来说,它已经足够了。如果您认为可以改进它,请随时进行改进或告诉我如何改进。