1. 程式人生 > >WTL 中使用 COwnerDraw<T> 類 自繪 List Box

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");

 

 

效果