SubItem Selection in List Control






4.10/5 (11 votes)
Sep 6, 2004
1 min read

86045

1849
Explains how to select Sub Items in Report style List Control.
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:
- Using MFC AppWizard, create a Dialog Based application. Give the application name as you like.
- Now, add a List-Control and in Properties, change the style to Report. This style is necessary if we want multiple columns.
- 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.
- 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. - 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.