自身支持排序的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;
};
/////////////////////////////////////////////////////////////////////////////