CListCtrl FAQ

개발 2007/06/19 12:28

Celtic Wolf, Inc. Home Page
Back to Useful Information

This FAQ answers questions that are frequently asked in microsoft.public.vc.mfc about the MFC class CListCtrl and the related class CListView.

Contents:
Insertion
1. When I try to insert information in the second, third, etc. columns, with InsertItem(), it doesn't work. Why?
Appearance
2. How do I make selection appear even when control doesn't have focus?
3. How do I select the entire row?
Getting and setting item states
4. How do I get the item's selected/focused state?
5. How can I check the state of an item's checkbox
6. How do I programmatically (de)select an item?
7. How do I programmatically make an item (un)focused?
8. How do I programmatically set the state of an item's checkbox?
Preventing the user from altering item states
9. How do I prevent an item from being (de)selected?
10. How can I prevent an item from being (un)checked?
Finding items
11. How do I find the (first) selected item?
12. How do I find the item with the focus?
Columns
13. When I create my control with column 0 set for center or right justification, why is it drawn with left justification?
Sorting
14. When my sorting callback function is called, why are lParam1 and lParam2 always 0?
15. How can I sort the control when the user clicks on a column header?
Advanced
16. How can I get the contents of a control in another program?

1. When I try to insert information in the second, third, etc. columns, with InsertItem(), it doesn't work. Why?

LVITEM lvi;
::ZeroMemory(&lvi, sizeof(LVITEM));
// Insert item for col 0
lvi.mask = LVIF_TEXT;
lvi.pszText = "one";
m_ListCtrl.InsertItem(&lvi);
// Insert subitem for col 1
lvi.pszText = "two";
lvi.iSubItem = 1;
m_ListCtrl.InsertItem(&lvi);

You can't use any of the InsertItem() functions or messages to insert subitems. Instead, you must use SetItemText() (or ListView_SetItemText() or LVM_SETITEMTEXT). InsertItem() inserts the row and populates the first cell. In order to populate additional cells in that row, you must call SetItemText().

2. How do I make selection appear even when control doesn't have focus?

Use the style LVS_SHOWSELALWAYS when creating your control.

3. How do I select the entire row?

Use CListCtrl::SetExtendedStyle to set the style LVS_EX_FULLROWSELECT. Note that this requires version 4.70 or higher of the comctl32.dll.

4. How do I get the item's selected/focused state?

UINT uState = m_ListCtrl.GetItemState(iIndex, LVIS_SELECTED | LVIS_FOCUSED);
if (uState & LVIS_SELECTED)
	// Item is selected
if (uState & LVIS_FOCUSED)
	// Item has the focus

5. How can I check the state of an item's checkbox

Use CListCtrl::GetCheck() or ListView_GetCheckState()

6. How do I programmatically (de)select an item?

Select: m_ListCtrl.SetItemState(iItem, LVIS_SELECTED, LVIS_SELECTED);
Deselect: m_ListCtrl.SetItemState(iItem, 0, LVIS_SELECTED);

7. How do I programmatically make an item (un)focused?

Focused: m_ListCtrl.SetItemState(iItem, LVIS_FOCUSED, LVIS_FOCUSED);
Unfocused: m_ListCtrl.SetItemState(iItem, 0, LVIS_FOCUSED);

8. How do I programmatically set the state of an item's checkbox?

Use CListCtrl::SetCheck() or the following macro:

#ifndef ListView_SetCheckState
   #define ListView_SetCheckState(hwndLV, i, fCheck) \
      ListView_SetItemState(hwndLV, i, \
      INDEXTOSTATEIMAGEMASK((fCheck)+1), LVIS_STATEIMAGEMASK)
#endif

9. How do I prevent an item from being (de)selected?

10. How can I prevent an item from being (un)checked?

You'll need to handle LVN_ITEMCHANGING and return FALSE to allow the item to be (un)checked or (de)selected and return TRUE to disallow a change.

Here's some code that might help.

Add this to your CMyListCtrl class definition as a protected function:

// Returns TRUE if the item is checked, false if it is not or uState == 0
inline BOOL IsChecked(UINT uState) {return
(uState ? ((uState & LVIS_STATEIMAGEMASK) >> 12) - 1 : FALSE);}

Here's a sample function for handling LVN_ITEMCHANGING:

void CTestListView::OnItemchanging(NMHDR* pNMHDR, LRESULT* pResult)
{
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	
	// If old state is unchecked and new state is checked
	// then item is being checked.
	if ((! IsChecked(pNMListView->uOldState)) &&
		(IsChecked(pNMListView->uNewState)))
		MessageBox("Item is being checked");
	
	// If old state is checked and new state is unchecked,
	// item is being unchecked
	else if ((IsChecked(pNMListView->uOldState)) &&
		(! IsChecked(pNMListView->uNewState)))
		MessageBox("Item is being unchecked");

	// return FALSE (or 0) to allow change, TRUE to prevent
	*pResult = 0;
}//OnItemchanging

11. How do I find the (first) selected item?

First: int iItem = m_ListCtrl.GetNextItem(-1, LVNI_SELECTED);
Subsequent: iItem = m_ListCtrl.GetNextItem(iItem, LVNI_SELECTED);

12. How do I find the item with the focus?

int iItem = m_ListCtrl.GetNextItem(-1, LVNI_FOCUSED);

13. When I create my control with column 0 set for center or right justification, why is it drawn with left justification?

For some reason, the control doesn't pay any attention to the LVCOLUMN.fmt value when creating the column. However, you can change this value later by calling CListCtrl::SetColumn() (or using ListView_SetColumn or LVM_SETCOLUMN). Simply set LVCOLUMN.fmt to the desired value.

LVCOLUMN lvCol;
::ZeroMemory(&lvCol, sizeof(LVCOLUMN));
lvCol.mask = LVCF_TEXT;
lvCol.pszText = "Col0";
// Insert the column
int iCol = m_ListCtrl.InsertColumn(0, &lvCol);
// Set it to be centered
lvCol.mask = LVCF_FMT;
lvCol.fmt = LVCFMT_CENTER;
BOOL bRes = m_ListCtrl.SetColumn(iCol, &lvCol);

14. When my sorting callback function is called, why are lParam1 and lParam2 always 0?

Some versions of the documentation on CListCtrl::SortItems and LVM_SORTITEMS seem to imply that the values of lParam1 and lParam2 are the indices of the items to be sorted. This is not the case. They are the 32 bit values that can be assigned to each item via CListCtrl::SetItemData or via the lParam member of the LVITEM struct. If you have not assigned any data to these variables, then they will be zero when passed to your sort function.

15. How can I sort the control when the user clicks on a column header?

To capture the click event: Sorting the list when user clicks on column header
To draw a sort arrow on the header: Indicating sort order in header control

16. How can I get the contents of a list control in another program?

See the September 1997 Win32 Q&A by Jeffrey Richter in MSJ

Home

Posted by 디오디오