自繪控件筆記

不選擇在 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。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章