WTL 中的COwnerDraw应用

COwnerDraw是WTL为用户提供为自画和定制外观控件的模板类,最近被这个类搞的晕头转向,其实关键的东西也只是那么一点点.

    自画需要响应四个消息:WM_MEASUREITEM, WM_DRAWITEM, WM_COMPAREITEM, 和WM_DELETEITEM,在atlframe.h头文件中定义的COwnerDraw类可以简化这些工作,使用这个类就不需要处理这四个消息,你只需将消息链入COwnerDraw,它会调用你的类中的重载函数。

       如何将消息链入COwnerDraw取决与你是否将消息反射给控件,两种方法有些不同。

       CHAIN_MSG_MAP(COwnerDraw<CSomeDlg>)

       上面这种直接将消息链入COwnerDraw

       CHAIN_MSG_MAP_ALT(COwnerDraw<CSomeButtonImpl>,  1) 
       DEFAULT_REFLECTION_HANDLER()

       如果你想要控件自己处理这些消息,你需要使用CHAIN_MSG_MAP_ALT宏将消息链入ALT_MSG_MAP(1)部分,如上.

        上面这些网上的教程都有.下面我要说的就是教程里没有的(太简单了,应该属于常识,人家的教程就没写进去,一致于像我这样的菜鸟搞了很长的时间,希望能帮助和我一样的菜鸟,呵呵)

         首先,想要把你自己实现个控件类和资源编辑器中的控件联系起来,你不光要做的是 attach()(用这个关联有问题,原因还不知道)和 SubclassWindow(),你还得必须把你控件的属性中的Owner Draw的属性设为true,才能和你控件关联起来,做了例子试试吧!(是不是太简单了,我用了两天时间才发现的).

       第二个关键,现在的运行程序发现Owner Draw的属性为true的控件都显示不出来,一个原因是你重载的DrawItem(LPDRAWITEMSTRUCT lpdis)函数是个空函数,一般情况下如果你要自画控件是应该在这里用gdi画的,可是你发现你已经把所要花的内容写好了,还是看不见.原因是我们的程序缺少一个宏   

  BEGIN_MSG_MAP(CMainDlg)
     REFLECT_NOTIFICATIONS()(少了这个宏)
 END_MSG_MAP() 

这是这个宏的全貌

#define REFLECT_NOTIFICATIONS() \
 { \
  bHandled = TRUE; \
  lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
  if(bHandled) \
   return TRUE; \
 }

这个宏调用的是函数 CWindowImplRoot::ReflectNotifications。这个函数通过参数取得发送事件控件的窗体句柄,并通过该句柄将事件发还给控件.

最后还有一点不是所有的控件都可以用COwnerDraw来自绘控件的,只有5个控件(MENU,LISTBOX,COMBOBOX,BUTTON,STATIC)支持.

猜你喜欢

转载自blog.csdn.net/csdn9990/article/details/82897131
WTL