用WTL實現自訂繪製控制項

來源:互聯網
上載者:User

 

簡述


      使用WTL一段時間以來,我發現非常缺乏相關的文檔。在我看來,WTL是解決Win32編程的最佳方案,並且我們在網路上能夠得到文檔越多,對我們越有協助。


     本文主要闡述使用WTL建立自訂繪製控制項的方法。


     我選擇使用一個listview和文章《Neat Stuff to do with List Controls using CustomDraw》聯絡起來。該篇文章通過MFC示範了相同的概念。我選擇簡單的方式並且將帶領你到文檔中獲得更多的例子,通過這些例子,你可以改進你的listview的視覺效果。


     MyListControl

     WTL把自訂繪製控制項變得非常的簡單,其要領是你得弄明白你的項目中實現功能的每一行代碼。我們從CListViewCtrl定義我們自己的類開始,這樣我們就能夠把自訂繪製放在同一個地方。

class MyListView : public CWindowImpl<MyListView, CListViewCtrl>,<br /> public CCustomDraw<MyListView><br />{<br />public:<br /> BEGIN_MSG_MAP(MyListView)<br /> CHAIN_MSG_MAP(CCustomDraw<MyListView>)<br /> END_MSG_MAP()<br />}

    我們必須從CWindowImpl中繼承,否則我們將無法得到任何視窗訊息。更重要的事情再次說明一下,我們也要從CCustomDraw中繼承。該類與CHAIN_MSG_MAP(CCustomDraw<MyListView>)宏一起,讓我們能夠輕易得重載CListViewControl繪製的過程。


宏 CHAIN_MSG_MAP轉寄訊息到基類中預設的的訊息映射中去。


如果你在AtlCtrls.h的代碼中看一眼CCustomDraw<T>,你將看到其定義了宏NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw),該宏處理自訂繪製訊息。NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw)分流訊息到各個組件,並且調用各自對應的函數。以下這些函數可以重載,用來繪製你的控制項。

 

// Overrideables<br />DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/);<br />DWORD OnPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/);<br />DWORD OnPreErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/);<br />DWORD OnPostErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/);<br />DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/);<br />DWORD OnItemPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/);<br />DWORD OnItemPreErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/);<br />DWORD OnItemPostErase(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/); 

我們將重載幾個函數並且改變每隔一行的背景填充顏色,讓其有一個分層的直觀,使得閱讀每一行的時候更加容易。


所以在我們 MyListViewCtrl類中,我們將定義下面兩個重載。

class MyListView : public CWindowImpl<MyListView, CListViewCtrl>,<br /> public CCustomDraw<MyListView><br />{<br />public:<br /> BEGIN_MSG_MAP(MyListView)<br /> CHAIN_MSG_MAP(CCustomDraw<MyListView>)<br /> END_MSG_MAP()<br /> DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)<br /> {<br /> return CDRF_NOTIFYITEMDRAW;<br /> }<br /> DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)<br /> {<br /> NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( lpNMCustomDraw );<br /> // This is the prepaint stage for an item. Here's where we set the<br /> // item's text color. Our return value will tell Windows to draw the<br /> // item itself, but it will use the new color we set here for the background<br /> COLORREF crText;<br /> if ( (pLVCD->nmcd.dwItemSpec % 2) == 0 )<br /> crText = RGB(200,200,255);<br /> else<br /> crText = RGB(255,255,255);<br /> // Store the color back in the NMLVCUSTOMDRAW struct.<br /> pLVCD->clrTextBk = crText;<br /> // Tell Windows to paint the control itself.<br /> return CDRF_DODEFAULT;<br /> }<br />}; 

建立控制項


     大多數我們在MSDN以及其他的文章上看到的例子都是假設控制項都是以資源的形式建立的,然後連結到我們的代碼中。為了與之前的不一樣,我們將直接在主介面上建立一個list box。


以下是所有的我們將添加到嚮導建立的CMainFrame中的代碼,用來建立我們的自訂繪製控制項。找到宏CHAIN_MSG

_MAP_MEMBER(m_listView)。失去了這個宏,你的類將無法得到NM_CUSTOMDRAW訊息。這個宏把資料包中的訊息轉寄訊息到預設的訊息映射中,這正是我們想要做的。


另外注意,我們可能已經在這層級處已經處理了NM_CUSTOMDRAW訊息。查一下,看看控制項的ID是什嗎?處理繪製過程是否合理?

在某些情況下,這是非常有用的,並且相對於我們當前做的事情已經簡單多了。注意,保持我們的代碼的簡潔與明了。

class CMainFrame : public CFrameWindowImpl<CMainFrame>,<br /> public CUpdateUI<CMainFrame>,<br /> public CMessageFilter, public CIdleHandler<br />{<br />public:<br /> // ...<br /> // code left out for readability<br /> // ...<br /> BEGIN_MSG_MAP(CMainFrame)<br /> // ...<br /> // code left out for readability<br /> // ...<br /> CHAIN_MSG_MAP_MEMBER(m_listView)<br /> END_MSG_MAP()</p><p> LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/,<br /> LPARAM /*lParam*/, BOOL& /*bHandled*/)<br /> {<br /> // code left out for readability<br /> // create a list box<br /> RECT r = {0,0,182,80};<br /> m_listView.Create(m_hWnd,r,CListViewCtrl::GetWndClassName(),<br /> WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |<br /> WS_CLIPCHILDREN | LVS_REPORT, WS_EX_CLIENTEDGE);</p><p> // fill in the headers<br /> m_listView.AddColumn(_T("Symbol"), 0);<br /> m_listView.AddColumn(_T("Company "), 1);<br /> m_listView.AddColumn(_T("Price "), 2);<br /> m_listView.AddItem(0,0,"VOD");<br /> m_listView.AddItem(0,1,"Vodaphone Airtouch");<br /> m_listView.AddItem(0,2,"252.25");<br /> m_listView.AddItem(1,0,"LAT");<br /> m_listView.AddItem(1,1,"Lattice Group");<br /> m_listView.AddItem(1,2,"149.9");<br /> m_listView.AddItem(2,0,"CLA");<br /> m_listView.AddItem(2,1,"Claims Direct");<br /> m_listView.AddItem(2,2,"132.50");<br /> return 0;<br /> }</p><p> // ...<br /> // code left out for readability<br /> // ... </p><p>public :<br /> MyListView m_listView;<br />}; 

在 OnCreate() 中,我們僅僅在,並且添加幾個例子數值。大功告成!


許可(英語原文)

本文沒有明確的許可。


作者:Billy Leverington 


翻譯:sKy  

 

英語原文:http://www.codeproject.com/KB/wtl/customdrawlist_wtl.aspx

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.