在CListCtrl的Report视图中的项目排序(摘自微软官方帮助和支持)

用于排序的项目在列表视图控件中,尤其是由CListCtrl MFC 类包装的过程提供了较少的信息。详细信息很容易实现,这篇文章会尝试填充此非常有用的功能的文档中的间隙。示例代码表示 MFC 对话框设置 LVS_REPORT 样式为列表控件。

要对列表视图控件中的项进行排序,必须为与项关联的LVITEM结构。MFC 提供这样的开发人员,使要插入具有合理的默认值创建结构的简单InsertItem (int nItem,LPCTSTR lpszItem)函数调用的项目。此类缓冲区从底层的复杂性有时会使人误解。但是, LVITEM结构是操作列表视图项,包括排序机制重要关键。

LVITEMlParam 元素提供了必要的信息。在调用 SortItemsCListCtrl 类的函数时,它必须提供要排序的回调函数和应用程序定义的 DWORD 值的函数指针。期间排序,选择列表控件中的两个项目进行比较时重复调用该回调函数。它接收到的参数是从每个项目的 LVITEM 结构,lParam 元素和 SortItems 调用由传递的 DWORD 值。

下面的代码表示一个简单的示例的十个美国总裁 ListView 控件中的列表进行排序。在总裁最初存储在静态多维 CString 数组中。

static CString strData[10][3] =
{
	{ _T("Washington"), _T("George"), _T("1789-1797") },
	{ _T("Adams"), _T("John"), _T("1797-1801") },
	{ _T("Jefferson"), _T("Thomas"), _T("1801-1809") },
	{ _T("Madison"), _T("James"), _T("1809-1817") },
	{ _T("Monroe"), _T("James"), _T("1817-1825") },
	{ _T("Adams"), _T("John Quincy"), _T("1825-1829") },
	{ _T("Jackson"), _T("Andrew"), _T("1829-1837") },
	{ _T("Van Buren"), _T("Martin"), _T("1837-1841") },
	{ _T("Harrison"), _T("William Henry"), _T("1841") },
	{ _T("Tyler"), _T("John"), _T("1841-1845") }
};

回调排序函数可能是静态定义为类的成员,或作为此处,只需为全局函数:

int CALLBACK SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);

lParam 元素可以是任何从简单到非常复杂。经常,结构是在此上下文从而允许多个要引用的数据片段中很有用的。此例如一个称为 ITEMDATA 的结构的定义是为了容纳组成给定的项目的三个元素:

ITEMDATA* m_pData[10];

在此示例中,结构定义在CDialog类的头文件中,并被定义为 10 的数组的指针的成员变量:

m_ctlListView.InsertColumn(0, _T("Last Name"), LVCFMT_LEFT, 100);
	m_ctlListView.InsertColumn(1, _T("First Name"), LVCFMT_LEFT, 100);
	m_ctlListView.InsertColumn(2, _T("Term"), LVCFMT_LEFT, 100);

	for (int i=0; i<10; i++)
	{
		m_pData[i] = new ITEMDATA;
		m_pData[i]->pszLastName = (LPTSTR)(LPCTSTR)strData[i][0];
		m_pData[i]->pszFirstName = (LPTSTR)(LPCTSTR)strData[i][1];
		m_pData[i]->pszTerm = (LPTSTR)(LPCTSTR)strData[i][2];

		m_ctlListView.InsertItem(i, strData[i][0]);
		m_ctlListView.SetItemText(i, 1, strData[i][1]);
		m_ctlListView.SetItemText(i, 2, strData[i][2]);
		m_ctlListView.SetItemData(i, (LPARAM)m_pData[i]);
	}

ListView 控件被添加到一个对话框,然后定义的成员变量名为 m_ctlListView。OnInitDialog中添加项目

三列插入的姓氏、 名字和术语的 office。然后,对于每个十个项目中,新的 ITEMDATA 结构进行分配和初始化 CString 数组中。插入项非常简单,只是索引和最后一个名称字符串中,使用,则文字将被设置为其他两项的列。最后, SetItemData调用函数时,将新的 ITEMDATA 作为参数。这样的项的 LVITEM 结构,lParam 将重新初始化并准备进行排序的方式。

ON_NOTIFY(HDN_ITEMCLICK, IDC_LIST1, OnItemclickList1)

此处的问题是通知并不实际源自 ListView 控件 ; 而是,创建该 ListView 的标头控件发送通知。在上面列出的消息映射项不起作用。此修复程序是简单,但是,因为标头控件总是具有一个 ID 为 0,宏可以进行编辑才能正常工作:

ON_NOTIFY(HDN_ITEMCLICK, 0, OnItemclickList1)

然后 OnItemclickList1 处理程序中进行 SortItems 调用:

ListView 的项目的对传递给该函数进行比较时,将重复调用 SortFunc 例程。前两个参数是各个项目的 LVITEM 结构,lParam 元素和第三个参数 (应用程序定义) 是在 SortItems 调用中提供的列数。

int CALLBACK SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
	int nRetVal;

	PITEMDATA pData1 = (PITEMDATA)lParam1;
	PITEMDATA pData2 = (PITEMDATA)lParam2;


	switch(lParamSort)
	{
	case 0:	// Last Name
		nRetVal = strcmp(pData1->pszLastName,
                                 pData2->pszLastName);
		break;

	case 1:	// First Name
		nRetVal = strcmp(pData1->pszFirstName,
                                 pData2->pszFirstName);
		break;

	case 2: // Term
		nRetVal = strcmp(pData1->pszTerm, pData2->pszTerm);
		break;

	default:
		break;
	}

	return nRetVal;
}

lParamSort 中传递的列索引确定 ITEMDATA 对象的哪个元素传递中 lParam1lParam2 应该用于比较。返回结果,该进程将持续到已经按排序的所有项目。

作为一个提醒 ITEMDATA 结构所分配的列表项的需要最终被销毁。此例如 WM_DESTROY 处理程序对话框用于循环访问成员元素,并删除它们。

for (int i=0; i<10; i++)
    delete m_pData[i];
				

The end......

 

 

posted @ 2012-08-03 09:33  imFolish  阅读(706)  评论(0编辑  收藏  举报