Click here to Skip to main content
Click here to Skip to main content

SubItem Selection in List Control

, 5 Sep 2004
Rate this:
Please Sign up or sign in to vote.
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

About the Author

Muhammad Azam
Web Developer
United States United States
No Biography provided

Comments and Discussions

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

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140709.1 | Last Updated 6 Sep 2004
Article Copyright 2004 by Muhammad Azam
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid