WTL 中使用 COwnerDraw<T> 類 自繪 List Box
WTL 中的 COwnerDraw<T> 提供對以下四個自繪訊息的支援, 在WTL 中不需要手動新增這些訊息對映, 只需要繼承這 COwnerDraw<T> 然後重寫對應的方法就行了
- WM_DRAWITEM
- WM_MEASUREITEM
- WM_COMPAREITEM
- WM_DELETEITEM
button,combo box, list box, menu, tab 都可以使用 COwnerDraw<T> 來進行自繪
下面以 List Box 來演示
一, 修改 List Box 的 Style
在對話方塊資源編輯器中編輯對話方塊, 新增入 List Box, 修改風格 Owner Draw 為 Fixed, 這個操作相當於給 List Box 加入 LBS_OWNERDRAWFIXED style, 帶這種風格的 List Box 在每次需要繪製內容時, 會發送 WM_DRAWITEM 訊息到父視窗
並且取消 Sort
二, 在父視窗中啟用訊息反射
在自己實現一個自繪的 List Box 類中處理繪製, 而不是在全部在父視窗中處理, 這樣會繪製更符合面向物件思想, 所以我們需要在在 List Box 所在的父視窗類中加入訊息反射
BEGIN_MSG_MAP_EX(CMainDlg) MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) MESSAGE_HANDLER(WM_DESTROY, OnDestroy) //... REFLECT_NOTIFICATIONS(); // 反射 WM_MEASUREITEM 和 WM_DRAWITEM 訊息 END_MSG_MAP()
三, 實現自繪的 List Box
class MyOwnerDrawListImpl :public CWindowImpl<MyListImpl, CListBox> , public COwnerDraw<MyListImpl> { public: BEGIN_MSG_MAP_EX(MyListImpl) CHAIN_MSG_MAP_ALT(COwnerDraw<MyListImpl>, 1) DEFAULT_REFLECTION_HANDLER(); END_MSG_MAP() public: void DrawItem(LPDRAWITEMSTRUCT item) { CDCHandle dc(item->hDC); CRect rect(item->rcItem); dc.SetBkMode(TRANSPARENT); CFontHandle font(GetParent().GetFont()); if (item->itemState & ODS_SELECTED) { dc.FillSolidRect(rect, RGB(87, 87, 225)); dc.SetTextColor(RGB(255, 255, 255)); } else { dc.FillSolidRect(rect, RGB(225, 225, 225)); dc.SetTextColor(RGB(0, 0, 0)); } dc.DrawText((LPTSTR)item->itemData, -1, rect, DT_VCENTER); } };
四, 在對話方塊所在的類中加入 成員變數以及初始化程式碼
MyOwnerDrawListImpl m_listbox; //...
m_listbox.SubclassWindow(GetDlgItem(IDC_LIST1));
m_listbox.AddString(L"List Box Item 0");
m_listbox.AddString(L"List Box Item 1");
m_listbox.AddString(L"List Box Item 2");
m_listbox.AddString(L"List Box Item 3");
m_listbox.AddString(L"List Box Item 4");
效果