Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

SubItem Selection in List Control

0.00/5 (No votes)
5 Sep 2004 1  
Explains how to select Sub Items in Report style List Control.

Sample screenshot

Introduction

In one of my projects, I needed to add a single cell (SubItem) selection in Report style list control. By default, List control has full row selection style that can be set using "LVS_EX_FULLROWSELECT" as a flag in SetExtendedStyle().

To select a subitem in Report style list control, you have to set LVS_OWNERDRAWFIXED style and have to implement DrawItem() function in your CListCtrl derived class.

Following is the implementation of DrawItem function that shows selection around a subitem in report style list control.

void CListCtrlEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{

 TCHAR  lpBuffer[256];
 LV_ITEM lvi;
 lvi.mask = LVIF_TEXT | LVIF_PARAM ;
 lvi.iItem = lpDrawItemStruct->itemID ;  
 lvi.iSubItem = 0;
 lvi.pszText = lpBuffer ;
 lvi.cchTextMax = sizeof(lpBuffer);
 VERIFY(GetItem(&lvi));
 LV_COLUMN lvc, lvcprev ;
 ::ZeroMemory(&lvc, sizeof(lvc));
 ::ZeroMemory(&lvcprev, sizeof(lvcprev));
 lvc.mask = LVCF_WIDTH |LVCF_FMT;
 lvcprev.mask = LVCF_WIDTH | LVCF_FMT;
 
 
 CDC* pDC;
 pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
 int nCol;
 if(!m_SelectionFlag)
 {
  for ( nCol=0; GetColumn(nCol, &lvc); nCol++)
  {
   if(nCol>0)
   {
    GetSubItemRect(lpDrawItemStruct->itemID, 
           nCol,LVIR_BOUNDS, m_SelectionRect);
   else
   {
    GetItemRect(lpDrawItemStruct->itemID, 
                 m_SelectionRect,LVIR_BOUNDS);
    m_SelectionRect.right = GetColumnWidth(0);
    m_SelectionRect.left = 0;
   }
   if(m_SelectionRect.PtInRect(m_Point))
   {
    m_SelectionFlag = TRUE;
    break;
   }
   else
    m_SelectionFlag = FALSE;
  } 
 
  if ( (lpDrawItemStruct->itemState & 
               ODS_SELECTED) && m_SelectionFlag )
  {
   CRect rc=lpDrawItemStruct->rcItem;
   rc.left=m_SelectionRect.left;
   rc.right = m_SelectionRect.right;
   
   pDC->FillSolidRect(&rc, RGB(255,0,0));
   //GetSysColor(COLOR_HIGHLIGHT)) ; 

  }
  else
  {
   pDC->FillSolidRect(&lpDrawItemStruct->rcItem, 
                         GetSysColor(COLOR_WINDOW)) ;
   pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT)) ; 
  }
 } 
 for ( nCol=0; GetColumn(nCol, &lvc); nCol++)
 {
  if ( nCol > 0 ) 
  {
   // Get Previous Column Width in order to move the next display item   

   GetColumn(nCol-1, &lvcprev) ;
   lpDrawItemStruct->rcItem.left += lvcprev.cx ;
   lpDrawItemStruct->rcItem.right += lpDrawItemStruct->rcItem.left ; 
  }
  // Get the text 

  ::ZeroMemory(&lvi, sizeof(lvi));
  lvi.iItem = lpDrawItemStruct->itemID;
  lvi.mask = LVIF_TEXT | LVIF_PARAM;
  lvi.iSubItem = nCol;
  lvi.pszText = lpBuffer;
  lvi.cchTextMax = sizeof(lpBuffer);
  VERIFY(GetItem(&lvi));
  pDC->SelectObject(GetStockObject(DEFAULT_GUI_FONT));
  UINT  uFormat    = DT_LEFT ;
  ::DrawText(lpDrawItemStruct->hDC, lpBuffer, strlen(lpBuffer), 
                          &lpDrawItemStruct->rcItem, uFormat) ;
  pDC->SelectStockObject(SYSTEM_FONT) ;
 }
}

Demo Project:

  1. Using MFC AppWizard, create a Dialog Based application. Give the application name as you like.
  2. Now, add a List-Control and in Properties, change the style to Report. This style is necessary if we want multiple columns.
  3. Add CListCtrlEx.cpp and CListCtrlEx.h files in your project by selecting Project->Add To Project->Files... menu from the menu bar and selecting these files in "Insert files to project" dialog.
  4. Now, go to classwizard, then select 'Member variable Tag' and add a member variable for your list control of category="Control" and VariableType='CListCtrlEx'. Give any name you want to your member variable (let's say m_ListCtrlEx). Do not forget to include 'ListCtrlEx.h' in your Dialog class' header file.
  5. In the OnInitDialog() function of your Dialog class, add the following lines of code:
BOOL CCListCtrlExDemoDlg::OnInitDialog()
{
 ...
 m_ListCtrlEx.SetStyles();
 m_ListCtrlEx.SetNoOfRows(5); 
 m_ListCtrlEx.SetNoOfColumns(3);
 m_ListCtrlEx.OnInitialUpdate();
}

That's it. Now, run the program and select subitems in the list control without having full row selection.

Conclusion

With this I will hope, you will get an idea how to show subitem selection in a List control.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here