Click here to Skip to main content
11,583,555 members (62,938 online)
Click here to Skip to main content

SubItem Selection in List Control

, 5 Sep 2004 65.3K 1.1K 32
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

Share

About the Author

Muhammad Azam
Web Developer
United States United States
No Biography provided

You may also be interested in...

Comments and Discussions

 
Questionhow to select multiple subitems. Pin
narmada Padhy29-Aug-12 17:54
membernarmada Padhy29-Aug-12 17:54 
GeneralMy vote of 3 Pin
DavidCrow23-Aug-10 8:40
mvpDavidCrow23-Aug-10 8:40 
QuestionThis is possible in ReportView's style? Pin
hakers27-Aug-05 20:23
memberhakers27-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 | Terms of Use | Mobile
Web04 | 2.8.150603.1 | Last Updated 6 Sep 2004
Article Copyright 2004 by Muhammad Azam
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid