This documentation is archived and is not being maintained.

Virtual List Controls

A virtual list control is a list view control that has the LVS_OWNERDATA style. This style enables the control to support an item count up to a DWORD (the default item count only extends to an int). However, the biggest advantage provided by this style is the ability to only have a subset of data items in memory at any one time. This allows the virtual list view control to lend itself for use with large databases of information, where specific methods of accessing data are already in place.


In addition to providing virtual list functionality in CListCtrl, MFC also provides the same functionality in the CListView class.

There are some compatibility issues you should be aware of when developing virtual list controls. For more information, see the Compatibility Issues section of the List-View Controls topic in the Windows SDK.

Virtual list controls maintain very little item information. Except for the item selection and focus information, all item information is managed by the owner of the control. Information is requested by the framework via a LVN_GETDISPINFO notification message. To provide the requested information, the owner of the virtual list control (or the control itself) must handle this notification. This can easily be done using the Properties window (see Mapping Messages to Functions). The resultant code should look something like the following example (where CMyDialog owns the virtual list control object and the dialog is handling the notification):

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

In the handler for the LVN_GETDISPINFO notification message, you must check to see what type of information is being requested. The possible values are:

  • LVIF_TEXT   The pszText member must be filled in.

  • LVIF_IMAGE   The iImage member must be filled in.

  • LVIF_INDENT   The iIndent member must be filled in.

  • LVIF_PARAM   The lParam member must be filled in.

  • LVIF_STATE   The state member must be filled in.

You should then supply whatever information is requested back to the framework.

The following example (taken from the body of the notification handler for the list control object) demonstrates one possible method by supplying information for the text buffers and image of an item:

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

int iItem = pItem->iItem;

if (pItem->mask & LVIF_TEXT) //valid text buffer?
      case 0: //fill in main text
         _tcscpy_s(pItem->pszText, pItem->cchTextMax,
      case 1: //fill in sub item 1 text
         _tcscpy_s(pItem->pszText, pItem->cchTextMax,
      case 2: //fill in sub item 2 text
         _tcscpy_s(pItem->pszText, pItem->cchTextMax,

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

Because this type of list control is intended for large data sets, it is recommended that you cache requested item data to improve retrieval performance. The framework provides a cache-hinting mechanism to assist in optimizing the cache by sending an LVN_ODCACHEHINT notification message.

The following example updates the cache with the range passed to the handler function.

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;

For more information on preparing and maintaining a cache, see the Cache Management section of the List-View Controls topic in the Windows SDK.

The LVN_ODFINDITEM notification message is sent by the virtual list control when a particular list control item needs to be found. The notification message is sent when the list view control receives quick key access or when it receives an LVM_FINDITEM message. Search information is sent in the form of an LVFINDINFO structure, which is a member of the NMLVFINDITEM structure. Handle this message by overriding the OnChildNotify function of your list control object and inside the body of the handler, check for the LVN_ODFINDITEM message. If found, perform the appropriate action.

You should be prepared to search for an item that matches the information given by the list view control. You should return the index of the item if successful, or -1 if no matching item is found.