关于CListCtrl表头单击消息

devzhao 2003-12-19 05:38:05
我想单击某一列的表头,则内容就按该列排序显示,该如何实现,
对应的windows message是什么?
...全文
661 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
brytison 2004-02-02
  • 打赏
  • 举报
回复
mark
popyyb 2004-01-14
  • 打赏
  • 举报
回复
mark
brytison 2003-12-20
  • 打赏
  • 举报
回复
恩,不错。
sinhighly 2003-12-19
  • 打赏
  • 举报
回复
强烈同意
wangweixing2000 2003-12-19
  • 打赏
  • 举报
回复
ninsenki(流浪鸟) 说的对
arvid_gs 2003-12-19
  • 打赏
  • 举报
回复
列表控件(CListCtrl)的顶部有一排按钮,用户可以通过选择不同的列来对记录进行排序。但是 CListCtrl并没有自动排序的功能,我们需要自己添加一个用于排序的回调函数来比较两个数据的大小,此外还需要响应排序按钮被点击的消息。下面讲述一下具体的做法。

CListCtrl提供了用于排序的函数,函数原型为:BOOL CListCtrl::SortItems( PFNLVCOMPARE pfnCompare, DWORD dwData )。其中第一个参数为全局排序函数的地址,第二个参数为用户数据,你可以根据你的需要传递一个数据或是指针。该函数返回-1代表第一项排应在第二项前面,返回1代表第一项排应在第二项后面,返回0代表两项相等。

用于排序的函数原形为:int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort),其中第三个参数为调用者传递的数据(即调用SortItems时的第二个参数dwData)。第一和第二个参数为用于比较的两项的ItemData,你可以通过DWORD CListCtrl::GetItemData( int nItem )/BOOL CListCtrl::SetItemData( int nItem, DWORD dwData )来对每一项的ItemData进行存取。在添加项时选用特定的CListCtrl::InsertItem也可以设置该值。由于你在排序时只能通过该值来确定项的位置所以你应该比较明确的确定该值的含义。

下面我们看一个例子,这个例子是一个派生类,并支持顺序/倒序两种方式排序。 //全局数据
struct DEMO_DATA
{
char szName[20];
int iAge;
}strAllData[5]={{"王某",30},{"张某",40},{"武某",32},{"陈某",20},{"李某",36}};

//使用方法
BOOL CSort_in_list_ctrlDlg::OnInitDialog()
{
CDialog::OnInitDialog();

//初始化ListCtrl中数据列表
m_listTest.InsertColumn(0,"姓名");
m_listTest.InsertColumn(1,"年龄");
m_listTest.SetColumnWidth(0,80);
m_listTest.SetColumnWidth(1,80);
for(int i=0;i<5;i++)
{
m_listTest.InsertItem(i,strAllData[i].szName);
char szAge[10];
sprintf(szAge,"%d",strAllData[i].iAge);
m_listTest.SetItemText(i,1,szAge);
//设置每项的ItemData为数组中数据的索引
//在排序函数中通过该ItemData来确定数据
m_listTest.SetItemData(i,i);
}
return TRUE; // return TRUE unless you set the focus to a control
}

//类定义
class CSortList : public CListCtrl
{
// Construction
public:
CSortList();
BOOL m_fAsc;//是否顺序排序
int m_nSortedCol;//当前排序的列
protected:
//{{AFX_MSG(CSortList)
//}}AFX_MSG
//手工定义消息映射,处理顶部按钮被按下的消息
afx_msg void OnHeaderClicked(NMHDR* pNMHDR, LRESULT* pResult);
...
};

//CPP文件
//排序函数
int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);

CSortList::CSortList()
{
m_fAsc=TRUE;
}

CSortList::~CSortList()
{
}


BEGIN_MESSAGE_MAP(CSortList, CListCtrl)
//{{AFX_MSG_MAP(CSortList)
//}}AFX_MSG_MAP
//手工定义消息映射,处理顶部按钮被按下的消息
ON_NOTIFY(HDN_ITEMCLICK, 0, OnHeaderClicked)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSortList message handlers
//处理顶部按钮被按下的消息
void CSortList::OnHeaderClicked(NMHDR* pNMHDR, LRESULT* pResult)
{
HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;
if( phdn->iButton == 0 )
{
//设置排序方式
if( phdn->iItem == m_nSortedCol )
m_fAsc = !m_fAsc;
else
m_fAsc = TRUE;
//设置排序的列
m_nSortedCol = phdn->iItem;
//开始排序
SortItems( ListCompare, (DWORD)this );
}
}

//排序函数实现
int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
//通过传递的参数来得到CSortList对象指针
CSortList* pV=(CSortList*)lParamSort;

//通过ItemData来确定数据
DEMO_DATA* pInfo1=strAllData+lParam1;
DEMO_DATA* pInfo2=strAllData+lParam2;
CString szComp1,szComp2;
int iCompRes;
switch(pV->m_nSortedCol)
{
case(0):
//以第一列为根据排序
szComp1=pInfo1->szName;
szComp2=pInfo2->szName;
iCompRes=szComp1.Compare(szComp2);
break;
case(1):
//以第二列为根据排序
if(pInfo1->iAge == pInfo2->iAge)
iCompRes = 0;
else
iCompRes=(pInfo1->iAge < pInfo2->iAge)?-1:1;
break;
default:
ASSERT(0);
break;
}
//根据当前的排序方式进行调整
if(pV->m_fAsc)
return iCompRes;
else
return iCompRes*-1;
}
ninsenki 2003-12-19
  • 打赏
  • 举报
回复
LVN_COLUMNCLICK
arvid_gs 2003-12-19
  • 打赏
  • 举报
回复
排序功能的实现

列表控制有一个特殊的功能,当以详细资料方式显示时,列表顶部的表头可以当作按钮来使用,这可以通过列表控制创建时的风格来控制。当鼠标点击列表头名称时,列表控制就会向其父窗口发送一个LNV_COLUMNCLICK消息,利用类导向中列表控制IDC_LISTCTRL对应的LNV_COLUMNCLICK消息加入相应处理函数,就可将表列按照特定顺序进行排列。其函数使用方法见程序,其中iSort为排序的表列索引号,(PFNLVCOMPARE)CompareFunc为进行具体排序的回调函数,也就是说,通过鼠标点击表头实现的排序过程是由第三方开发的专用排序函数来实现的,排序函数只是实现表项的具体比较操作,而整个排序过程是由SortItemS属性通过不断调用这个函数来实现的。正常的排序过程是升序方式,通过调换排序函数中的参数值,就可实现降序排列,即将PARAM1与PARAM2调换位置。这个回调函数的前两个参数为表列中表项的索引号,第三个参数为排序的表列索引号。

void CVCLISTDlg::OnColumnclickListctrl(NMHDR* pNMHDR, LRESULT* pResult)

{ //鼠标左键单击表头处理函数

NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

// TODO: Add your control notification handler code here

static int iSorted=-1;//排列序号

if (pNMListView->iSubItem==iSorted) return;

iSorted=pNMListView->iSubItem;

m_ListCtrl.SortItems((PFNLVCOMPARE)CompareFunc,iSorted);

*pResult = 0;

}

//排序时比较表项的回调函数

int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2,LPARAM lParamSort)

{ char *text1,*text2;

switch (lParamSort){

case 0L:text1=Sps[lParam1].szPm;

text2=Sps[lParam2].szPm;break;

case 1L:text1=Sps[lParam1].szSl;

text2=Sps[lParam2].szSl;break;

case 2L:text1=Sps[lParam1].szDj;

text2=Sps[lParam2].szDj;break;

case 3L:text1=Sps[lParam1].szJe;

text2=Sps[lParam2].szJe;break;

}

return (strcmp(text1,text2));//结果为>0 =0 <0

}

同样,也可以通过专用按钮来实现排序功能,如本文的排序按钮对应的功能代码如下:

void CVCLISTDlg::OnSort()

{ // TODO: Add your control notification handler code here

m_ListCtrl.SortItems((PFNLVCOMPARE)CompareFunc,0);}

15,980

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧