本文根據本人在項目中的應用,來談談CListCtrl的部分用法及技巧。當初學習時,查了不少資料,零零碎碎的做了些記錄,如今主要是來作個總結,方便之後查閱。主要包括如下十三點內容:基本操做、獲取選中行的行號、複選框操做、動態設置選中行的字體顏色、設置選中行的背景顏色、禁止拖動表頭、讓第一列居中顯示、設置行高與字體、虛擬列表技術、點擊表頭時進行歸類、向上與向下移動、動態調整大小問題、避免閃爍問題。編程
分爲兩篇來進行總結。本篇重點總結:基本操做、獲取選中行的行號、複選框操做、動態設置選中行的字體顏色、設置選中行的背景顏色windows
分別從下面四點來介紹CListCtrl的基本操做:函數
①設置列表視圖顯示方式學習
Ⅰ. CListCtrl有四種樣式:LVS_ICON、LVS_SMALLICON、LVS_LIST、LSV_REPORT,可經過控件屬性來設置。本文所述均爲LSV_REPORT屬性。字體
Ⅱ. 擴展樣式:spa
經常使用的擴展樣式有三種:LVS_EX_FULLROWSELECT、LVS_EX_GRIDLINES、LVS_EX_CHECKBOXES,分別對應做用 選中某行時使正行高亮、設置網格線、item前生成Ckeckbox控件。.net
使用SetExtendedStyle(style)函數設置擴展樣式,使用GetExtendedStyle()函數獲取樣式,如:翻譯
m_listInfo.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
Ⅲ. 使用CListView時,須要在PreCreateWindow()函數中添加 cs.style | = LVS_REPORT;code
來將其設置爲LVS_REPORT風格,不然插入無效。還用另外一種方法來設置風格,即在OnInitialUpate()中獲取CListCtrl控制權,而後修改風格,以下所示:orm
CListCtrl &theCtrl =GetListCtrl();
theCtrl.ModifyStyle(0, LVS_REPORT);
②插入操做
先插入列:
int InsertColumn( int nCol, LPCTSTR lpszColumnHeading, int nFormat, int nWidth, int nSubItem)
插入列時,可指明列號、列名稱、列名稱顯示樣式,列寬等信息。對於列號爲0的那一列,始終是靠左顯示,後面會有修改使其劇中顯示的方法,其餘列經過設置nFormat屬性能夠居中顯示。
插入行:
int InsertItem( int nItem, LPCTSTRlpszItem )
直接插入一行,nItem指明行號,lpszItem指明該行第0列的信息。
設置信息:
BOOL SetItemText(int nItem, int nSubItem, LPCTSTR lpszText )
設置第nItem行nSubItem列的信息(nItem:0,1,2,3……; nSubItem:1,2,3……)
③刪除操做
有三個操做函數:
BOOL DeleteAllItems() -------刪除全部的行
BOOL DeleteItem(nItem) --------刪除某一行
BOOL DeleteColumn(nCol) -----刪除某一列
④獲取/設置屬性函數
有不少函數了,就不一一介紹了。經常使用的有
int GetItemCount() -------- 獲取已插入信息的行數
BOOL SetItemState(int iLink, UINTstate, UINTstateMask ) ---------設置行狀態,如高亮顯示等
等等
獲取選中行的行號,而後對該行進行相關處理,這點在編程中用的很是多。
當鼠標單擊item時,控件向父窗口發送NM_CLICK消息,其響應函數爲OnNMClickXXXX(NMHDR *pNMHDR, LRESULT *pResult),在該函數下來編寫代碼獲取鼠標點擊的行號。
有兩種方法來獲取行號:第一種是使用GetFirstSelectedItemPosition和GetNextSelectedItem配合來獲取;第二種是先獲取鼠標位置信息,而後調用HitTest函數來找出行號。示例分別以下:
第一種方法,該示例截自MSDN,可做修改後使用。
第二種方法,該示例來自個人項目,可做修改後使用。
對於LVHITTESTINFO 結構體,其有四個成員,在上述HitTest調用中,其第一個成員做爲輸入,另外三個做爲輸出。具體變量含義可查看MSDN。
有時須要在item前面添加一個CheckBox,供用戶選擇,而後對全部選中項進行處理。
這裏涉及到兩個問題:第一個,如何添加CheckBox風格;第二個,如何判斷某一行的CheckBox狀態是否發生改變。
對於第一個問題,在基本操做裏已經有所闡述了,即經過SetExtendedStyle函數添加LVS_EX_CHECKBOXES擴展風格。
這裏重點探討第二個問題,首先,操做複選框狀態的有兩個函數:
BOOL GetCheck(int nItem)-------獲取複選框狀態
BOOL SetCheck( int nItem, BOOL fCheck = TRUE )-------設置複選框狀態
其次,咱們要搞清楚如下四點:
① 當列表的項item改變時,控件會向父窗口發送LVN_ITEMCHANGED消息,所以能夠在LVN_ITEMCHANGED消息的響應函數中對複選框的狀態進行處理(查詢或設置)。
② 鼠標點擊CheckBox時,消息的順序是 NM_CLICK —> LVN_ITEMCHANGED,即CheckBox的狀態是在 NM_CLICK消息函數結束後纔會發生變化,在NM_CLICK中使用GetCheck無效。
③ 鼠標點擊Item(非CheckBox區域)時,消息的順序是 LVN_ITEMCHANGED —> NM_CLICK。
④ 調用InsertItem 函數時,也會產生LVN_ITEMCHANGED消息。鑑於此,一般會自定義一個BOOL型變量m_bHit 來判斷是點擊操做仍是插入操做,該變量初始賦FALSE,當有鼠標點擊item時賦TRUE, 檢測完是否有CheckBox被點擊後從新復位爲FALSE。
示例以下所示:
有時可能須要設置某行的文字爲特殊顏色,以表示某種特殊含義,好比正在下載的信息用綠色,暫停下載的用灰色。
首先,給出一個CodeProject的連接,這篇文章講的很是好,主要是利用Custom Draw。http://www.codeproject.com/Articles/79/Neat-Stuff-to-Do-in-List-Controls-Using-Custom-Dra
而後,來談談個人方法,這裏主要談對選中行的字體顏色進行動態修改,固然也是我經過上面文章和本身實踐結合得出的。
咱們須要搞清楚如下幾點(能夠結合下面修改某一行的字體顏色的方法來看):
① 當控件繪製時,會發送NM_CUSTOMDRAW 消息,該消息的消息響應函數爲
②其中,pNMHDR爲輸入參數,其指向NMLVCUSTOMDRAW結構體,該結構包含了不少信息,包括字體顏色、背景等等,特別是第一個成員,爲NMCUSTOMDRAW結構體變量,其包含了Current drawing stage(不知道怎麼編譯比較好),其可能的值以下圖(截自MSDN)所示
③ pResult爲輸出參數,該參數決定了接下來向windows發送什麼消息(與繪製有關的),經過發送該消息咱們能夠進入下一步須要的處理階段。具體輸出哪一個值取決於Current drawing stage,其可能的值以下圖(截自MSDN)所示
④ 有一點必須注意(英文的,我以爲看起來比翻譯過來更精確):
One thing to keep in mind is you must always check the draw stage before doing anything else, because your handler will receive many messages, and the draw stage determines what action your code takes.
下面咱們來看看如何修改某一行的字體顏色:
① 首先,咱們應該明白要修改字體顏色,應該在pre-paint 階段來完成
② 所以,在消息響應函數中,咱們首先判斷是否處於pre-paint stage(即pLVCD->nmcd.dwDrawStage == CDDS_PREPAINT),而後經過修改輸出值pResult 的值來通知windows咱們須要處理每一個item的消息(即設置 *pResult = CDRF_NOTIFYITEMDRAW)。
③ 再次進入消息響應函數時,咱們判斷是否處於Item的pre-paint stage(即pLVCD->nmcd.dwDrawStage == CDDS_ITEMPREPAINT),若是是則進行相關處理,即修改字體顏色等等。
④ 處理完了後從新設置 *pResult = CDRF_DODEFAULT,表示咱們再也不須要其餘特殊的消息了,默認執行便可。
示例以下:
上面談的方法主要用於設置靜態字體顏色,固然,若是你的列表的信息在不斷變化(即用SetItemText不斷修改),那麼也就實現了動態改變了,不然須要在合適的地方調用重繪函數:
BOOL RedrawItems( int nFirst, int nLast )
表示在nFirst和nLast之間的行須要進行重繪。
設置選中行的背景顏色,能夠將選中行以特殊顏色顯示,容易明白當前處理的是哪一行。儘管有高亮,可是高亮是基於焦點的,若是你選中了某一行,而後焦點轉移了,這是就沒法判斷你選的是哪一行了。
設置選中行的背景顏色的方法和第四節中講的修改字體顏色的方法是類似的,都是利用Custom Draw。這裏涉及到設置當前選中行爲特殊顏色,同時要恢復前一次選中行的顏色,不然就亂了。所以須要記錄前一次選中行、當前選中行的行號,相信經過前面的總結,這點並不難實現。而後在當前選中行和前一次選中行之間進行重繪便可。
示例以下: