class CComboBoxEx:public CWindowImpl< CComboBoxEx, CComboBox>
于是,添加DEFAULT_REFLECTION_HANDLER宏得操作通过了编译,但是事实证明,不合逻辑的想法很难带来正确的结果,不仅重画事件没有被触发,修改后,在控件类析构时碰到了ATL的断言。
错误提示是,类在窗体句柄销毁之前被析构。
这个错误到让我们想到原书中提到的一个WTL特性,WTL不会自动销毁窗体句柄,需要自己手工Detach()窗体句柄。既然这样,我们又添加了下面的代码:
~CComboBoxEx() {
Detach();
}
虽然,没有Attach()的Detach()感觉有点怪,可是毕竟ATL的断言不会出现了。但是,问题并没有解决,重画事件还是没有被触发。难道是CMainDlg没有反射事件回来?看看用来反射事件的REFLECT_NOTIFICATIONS宏的代码:
#define REFLECT_NOTIFICATIONS() \
{ \
bHandled = TRUE; \
lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
if(bHandled) \
return TRUE; \
}
参看ATL文件<atlwin.h>
REFLECT_NOTIFICATIONS宏调用的是函数CWindowImplRoot::ReflectNotifications。这个函数通过参数取得发送事件控件的窗体句柄,并通过该句柄将事件发还给控件,代码如下:
template <class TBase>
LRESULT CWindowImplRoot< TBase >::ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
HWND hWndChild = NULL;
switch(uMsg)
{
case WM_COMMAND:
if(lParam != NULL) // not from a menu
hWndChild = (HWND)lParam;
break;
case WM_NOTIFY:
hWndChild = ((LPNMHDR)lParam)->hwndFrom;
break;
case WM_PARENTNOTIFY:
switch(LOWORD(wParam))
{
case WM_CREATE:
case WM_DESTROY:
hWndChild = (HWND)lParam;
break;
default:
hWndChild = GetDlgItem(HIWORD(wParam));
break;
}
break;
case WM_DRAWITEM:
if(wParam) // not from a menu
hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem;
break;
case WM_MEASUREITEM:
if(wParam) // not from a menu
hWndChild = GetDlgItem(((LPMEASUREITEMSTRUCT)lParam)->CtlID);
break;
case WM_COMPAREITEM:
if(wParam) // not from a menu
hWndChild = GetDlgItem(((LPCOMPAREITEMSTRUCT)lParam)->CtlID);
break;
case WM_DELETEITEM:
if(wParam) // not from a menu
hWndChild = GetDlgItem(((LPDELETEITEMSTRUCT)lParam)->CtlID)
(编辑:aniston)
|