CListCtrl基本用法

 
CListCtrl是列表控件類,列表控件的每一行叫做一個item,每一列叫做一個subitem。每一行和每一列都有個ID號,可以確定唯一的單元格。

最近使用了這個控件,有心得總結如下:      

(Dialog模式)                                                                                                    

1. 創建列表控件.

定義一個成員變量:CListCtrl *m_pListCtrl;

在初始化對話框的時候創建列表,也就是在OnInitDialog()中創建(在哪裏創建沒有規定,只要符合對象和資源創建的規則即可。)

m_pListCtrl=new CListCtrl();

m_pListCtrl->Create();

m_pListCtrl->SetExtendedStyle();

Create函數有四個參數,DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID 。第一個參數可以是一些值的組合,用來定義列表的樣式,這些值MSDN有詳細說明,我只舉一個簡單的例子,更多的查看MSDN。例如第一個參數使用LVS_REPORT,則表示列表有標題,或者說有列頭,很多其他的樣式必須是和這個樣式搭配使用纔有效。第二個參數是列表的座標和大小,這個矩形框就表示列表的矩形框。第三個參數表示這個列表的父類,如果列表在對話框上或者是在試圖上,這個參數可以是this。第四個參數是列表的資源號。

SetExtendedStyle函數只有一個參數,是一些值的組合,用來設置列表的擴展樣式,這些值MSDN有詳細的說明,我只介紹兩個比較常用的。 LVS_EX_GRIDLINES :列表顯示網格,只適用於LVS_REPORT 風格。LVS_EX_FULLROWSELECT:當一個item被選中時,它的所有subitems也處於被選中狀態,點擊任意一個subitem,則可同時選中整個行. 只適用於LVS_REPORT 風格。

2.構建列表   

構建列表也就是兩個操作,插入列和插入行,前面說過,一個列就是一個subitem,一行就是一個item。

m_pListCtrl->InsertColumn(0,"第一列");

列索引從0開始,InsertColumn函數將在列表中建立一個列,如果數據有三列,就調用三次此函數,索引分別是0,1,2。

m_pListCtrl->InsertItem(0,"第一行");

行索引也從0開始,InsertItem函數在列表中建立一行,且“第一行”的字樣顯示在的一列中,其他各列爲空,如果要在除第一列以外的列中插入數據,調用SetItemText()函數,這個函數有三個參數,第一個參數表示要在第幾行插入,第二個參數表示要在第幾列插入,第三個參數表示要插入的內容。

可以設定列寬:

LVCOLUMN lvcolumn;
m_pListCtrl->GetColumn(0,&lvcolumn);
lvcolumn.mask=LVCF_WIDTH;
lvcolumn.cx=335;
m_pListCtrl->SetColumn(0,&lvcolumn);

表示將列寬設定爲335像素。

3.操作列表

這裏主要介紹一個比較有用的函數SubItemHitTest()

當鼠標停留在列表框上時,此函數會返回鼠標所在的行號,和鼠標所在的列號。

LVHITTESTINFO linfo;
DWORD dwPos   =   GetMessagePos();   
CPoint point(LOWORD(dwPos),HIWORD(dwPos));
m_pListCtrl->ScreenToClient(&point);
linfo.pt=point;
linfo.flags=LVHT_ABOVE;
int iItem=m_pListCtrl->SubItemHitTest(&linfo);

行號保存在linfo.iItem中,列號保存在linfo.iSubItem中,此時可以調用GetItemText()函數獲得這個單元格的內容了。

這個方法常用在列表的NM_CLICK和NM_DBLCLK事件中。

此類消息爲:

ON_NOTIFY(NM_CLICK, IDC, OnFun)

函數原型:

void OnFun(NMHDR *pNMHDR, LRESULT *pResult)
{
*pResult = 0;
}

4.列表中的CheckBox

列表有多中風格,帶CheckBox是其中常見的一種,設置這種風格的列表只需要在調用SetExtendedStyle函數的時候設置LVS_EX_CHECKBOXES。對CheckBox最常見的操作就是選中和取消,可能是我的知識貧乏,到目前,我還沒有找到專門的消息處理這兩個操作。要處理這樣的操作,我使用下面的方法。

響應列表的NM_CLICK消息,在這個消息處理函數中,判斷鼠標點擊的位置是文本還是CheckBox,代碼如下:

UINT nFlag;
DWORD   dwPos   =   GetMessagePos();   
CPoint    point(LOWORD(dwPos),HIWORD(dwPos));
m_pList1->ScreenToClient(&point);
m_pList1->HitTest ( point , &nFlag ) ;

如果nFlag==LVHT_ONITEMSTATEICON ,說明鼠標點中了CheckBox。本可以調用GetCheck函數來獲得CheckBox的狀態,但是很可惜,CheckBox的狀態似乎是在NM_CLICK消息函數結束以後纔會改變。所以,在NM_CLICK的消息處理函數中獲得CheckBox的狀態是沒有改變之前的。

還有一點需要注意,假設現在目前CheckBox的狀態是選中,那麼,當你點擊兩下鼠標的時候,CheckBox還是選中狀態,而且NM_CLICK消息處理函數被執行了兩次,所以,結果是正確的。但是當你點擊兩下鼠標時速度比較快,那麼系統會把兩次單擊鼠標看作一次雙擊,這樣,NM_CLICK的消息處理函數只會執行一次,但是,注意但是,CheckBox的狀態卻改變了兩次。因此,這個時候你看到的CheckBox的狀態和程序的結果就相反了。要解決這個問題,就需要在NM_DBLCLK的消息函數中做相應的工作。CListCtrl是列表控件類,列表控件的每一行叫做一個item,每一列叫做一個subitem。每一行和每一列都有個ID號,可以確定唯一的單元格。

最近使用了這個控件,有心得總結如下:      

(Dialog模式)                                                                                                    

1. 創建列表控件.

定義一個成員變量:CListCtrl *m_pListCtrl;

在初始化對話框的時候創建列表,也就是在OnInitDialog()中創建(在哪裏創建沒有規定,只要符合對象和資源創建的規則即可。)

m_pListCtrl=new CListCtrl();

m_pListCtrl->Create();

m_pListCtrl->SetExtendedStyle();

Create函數有四個參數,DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID 。第一個參數可以是一些值的組合,用來定義列表的樣式,這些值MSDN有詳細說明,我只舉一個簡單的例子,更多的查看MSDN。例如第一個參數使用LVS_REPORT,則表示列表有標題,或者說有列頭,很多其他的樣式必須是和這個樣式搭配使用纔有效。第二個參數是列表的座標和大小,這個矩形框就表示列表的矩形框。第三個參數表示這個列表的父類,如果列表在對話框上或者是在試圖上,這個參數可以是this。第四個參數是列表的資源號。

SetExtendedStyle函數只有一個參數,是一些值的組合,用來設置列表的擴展樣式,這些值MSDN有詳細的說明,我只介紹兩個比較常用的。 LVS_EX_GRIDLINES :列表顯示網格,只適用於LVS_REPORT 風格。LVS_EX_FULLROWSELECT:當一個item被選中時,它的所有subitems也處於被選中狀態,點擊任意一個subitem,則可同時選中整個行. 只適用於LVS_REPORT 風格。

2.構建列表   

構建列表也就是兩個操作,插入列和插入行,前面說過,一個列就是一個subitem,一行就是一個item。

m_pListCtrl->InsertColumn(0,"第一列");

列索引從0開始,InsertColumn函數將在列表中建立一個列,如果數據有三列,就調用三次此函數,索引分別是0,1,2。

m_pListCtrl->InsertItem(0,"第一行");

行索引也從0開始,InsertItem函數在列表中建立一行,且“第一行”的字樣顯示在的一列中,其他各列爲空,如果要在除第一列以外的列中插入數據,調用SetItemText()函數,這個函數有三個參數,第一個參數表示要在第幾行插入,第二個參數表示要在第幾列插入,第三個參數表示要插入的內容。

可以設定列寬:

LVCOLUMN lvcolumn;
m_pListCtrl->GetColumn(0,&lvcolumn);
lvcolumn.mask=LVCF_WIDTH;
lvcolumn.cx=335;
m_pListCtrl->SetColumn(0,&lvcolumn);

表示將列寬設定爲335像素。

3.操作列表

這裏主要介紹一個比較有用的函數SubItemHitTest()

當鼠標停留在列表框上時,此函數會返回鼠標所在的行號,和鼠標所在的列號。

LVHITTESTINFO linfo;
DWORD dwPos   =   GetMessagePos();   
CPoint point(LOWORD(dwPos),HIWORD(dwPos));
m_pListCtrl->ScreenToClient(&point);
linfo.pt=point;
linfo.flags=LVHT_ABOVE;
int iItem=m_pListCtrl->SubItemHitTest(&linfo);

行號保存在linfo.iItem中,列號保存在linfo.iSubItem中,此時可以調用GetItemText()函數獲得這個單元格的內容了。

這個方法常用在列表的NM_CLICK和NM_DBLCLK事件中。

此類消息爲:

ON_NOTIFY(NM_CLICK, IDC, OnFun)

函數原型:

void OnFun(NMHDR *pNMHDR, LRESULT *pResult)
{
*pResult = 0;
}

4.列表中的CheckBox

列表有多中風格,帶CheckBox是其中常見的一種,設置這種風格的列表只需要在調用SetExtendedStyle函數的時候設置LVS_EX_CHECKBOXES。對CheckBox最常見的操作就是選中和取消,可能是我的知識貧乏,到目前,我還沒有找到專門的消息處理這兩個操作。要處理這樣的操作,我使用下面的方法。

響應列表的NM_CLICK消息,在這個消息處理函數中,判斷鼠標點擊的位置是文本還是CheckBox,代碼如下:

UINT nFlag;
DWORD   dwPos   =   GetMessagePos();   
CPoint    point(LOWORD(dwPos),HIWORD(dwPos));
m_pList1->ScreenToClient(&point);
m_pList1->HitTest ( point , &nFlag ) ;

如果nFlag==LVHT_ONITEMSTATEICON ,說明鼠標點中了CheckBox。本可以調用GetCheck函數來獲得CheckBox的狀態,但是很可惜,CheckBox的狀態似乎是在NM_CLICK消息函數結束以後纔會改變。所以,在NM_CLICK的消息處理函數中獲得CheckBox的狀態是沒有改變之前的。

還有一點需要注意,假設現在目前CheckBox的狀態是選中,那麼,當你點擊兩下鼠標的時候,CheckBox還是選中狀態,而且NM_CLICK消息處理函數被執行了兩次,所以,結果是正確的。但是當你點擊兩下鼠標時速度比較快,那麼系統會把兩次單擊鼠標看作一次雙擊,這樣,NM_CLICK的消息處理函數只會執行一次,但是,注意但是,CheckBox的狀態卻改變了兩次。因此,這個時候你看到的CheckBox的狀態和程序的結果就相反了。要解決這個問題,就需要在NM_DBLCLK的消息函數中做相應的工作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章