王朝网络
分享
 
 
 

自身支持排序的ListCtrl

王朝vc·作者佚名  2006-01-09
宽屏版  字体: |||超大  

自身支持排序的ListCtrl

VC里的CListCtrl是个很不好用的控件,特别是排序,实现起来很麻烦。

关于排序的基本用法,有一篇很好的文章:

http://www.vchelp.net/vchelp/zart/sortl.asp?type_id=9&class_id=1&cata_id=1&article_id=73&search_term=

但是,在这个例子里也存在个问题:排序的实现是和数据源相关的,如果有若干个表需要排序的话,每个表都要写相应的代码,这是一件非常痛苦的事。

所以,在上面的基础上,重新写了一个自身支持排序的CSoftList,从某个意义上说,也算是实现文档和视图的真正分离。

下面说说几个主要的地方。

1. CSortList是CListCtrl的派生类 (好象是废话)

2. 要让CSortList自行排序,当然得让CSortList自己处理LVN_COLUMNCLICK消息

ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnLvnColumnclick)

OnLvnColumnclick的作用就是设置排序列,排序方式,最后调用SortItems()。

3. 排序的具体实现,也就是CALLBACK ListCompare(...)的实现:

基本要求: 让CSortList根据Item进行排序,而与数据源无关。(当然这样也有不足之处,就是排序只能按文本排序了。如果你需要按数字排序的话,那就只有特殊处理了。)

这里涉及到的最主要的函数是:

1)ListCompare - 实现排序的回调函数

int CALLBACK CSortList::ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);

2)CListCtrl::FindItem - 查找相应的Item, 查找方式可指定

int FindItem( LVFINDINFO* pFindInfo, int nStart = -1 ) const;

FindItem的具体细节请参考MSDN.

基本思路:

1)ListCompare的原型:传入的参数lParam1,lParam2是相应两行的ItemData;

2)FindItem根据lParam1,lParam2得到相应的Item;

FindItem有多种查找方式(查找方式通过LVFINDINFO->flags进行设置),这里只是根据ItemData进行查找。

3)再用GetItemText得到排序列的ItemText;

4)最后就是比较ItemText了。

4. 显示指明排序方式的标记

简单地说,就是给CListCtrl的CHeadCtrl指定一个CImageList,根据需要指定Column要显示的Image。

主要函数:

1)CHeaderCtrl::GetItem - 取得表头控制中某一项目的内容

BOOL GetItem( int nPos, HDITEM* pHeaderItem ) const;

2)CHeaderCtrl::SetItem - 设置表头控制中某一项目的内容

BOOL SetItem( int nPos, HDITEM* pHeaderItem );

下面是源代码:

只有两个文件:CSortList.H, CSortList.cpp

直接把这两个文件放到项目里就可以了。

唯一要注意的是:IDB_HDRUP, IDB_HDRDOWN 是两个位图资源,分别表示顺序和倒序,这个就需要自己弄了。

A. SoftList.h

#if !defined(AFX_SORTLIST_H__6ACE2F6F_AEFE_11D3_BDE9_F4145AA4F676__INCLUDED_)

#define AFX_SORTLIST_H__6ACE2F6F_AEFE_11D3_BDE9_F4145AA4F676__INCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

// SortList.h : header file

//

/////////////////////////////////////////////////////////////////////////////

// CSortList window

class CSortList : public CListCtrl

{

// Construction

public:

CSortList();

// Attributes

public:

// Operations

public:

// Overrides

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CSortList)

//}}AFX_VIRTUAL

// Implementation

public:

virtual ~CSortList();

// Generated message map functions

protected:

//{{AFX_MSG(CSortList)

afx_msg bool OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult);

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

public:

afx_msg void OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult);

void CreateSortIcons();

void SetSortIcon();

bool GetFullRowSelect();

// 设置为行选中

void SetFullRowSelect( bool bFullRowSelect );

bool GetGridLines();

// 设置绘制表格

void SetGridLines( bool bGridLines );

static CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);

public:

BOOL m_bAsc;//是否顺序排序

int m_nSortedCol;//当前排序的列

private:

CBitmap m_bmpUpArrow;

CBitmap m_bmpDownArrow;

int m_nUpArrow;

int m_nDownArrow;

CImageList m_imglstSortIcons;

};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}

// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_SORTLIST_H__6ACE2F6F_AEFE_11D3_BDE9_F4145AA4F676__INCLUDED_)

B. SoftList.cpp

// SortList.cpp : implementation file

//

#include "stdafx.h"

#include "SortList.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

/////////////////////////////////////////////////////////////////////////////

// CSortList

CSortList::CSortList()

{

m_bAsc=TRUE;

//this->m_nSortedCol = -1;

CreateSortIcons();

//GetHeaderCtrl()->SetImageList(&m_imglstSortIcons);

}

CSortList::~CSortList()

{

m_imglstSortIcons.DeleteImageList();

m_bmpUpArrow.DeleteObject();

m_bmpDownArrow.DeleteObject();

}

BEGIN_MESSAGE_MAP(CSortList, CListCtrl)

//{{AFX_MSG_MAP(CSortList)

//}}AFX_MSG_MAP

ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnLvnColumnclick)

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CSortList message handlers

void CSortList::OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult)

{

LPNMLISTVIEW pNMListView = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);

// TODO: Add your control notification handler code here

//NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

if( pNMListView->iSubItem == m_nSortedCol )

m_bAsc = !m_bAsc;

else

{

m_bAsc = TRUE;

m_nSortedCol = pNMListView->iSubItem;

}

SortItems( ListCompare, (DWORD)this );

SetSortIcon();

*pResult = 0;

}

void CSortList::CreateSortIcons()

{

if (!m_imglstSortIcons.m_hImageList)

{

COLORMAP cm = {RGB(0, 0, 0), GetSysColor(COLOR_GRAYTEXT)};

m_imglstSortIcons.Create (9, 5, ILC_COLOR24 | ILC_MASK, 2, 0);

m_bmpUpArrow.LoadMappedBitmap(IDB_HDRUP, 0, &cm, 1);

m_nUpArrow = m_imglstSortIcons.Add(&m_bmpUpArrow, RGB(255, 255, 255));

m_bmpDownArrow.LoadMappedBitmap(IDB_HDRDOWN, 0, &cm, 1);

m_nDownArrow = m_imglstSortIcons.Add(&m_bmpDownArrow, RGB(255, 255, 255));

}

}

void CSortList::SetSortIcon()

{

CHeaderCtrl* pHeaderCtrl = this->GetHeaderCtrl();

ASSERT(pHeaderCtrl);

pHeaderCtrl->SetImageList(&m_imglstSortIcons);

for( int col = 0; col< GetHeaderCtrl()->GetItemCount(); col++ )

{

HDITEM hdrItem = { 0,};

hdrItem.mask = HDI_FORMAT | HDI_IMAGE;

BOOL ret = pHeaderCtrl->GetItem(col-1, &hdrItem);

ret = pHeaderCtrl->GetItem(col+1, &hdrItem);

ret = pHeaderCtrl->GetItem(col, &hdrItem);

if ( m_nSortedCol == col)

{

hdrItem.fmt = hdrItem.fmt & HDF_JUSTIFYMASK | HDF_IMAGE | HDF_STRING | HDF_BITMAP_ON_RIGHT;

if( m_bAsc )

hdrItem.iImage = m_nUpArrow;

else

hdrItem.iImage = m_nDownArrow;

}

else

{

hdrItem.fmt = hdrItem.fmt & HDF_JUSTIFYMASK | HDF_STRING;

}

pHeaderCtrl->SetItem(col, &hdrItem);

}

}

bool CSortList::GetFullRowSelect()

{

return ( GetExtendedStyle()&LVS_EX_FULLROWSELECT) == LVS_EX_FULLROWSELECT;

}

void CSortList::SetFullRowSelect( bool bFullRowSelect )

{

if( bFullRowSelect )

SetExtendedStyle( GetExtendedStyle()|LVS_EX_FULLROWSELECT );

else

SetExtendedStyle( GetExtendedStyle()&(~LVS_EX_FULLROWSELECT) );

}

bool CSortList::GetGridLines()

{

return ( GetExtendedStyle() & LVS_EX_GRIDLINES ) == LVS_EX_GRIDLINES;

}

void CSortList::SetGridLines( bool bGridLines )

{

if( bGridLines )

SetExtendedStyle( GetExtendedStyle()|LVS_EX_GRIDLINES );

else

SetExtendedStyle( GetExtendedStyle()&(~LVS_EX_GRIDLINES) );

}

int CALLBACK CSortList::ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)

{

CSortList* pList=(CSortList*)lParamSort;

int nItem1, nItem2;

LVFINDINFO FindInfo;

FindInfo.flags = LVFI_PARAM; // 指定查找方式

FindInfo.lParam = lParam1;

nItem1 = pList->FindItem(&FindInfo, -1); // 得到对应Item索引

FindInfo.lParam = lParam2;

nItem2 = pList->FindItem(&FindInfo, -1);

if((nItem1 == -1) || (nItem2 == -1))

{

TRACE("无法找到!\n");

return 0;

}

CString Str1,Str2;

Str1 = pList->GetItemText(nItem1, pList->m_nSortedCol); // 得到排序列的Text

Str2 = pList->GetItemText(nItem2, pList->m_nSortedCol);

int iCompRes = 0;

if(Str1 > Str2)

iCompRes = 1;

else if(Str1 == Str2)

iCompRes = 0;

else

iCompRes = -1;

if(pList->m_bAsc)

return iCompRes;

else

return iCompRes*-1;

return 0;

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有