Click here to Skip to main content
15,885,031 members
Articles / Desktop Programming / MFC
Article

SubItem Selection in List Control

Rate me:
Please Sign up or sign in to vote.
4.10/5 (11 votes)
5 Sep 20041 min read 85.1K   1.8K   33   3
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


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questionhow to select multiple subitems. Pin
narmada Padhy29-Aug-12 17:54
narmada Padhy29-Aug-12 17:54 
GeneralMy vote of 3 Pin
David Crow23-Aug-10 8:40
David Crow23-Aug-10 8:40 
QuestionThis is possible in ReportView's style? Pin
hakers27-Aug-05 20:23
hakers27-Aug-05 20:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.