在ListControl中使用检查框
闻怡洋翻译

This article was contributed by Eran Yariv.

List Control/View给了界面设计者更多的选择,开发者可以方便的显示列表。下面我们介绍一中带有检查框的ListCtrl,其中你可以得到用户的点击情况以改变选择状态。我们将利用一个CListCtrl的派生类CCheckListBox来实现。

你可以使用OWNER_DRAW风格来自己绘制检查框(我以前翻译过一篇文章是利用改变状态来显示不同IMG,有兴趣可以查查 译者),还有一种简单的方法是利用IE3中带有的新风格。

本文介绍一些新的风格,这些可以在VC5或更高版本上使用。

首先我们需要更改CONTROL的风格。

ListView_SetExtendedListViewStyle 
   (m_lvTestList.m_hWnd, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
下面介绍一些新的风格:
LVS_EX_CHECKBOXES 使用检查框
LVS_EX_FULLROWSELECT 选择整行
LVS_EX_GRIDLINES 在REPORT中画出分隔线
LVS_EX_HEADERDRAGDROP LVS_REPORT时可以利用drag-and-drop重新排序
LVS_EX_SUBITEMIMAGES 允许在子项中显示image
LVS_EX_TRACKSELECT 当鼠标指到某一项时便自动选择该项
映射下面的消息:
ON_NOTIFY(LVN_ITEMCHANGED, IDC_MYLIST, OnItemchangedLinksList)

得到检查状态

void DemoDlg::OnItemchangedLinksList(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	*pResult = 0;

	if (pNMListView->uOldState == 0 && pNMListView->uNewState == 0)
		return;	// No change

	BOOL bPrevState = (BOOL)(((pNMListView->uOldState & 
				LVIS_STATEIMAGEMASK)>>12)-1);   // Old check box state
	if (bPrevState < 0)	// On startup there's no previous state 
		bPrevState = 0; // so assign as false (unchecked)

	// New check box state
	BOOL bChecked=(BOOL)(((pNMListView->uNewState & LVIS_STATEIMAGEMASK)>>12)-1);   
	if (bChecked < 0) // On non-checkbox notifications assume false
		bChecked = 0; 

	if (bPrevState == bChecked) // No change in check box
		return;
	
	// Now bChecked holds the new check box state

	// ....
}

设置检查框状态

void SetLVCheck (WPARAM ItemIndex, BOOL bCheck)
{
	ListView_SetItemState (m_lvTestList.m_hWnd, ItemIndex, 
		UINT((int(bCheck) + 1) << 12), LVIS_STATEIMAGEMASK);
}

得到检查框状态

使用在commctl.h中定义的宏 ListView_GetCheckState(hwndLV,i);hwndLV为CONTROL的句柄,i为位置索引。