clistctrl 虛擬列表

2021-09-08 23:31:34 字數 4681 閱讀 4604

一、什麼是虛擬列表控制項

虛擬列表控制項是指帶有lvs_ownerdata風格的列表控制項。。

二、為什麼使用虛擬列表控制項

為此,mfc特別提供了虛擬列表的支援。乙個虛擬列表看起來和普通的listctrl一樣,但是不用通過insertitem來插入資料,它僅僅知道自己應該顯示多少資料。但是它如何知道要顯示什麼資料呢?秘密就在於當列表控制項需要顯示某個資料的時候,它向父視窗要。假設這個列表控制項包含100個元素,第10到20個元素(行)是可見的。當列表控制項重畫的時候 ,它首先請求父視窗給它第10個元素的資料,父視窗收到請求以後,把資料資訊填充到列表提供的乙個結構中,列表就可以用來顯示了,顯示第10個資料後,列表會繼續請求下乙個資料。

在虛擬的樣式下,listctrl可以支援多達dword個資料項。(預設的listctrl控制項最多支援int個資料項)。但是,虛擬列表的最大優點不在於此,而是它僅僅需要在記憶體中保持極少量的資料,從而加快了顯示的速度。所以,在使用列表控制項顯示乙個很大的資料庫的情況下,採用虛擬列表最好不過了。

不僅clistctrl提供虛擬列表的功能, mfc的clistview類也有同樣的功能。

三、虛擬列表控制項的訊息

虛擬列表總共傳送三個訊息給父視窗:當它需要資料的時候,它傳送lvn_getdispinfo訊息。這是最重要的訊息。當使用者試圖查詢某個元素的時候,它傳送lvn_odfinditem訊息;還有乙個訊息是lvn_odcachehint,用來緩衝資料,基本上很少用到這個訊息。

虛擬列表控制項使用起來非常簡單。它總共只有三個相關的訊息,如果你直接使用clistctrl,應該在對話方塊中響應這三個訊息。如果你使用clistctrl派生類,可以在派生類中響應這三個訊息的反射訊息。這三個訊息分別是:

(1)lvn_getdispinfo 控制項請求某個資料

(2)lvn_odfinditem  查詢某個資料

(3)lvn_odcachehint 緩衝某一部分資料

我們必須響應的訊息是(1),多數情況下要響應(2),極少數的情況下需要響應(3)

四、如何使用虛擬列表控制項

1、首先要建立控制項,建立乙個虛擬列表和建立乙個正常的 clistctrl差不多。先在資源編輯器裡面新增乙個list control資源。然後選中"owner data"屬性,然後給它**乙個clistctrl變數。新增列,新增imagelist等都和使用正常的listctrl一樣。

2、給虛擬列表新增元素。假設 m_list 是這個列表的控制變數。通常的情況下這樣新增資料:

m_list.insertitem(0, _t("hello world"));

但是對於虛擬列表,不能這麼做。只需告訴列表有多少個資料:

//總共顯示100行

m_list.setitemcount(100);

3、處理它的通知訊息。

五、如何響應虛擬列表的訊息

1、處理 lvn_getdispinfo 通知訊息

當虛擬列表控制項需要某個資料的時候,它給父視窗傳送乙個 lvn_getdispinfo通知訊息,表示請求某個資料。因此列表的所有者視窗(或者它自己)必須處理這個訊息。例如派生類的情況 (cmylistctrl是乙個虛擬列表類物件):

//這裡處理的是反射訊息

begin_message_map(cmylistctrl, clistctrl)

//}afx_msg_map

end_message_map()

在lvn_getdispinfo的處理函式中,必須首先檢查列表請求的是什麼資料,可能的值包括:

(1)lvif_text   必須填充 psztext

(2)lvif_image  必須填充 iimage

(3)lvif_indent 必須填充 iindent

(4)lvif_param  必須填充 lparam

(5)lvif_state  必須填充 state

根據它的請求,填充所需的資料即可。

//***************== 例子*************************************==

下面的給出乙個例子,填充的是列表所需的某個資料項的文字以及影象資訊:

lv_dispinfo* pdispinfo = (lv_dispinfo*)pnmhdr;

lv_item* pitem= &(pdispinfo)->item;

int iitemindx= pitem->iitem;

if (pitem->mask & lvif_text) //字串緩衝區有效

}/*注意,多數情況下要使用lstrcpyn ,因為最多複製字元的個數由pitem->cchtextmax給出:

lstrcpyn(pitem->psztext, text, pitem->cchtextmax);

*/if (pitem->mask & lvif_image) //是否請求影象

pitem->iimage= m_items[iitemindx].m_iimageindex;

甚至連某行資料是否選中(當有checkbox的情況下)的資訊也需要由使用者自己來維護,例如:

//是否顯示該行的選擇資訊?

if(ischeckboxesvisible()) //自定義函式

else

}2、處理 lvn_odfinditem 訊息

在資源管理器裡面,定位到某個資料夾,會顯示很多檔案,如果按下鍵盤的『a』,則資源管理器會自動找到名字以 'a'打頭的資料夾或者檔案, 並選擇該檔案。繼續按 a,如果還有其它名字以'a'打頭的檔案,則下乙個檔案被選中。如果輸入 "ab",則 'ab'打頭的檔案被選中。這就是列表控制項的自動查詢功能。

當虛擬列表收到乙個lvm_finditem訊息,它也會傳送這個訊息通知父視窗查詢目標元素。要搜尋的資訊通過 lvfindinfo 結構給出。它是 nmlvfinditem 結構的乙個成員。當找到要搜尋的資料後,應該把該資料的索引(行號)返回,如果沒有找到,則返回-1。

以對話方塊為例,響應函式大致如下:

//***************== 例子*************************************==

void cvirtuallistdlg::onodfinditemlist(nmhdr* pnmhdr, lresult* presult)

//這是我們要找的字串

cstring searchstr = pfindinfo->lvfi.psz;

int startpos = pfindinfo->istart;//儲存起始位置

//判斷是否最後一行

if(startpos >= m_list.getitemcount())

startpos = 0;

int currentpos=startpos;

//開始查詢

docurrentpos++;

//從頭開始

if(currentpos >= m_list.getitemcount())

currentpos = 0;

}while(currentpos != startpos);       

}顯然,如果資料很多,必須實現乙個快速查詢的方法。

關於pfindinfo->lvfi裡面的資訊的詳細說明可以參考 msdn。

3、處理 lvn_odcachehint 訊息。

假如我們從資料庫或者其它地方讀取資料的速度比較慢,則可以利用這個訊息,批量讀取一些資料,然後根據請求,逐個提供給虛擬列表。lvn_odcachehint訊息的用途就是給程式乙個緩衝資料的機會。以提高程式的效能。

//***************== 例子*************************************==

使用 classwizard 過載 onchildnotify 函式,檢查是否 lvn_odcachehint 訊息,然後準備緩衝資料:

nmlvcachehint* pcachehint=null;

nmhdr* phdr = (nmhdr*)lparam;

if(phdr->code == lvn_odcachehint)

else ...

注意,如果訊息不是 lvn_odcachehint,則要傳遞給基類進行處理。

五、如何修改listctrl顯示的資料。

由於是程式自己維護資料,所以只需修改資料庫中的資料,然後呼叫clistctrl::redrawitems函式進行重畫即可。

六、資料的選擇狀態和選擇框

clistctrl可以顯示checkbox選擇框。有些情況下是很有用的。對於正常的listctrl,使用者可以用滑鼠來修改某個元素的選擇狀態,但是對於虛擬列表就不行了。必須自己處理一些訊息,然後自己儲存資料的選中狀態:

void cvirtuallistdlg::togglecheckbox(int item)

處理 lvn_keydown訊息,新增對空格鍵 的響應,用於切換選擇狀態:

void cvirtuallistdlg::onkeydownlist(nmhdr* pnmhdr, lresult* presult)

*presult = 0;

}然後處理 nm_click 訊息:

void cvirtuallistdlg::onclicklist(nmhdr* pnmhdr, lresult* presult)

}*presult = 0;

}七、備註:

1、虛擬列表無法進行排序。

2、虛表的乙個優點是容易保持和資料庫的同步。修改資料庫中的資料,然後重畫list十分容易而且高效。

3、虛表的另乙個優點是可以根據需要產生資料。比如在某一列加上行號。

clistctrl 虛擬列表

一 什麼是虛擬列表控制項 虛擬列表控制項是指帶有lvs ownerdata風格的列表控制項。二 為什麼使用虛擬列表控制項 為此,mfc特別提供了虛擬列表的支援。乙個虛擬列表看起來和普通的listctrl一樣,但是不用通過insertitem來插入資料,它僅僅知道自己應該顯示多少資料。但是它如何知道要...

虛擬列表控制項(CListCtrl)

m list.setitemcount 100 3 處理它的通知訊息。五 如何響應虛擬列表的訊息 1 處理 lvn getdispinfo 通知訊息 當虛擬列表控制項需要某個資料的時候,它給父視窗傳送乙個 lvn getdispinfo通知訊息,表示請求某個資料。因此列表的所有者視窗 或者它自己 必...

虛擬列表控制項(CListCtrl)

虛擬列表控制項 clistctrl 2011年02月16日 星期三 下午 02 02 m list.setitemcount 100 3 處理它的通知訊息。五 如何響應虛擬列表的訊息 http www.pudn.com downloads72 sourcecode windows control l...