自绘控件笔记

不选择在 PreSubclassWindow 中作“初始化”工作是因为用户可能在使用中改变属性,必须在一个经常进入的地方检查是否要重新“初始化”。把这项工作放到和绘制有关的消息响应函数里则父窗口一个 RedrawWindow() 就可以引起重新“初始化”。
 
一般步骤:
1.派生控件子类
2.添加 PreTranslateMessage
3.进行常规操作记下消息类型
4.在子类里处理消息
 
MFC的 CStatic 控件无法有效 SS_OWNERDRAW 属性,从而无法响应 OnDrawItem。
按MSDN SDK中的static控件可以使能 SS_OWNERDRAW 并发送 WM_DRAWITEM 消息。
经测试 CStatic 控件可利用的只有 WM_PAINT 消息。
 
设有 BS_OWNERDRAW 属性的 CButton 控件先响应 OnEraseBkgnd 再响应 DrawItem。
因此调整窗口尺寸等“初始化”工作可以放再 OnEraseBkgnd 里完成。
 
CProgressCtrl 控件通过 SetPos 、StepIt 绘制,更改进度值不会触发 OnEraseBkgnd 消息但至少会有一次 OnEraseBkgnd,可以利用来作初始化。OnPaint 不完成绘制工作,截获该消息默认的绘制将停止。
 
CSliderCtrl 绘制行为类似 CProgressCtrl,截获 OnPaint 默认不绘制,但状态改变时会触发 OnPaint 消息。OnEraseBkgnd 可以用来作初始化。OnTimer 在点击轨道时触发,每500ms一次,用来模拟 PageDown/Up,在鼠标放开时timer被kill掉。如果鼠标恰好在当前位置按下则不触发 OnTimer,拖曳滑块不触发 OnTimer。
 
CMenu 不是 CWnd 的子类但有纯虚的 MeasureItem 和 DrawItem,绘制工作能且只能依赖它们。菜单风格包括 整体背景风格、菜单项风格、文字风格,尺寸参数包括 菜单项尺寸、菜单项图标尺寸、文字尺寸。以上种种还因菜单项状态不同改变。
MEASUREITEMSTRUCT 和 DRAWITEMSTRUCT 中的 itemData 在 MF_OWNERDRAW 时都是取自 AppendMenu 、InsertMenu 、ModifyMenu 的最后一个参数,所以不得不有一个结构专门管理菜单项类型、文字、图像等信息。
使用 SetMenuInfo、SetMenuItemInfo、GetMenuInfo、GetMenuItemInfo 可以方便的管理菜单信息,但要实现自绘必须有 MF_OWNERDRAW 属性,因此用一个自定义结构管理菜单项的若干重要信息仍是有意义的。
自绘按钮在 MeasureItem 或 DrawItem 里设断点会引起windows菜单显示异常!折腾了很久以为是我的问题呢!
GDI+ new 出的 Bitmap 对象竟然会使用相同的地址!?而且就算地址不同也有冲突?难道不能存储大量的 Bitmap 对象吗?? GdiAlloc 和 GdipCreateBitmapFrom*** 究竟怎么管理内存,new 出的对象不 delete 也不会有任何问题, 文档太少!
CreateMenu 和 CreatePopupMenu 的绘图方式有差异,一定要确定到底是要哪种菜单。
支持子菜单需要动态创建、删除 CSkinMenu 实例,如果用Load方式载入按钮爬一遍即可;如果Insert方式加入的子菜单则由用户决定是否拓展,换言之应不作特殊处理。另外Detach、 DestroyMenu、RemoveMenu 都应处理被扩展的子菜单。
 
CScrollBar 的消息反射OnVscroll、OnHscroll里设置pos是没有用的,大概反射消息只是用来通知不是用来操作。关于Scroll Bar的详细状态可以用GetScrollBarInfo获得。
 
CListBox的OwnerDraw属性只能在创建的时候指定,不能在PreSubclassWindow里用ModifyStyle改变。 而且如果需要触发MeasureItem必须把OwnerDraw设成Variable,Fix时MeasureItem不被调用只能使用 SetItemHeight设置高度。
 
CComboBox的edit部分由OnPaint控制,输入文字是发出OnEditChange,通过列表改变时发出 OnSelchange。list部分由DrawItem控制,创立时必须有OwnerDraw风格。但CListBox似乎不能触发 MeasureItem。


你可能感兴趣的:(笔记)