1.创建Virtual List
只需添加LVS_OWNERDATA风格到List Ctrl就行了。
m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_OWNERDATA);
2.添加,删除和更改一行
添加:因为Virtual List不拥有数据,数据存在外部(如:数据库),所以你只需将数据添加到外部,然后m_list.SetItemCount(list_size+1)告诉Virtual List行数加一。这样Virtual List会更改滚动条的样子,以便看上去添加了一行.
删除:先在外部数据中删除行,然后m_list.SetItemCount(list_size-1)更改滚动条.
更改:直接修改在外部数据中的行.
如果这些行是正在显示的行,则需要调用m_list.RedrawItems(nFirst,nLast)
3.响应LVN_GETDISPINFO消息
当Virtual List需要显示一行数据时,它发送这个消息给父窗口询问数据内容.父窗口收到消息后从传过来参数中知道Virtual List现在显示的是第几项,第几列,内容是什么类型.然后父窗口在外部数据中找到数据内容,将它返回给Virtual List.
先添加消息映射,这里用的是反射消息,可以减少控件于父窗口之间的耦合度
BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
ON_NOTIFY_REFLECT(LVN_GETDISPINFO, OnGetdispinfo)
END_MESSAGE_MAP()
相应的响应函数
void CMyListCtrl::OnGetdispinfo(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
LV_ITEM* pItem= &(pDispInfo)->item;
int iItemIndx= pItem->iItem;
if (pItem->mask & LVIF_TEXT)
{
switch(pItem->iSubItem)
{
case 0:
{
memcpy(pItem->pszText,(find_index + iItemIndx)->code,8);
*(pItem->pszText+8) = 0;
}
break;
case 1:
{
memcpy(pItem->pszText,(find_index + iItemIndx)-
>description,INDEX_DESLEN);
*(pItem->pszText+INDEX_DESLEN) = 0;
}
break;
}
}
*pResult = 0;
}
4.响应LVN_ODCACHEHINT消息
这个消息用来缓存请求项的数据.我没用到这个消息,因为我已一次将所有数据读入内存.
5.响应LVN_ODFINDITEM消息
在资源管理器中浏览文件时,让焦点list上,然后在键盘上输入文件名.资源管理器会自动找到并选中与之最相近的文件.LVN_ODFINDITEM就是实现这个功能的.当焦点在list上时,按键操作会使Virtual List发送LVN_ODFINDITEM给父窗口.父窗口找到相应项并将它选中.
BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
ON_NOTIFY_REFLECT(LVN_ODFINDITEM, OnOdfinditemList)
END_MESSAGE_MAP()
void CMyListCtrl::OnOdfinditemList(NMHDR* pNMHDR, LRESULT* pResult)
{
// pNMHDR has information about the item we should find
// In pResult we should save which item that should be selected
NMLVFINDITEM* pFindInfo = (NMLVFINDITEM*)pNMHDR;
*pResult = -1; // *pResult = -1 表明没有找到
if( (pFindInfo->lvfi.flags & LVFI_STRING) == 0 )
return;
int nlen = _tcslen(pFindInfo->lvfi.psz);
int startPos = pFindInfo->iStart;
//Is startPos outside the list (happens if last item is selected)
if(startPos >= m_list.GetItemCount())
startPos = 0;
int currentPos=startPos;
do
{
if(memcmp((find_index + startPos ),pFindInfo->lvfi.psz,nlen) == 0)
{
*pResult = currentPos;
break;
}
currentPos++;
if(currentPos >= m_list.GetItemCount())
currentPos = 0;
}while(currentPos != startPos);
}