虚拟列表控件

虚拟列表控件是具有 LVS_OWNERDATA 样式的列表视图控件。 此样式使控件能够支持最多为 DWORD 的项计数(默认项计数仅扩展到 int)。 但是,此样式具有的最大优势是,允许内存中任何时候都只有一部分数据项。 这样,虚拟列表视图控件就可以与大型信息数据库一起使用,而这些数据库中的访问数据的特定方法已经到位。

注意

除了在 CListCtrl 中提供虚拟列表功能外,MFC 还在 CListView 类中提供相同的功能。

开发虚拟列表控件时,应该注意一些兼容性问题。 有关详细信息,请参阅 Windows SDK 中“列表视图控件”主题的“兼容性问题”部分。

处理 LVN_GETDISPINFO 通知

虚拟列表控件保留的项信息很少。 除项选择和焦点信息外,所有项信息均由控件的所有者管理。 框架通过 LVN_GETDISPINFO 通知消息来请求信息。 提供请求的信息的前提是虚拟列表控件的所有者(或控件本身)处理此通知。 可以使用类向导轻松完成此操作(请参阅将消息映射到函数)。 生成的代码应类似于以下示例(其中,CMyDialog 拥有虚拟列表控件对象,对话框将处理通知):

ON_NOTIFY(LVN_GETDISPINFO, IDC_LIST3, &CMyDialog::OnLvnGetdispinfoList3)

在 LVN_GETDISPINFO 通知消息的处理程序中,你必须查看请求的信息类型。 可能的值为:

  • LVIF_TEXT 必须填充 pszText 成员。

  • LVIF_IMAGE 必须填充 iImage 成员。

  • LVIF_INDENT 必须填充 iIndent 成员。

  • LVIF_PARAM 必须填充 lParam 成员。 (对于子项而言并不存在。)

  • LVIF_STATE 必须填充 state 成员。

然后,应向框架提供所请求的任何信息。

以下示例(从列表控件对象的通知处理程序的正文中获取)演示了一种可能的方法,即提供项的文本缓冲区和图像的信息:

NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO *>(pNMHDR);
LVITEM *pItem = &(pDispInfo)->item;

int iItem = pItem->iItem;

if (pItem->mask & LVIF_TEXT) //valid text buffer?
{
   switch (pItem->iSubItem)
   {
   case 0: //fill in main text
      _tcscpy_s(pItem->pszText, pItem->cchTextMax,
                m_Items[iItem].m_strItemText);
      break;
   case 1: //fill in sub item 1 text
      _tcscpy_s(pItem->pszText, pItem->cchTextMax,
                m_Items[iItem].m_strSubItem1Text);
      break;
   case 2: //fill in sub item 2 text
      _tcscpy_s(pItem->pszText, pItem->cchTextMax,
                m_Items[iItem].m_strSubItem2Text);
      break;
   }
}

if (pItem->mask & LVIF_IMAGE) //valid image?
{
   pItem->iImage = m_Items[iItem].m_iImage;
}

缓存和虚拟列表控件

由于这种类型的列表控件适用于大型数据集,因此建议缓存请求的项数据以提高检索性能。 该框架提供了一种缓存提示机制,通过发送 LVN_ODCACHEHINT 通知消息来帮助优化缓存。

以下示例使用传递给处理程序函数的范围来更新缓存。

void CMyDialog::OnLvnOdcachehintList3(NMHDR* pNMHDR, LRESULT* pResult)
{
   LPNMLVCACHEHINT pCacheHint = reinterpret_cast<LPNMLVCACHEHINT>(pNMHDR);

   // Update the cache with the recommended range.
   for (int i = pCacheHint->iFrom; i <= pCacheHint->iTo; i++)
   {
      m_Items[i].m_iImage = i % 2;
      m_Items[i].m_strItemText.Format(_T("Item %d"), i);
      m_Items[i].m_strSubItem1Text = _T("Sub 1");
      m_Items[i].m_strSubItem2Text = _T("Sub 2");
   }

   *pResult = 0;
}

若要详细了解如何准备和维护缓存,请参阅 Windows SDK 中“列表视图控件”主题的“缓存管理”部分。

查找特定项

需要找到特定列表控件项时,虚拟列表控件会发送 LVN_ODFINDITEM 通知消息。 当列表视图控件收到快速密钥访问或收到 LVM_FINDITEM 消息时,会发送通知消息。 搜索信息以 LVFINDINFO 结构的形式发送,该结构是 NMLVFINDITEM 结构的成员。 通过重写列表控件对象的 OnChildNotify 函数来处理此消息,并在处理程序正文中查找 LVN_ODFINDITEM 消息。 如果找到该消息,则执行相应的操作。

应准备好搜索与列表视图控件提供的信息匹配的项。 如果成功,则应返回项的索引;如果未找到匹配项,则应返回 -1。

另请参阅

使用 CListCtrl
控件