| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 9766 人关注过本帖, 1 人收藏
标题:[原创]CListCtrl详解
取消只看楼主 加入收藏
myajax95
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:30
帖 子:2978
专家分:0
注 册:2006-3-5
收藏(1)
 问题点数:0 回复次数:8 
[原创]CListCtrl详解

(07/15 更新: 几乎重写)
作为MFC中最常用的控件之一,CListCtrl功能的使用,修改及扩展是一个很深,很广泛的问题。在学习的过程中我尽量留下笔记,贴在这里和大家共享,欢迎大家挑错。

CListCtrl应用在作表格上最多,所以一般研究的功能都是Report view。
下面的程序实现了一些ListCtrl的加强功能。如果你遇到这个问题想找一个现成的解决方法,你可以下载下面的小程序包。

0gjad9M4.rar (48.23 KB) [原创]CListCtrl详解



这个增强的listctrl控件支持CheckBox和彩色字体。同时可以选择当鼠标选中一个格子的时候是全行显示被选中,还是只有这个格子显示被选中。上图中只有当前的格子被选中。
对程序稍作修改可以调整背景颜色等等。
如果想在表格中显示其它控件,只需要按照下面说的方法加入两三个函数就可以了。

下面讲一下怎么应用这个小程序:

这是一个演示增强控件CListReport的程序,如果你要用CListReport这个控件,需要把在Shared Classes里面的六个文件加到你的project中。6个文件所在目录的深度需要一样,否则在include的语句中你需要修改以下路径。

在你的Dialog或者FormView里加上想要用的List Control。在class wizard里给list control加控制变量,variable type里就会有CListCtrl和CListReport两个选后者,然后把List Control的Proprty中View设成Report,然后选Owner draw fixed。就可以了。(如果由于一些原因你在class wizard中找不到CListReport,可以直接加成CListCtrl类,然后在自己的.h中将其改成CListReport,然后在.h最前面写 #include "路径/ListReport.h")


CListReport的默认显示方式是全行选中,就是当你选中一个格子的时候全行被hightlight,这个和CListCtrl的默认风格一样。想改成选中格子就只加重这个格子,在你的Dialog或FormView的析构函数中初始话风格变量:
CListDemoDlg::CListDemoDlg(CWnd* pParent /*=NULL*/)
: CDialog(CListDemoDlg::IDD, pParent)
, m_listDemo(ListReportDefinition::intCellSelect)

用以下方法在表格中进行添加。
在你的主程序中用下面的方法调用: 假设变量名叫m_listDemo
CReportCtrl m_listDemo
在header中加一列: m_listDemo.AddColumn("Column 0", 0); //第一个参数是列的文字,第二个参数是列号。
在header中加一列,并指定其宽度为200: m_listDemo.AddColumn("Column 0", 0, 200);

在第0行第0列加Text "Row 0, Col 000",红色字体,粗体字
m_listDemo.AddItem(0, 0, "Row 0, Col 000", CListItemText::GenerateProperty(true, RGB(255, 0, 0)))
字太长的时候item会显示成...(如图)。
在第0行第1列加Text "Row 0, Col 100",绿色字体,非粗体字
m_listDemo.AddItem(0, 1, "Row 0, Col 100", CListItemText::GenerateProperty(false, RGB(0, 255, 0)));
在第0行第2列加Check Box,初始状态为选中。
m_listDemo.AddItem(0, 2, "1", CListItemCheckBox::GenerateProperty());


基本上直接使用的函数就这些了。如果你想作进一步修改
1。改写DrawItem()函数,可以将颜色背景颜色之类的进行调整。
2。如果除了彩色字体和checkbox你还想加入别的类,例如图片类。你只需要作以下几个步骤:
生成一个普通的C++ class,从CListItem继承下来(#include "路径/ListItem.h",或者直接写在ListItem.h/.cpp中)。
CListItem是显示没个小格子的基类。对于你的contructor而言,你可以定义格子的风格参数。例如CListItemText中定义了是否是粗体字,是什么颜色等等。CListItemCheckBox没有任何附加的功能,contructor就是空的。这里我用CSV格式来将所有的参数一次性输入,然后在画图的时候再将其展开。每个函数的GenerateProperty()就是实现这个功能的。
好,假设你已经定义好了所有风格,或者没有风格,下面需要写的就是如何显示它了。实现DrawRect(CDC &dc, CRect rcItem, string sText, bool bSelected)函数。 其中提供了dc,格子的位置,格子的内容以及当前是否被选中,干什么都够了。
显示已经作完了。如果你想实现点击功能,需要写ClickItem和DbClickItem这两个功能。注意在List中如果点的很快,响应将是double click,所以像CheckBox,必须重载ClickItem和DbClickItem这两个功能,而不能只重载ClickItem参数中第一个pParent是这个List。另外两个是行和列。

需要注意的问题是,这个ListReport控件使用了ON_WM_LBUTTONDOWN和ON_WM_LBUTTONDBLCLK两个事件,那么其parent就无法获得这两个事件了。作为补偿,这里增加了两个user message:
#define WM_LISTREPORT_LBUTTONDOWN WM_USER+1201
#define WM_LISTREPORT_LBUTTONDBLCLK WM_USER+1202
你的主Dialog可以像处理ON_WM_LBUTTONDOWN和ON_WM_LBUTTONDBLCLK一样处理这两个事件,我没有在PostMessage里面加任何参数,因为好像没太多必要。找到鼠标的位置然后hittest一下就得到所有信息了。如果有什么其它需要的希望大家提醒。

尚存问题:目前为止发现的问题是有时候连续选中一行的不同列的时候反应比较慢,能长达半秒钟。主要问题大概是ListCtrl本身把这一行来回draw了好几遍。我的DrawItem里面需要更仔细的判断以提高速度。

功能讲完了。制作的原理大概就是在鼠标左键按下的时候记下鼠标的位置,重载DrawItem函数,根据鼠标位置决定文字的背景颜色。程序应该很好懂,有什么问题欢迎大家指正。

其它ListCtrl的常见问题:
问题1:如何左击list的列的时候如何获得当前的列号?
ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST, OnLvnColumnclickList)

void CDlgLists::OnLvnColumnclickList(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
int intSelectedColumn = pNMLV->iSubItem;

这里intSelectedColumn就是当前选中的列好了。

这个事件也可以在list内管理,而不在Dialog中管理。看具体的处理事件是什么了。一般的概念就是谁来处理这个事件就有谁管理。例如我的list上有30行,我想用ListCtrl自身的sort()来重新排序,那么这个事件应该由list管理。如果希望sort有其Dialog实现,就应该在Dialog中管理。我个人更加倾向于在Dialog中管理。因为list本身能作的事情太有限了。例如我要求sort()结束后在下面的状态栏里显示Sort by 哪一列,这个很小的附加功能对于list管理的方法而言就很不舒服了。另外如果list显示的是一个巨大的数据库中的某一页,我想sort()的时候当然是对整个数据库sort()。list控件的sort()对此无能为力。

以后我会不断更新本文,增加其它CListCtrl的功能,并讲解相关问题。


[此贴子已经被作者于2006-7-16 14:38:19编辑过]



qcL7xNUH.rar (32.08 KB) [原创]CListCtrl详解



DpWx0Fp3.jpg (23.64 KB)
图片附件: 游客没有浏览图片的权限,请 登录注册


elprAoWd.rar (44.29 KB) [原创]CListCtrl详解



CYYcxK82.jpg (23.41 KB)
图片附件: 游客没有浏览图片的权限,请 登录注册


gsgtrjfb.rar (41.07 KB) [原创]CListCtrl详解



e6xIVycE.rar (46.84 KB) [原创]CListCtrl详解

搜索更多相关主题的帖子: CListCtrl 详解 鼠标 控件 字体 
2006-07-08 16:53
myajax95
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:30
帖 子:2978
专家分:0
注 册:2006-3-5
收藏
得分:0 

新加了CheckBox,同时可以显示彩色字体和粗体。以后加入位图或者按钮应该没什么难度。


http://myajax95./
2006-07-09 14:47
myajax95
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:30
帖 子:2978
专家分:0
注 册:2006-3-5
收藏
得分:0 
5楼的,我刚试了一下,没有这个问题,可能是你打开project的方法不对。可以试着重新下载,或者把包里的CSVLineParser.h和.cpp重新加到project中。

http://myajax95./
2006-07-11 22:54
myajax95
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:30
帖 子:2978
专家分:0
注 册:2006-3-5
收藏
得分:0 
是个CListCtrl,以后会加上位图,没准下拉菜单等功能。

http://myajax95./
2006-07-14 00:16
myajax95
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:30
帖 子:2978
专家分:0
注 册:2006-3-5
收藏
得分:0 
以下是引用热情依然在2006-7-15 13:13:18的发言:
好东西,我正想派生CListCtrl,但是楼主那个程序选中单列的时候响应太慢了,这样做数据库操作的时候就麻烦了

不知道说的是怎么个单列选择?我知道选check box的时候点的太快会不响应,正在调查这个问题。


http://myajax95./
2006-07-15 19:38
myajax95
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:30
帖 子:2978
专家分:0
注 册:2006-3-5
收藏
得分:0 
响应慢的问题已经解决。1楼的下载已经更新。

http://myajax95./
2006-07-15 19:59
myajax95
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:30
帖 子:2978
专家分:0
注 册:2006-3-5
收藏
得分:0 
如果只要实现在list中加text和checkbox,这样的listctrl会很简单,这个控件主要还是要继续扩展功能。

http://myajax95./
2006-07-22 01:23
myajax95
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:30
帖 子:2978
专家分:0
注 册:2006-3-5
收藏
得分:0 
以下是引用a813649在2006-8-12 11:08:20的发言:
偶是新手,感觉楼主的程序好深,好多函数看不懂啊。。
我想请教一下 怎么样才能在CListctrl中的随即列加入类似checkbox的控件。
目前做的一个课题现在就卡在这了。。麻烦楼主帮忙下。
如果可以的话,希望能发个详细的方案到鄙人邮箱。。。

如果只需要checkbox 功能可以在CListCtrl的style中改
试一下在OnInitDialog中加上下面一段:
m_list.SetExtendedStyle(m_list.GetExtendedStyle() | LVS_EX_CHECKBOXES);


http://myajax95./
2006-08-15 22:59
myajax95
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:30
帖 子:2978
专家分:0
注 册:2006-3-5
收藏
得分:0 
以下是引用yyeungg在2006-8-13 20:52:19的发言:
楼主 我用了你的控件 可是出现了一个问题 就是字体较大的时候 因为行的高度较小 控件就不能完全显示字了 只能显示一部分 看了程序 不知道应该改哪里 能麻烦你告诉我一下吗 非常感谢

怎样增大CListCtrl的行距?(回答人:aogun)
试试插入一列图片,图片的高度设为你想要的高度,这样行高就变高了

程序代码:

CImageList imagelist;
ImageList.Create(1, 40, ILC_COLOR, 10, 10);
m_ListCtrl.SetImageList(&ImageList, LVSIL_SMALL);


http://myajax95./
2006-08-15 23:00
快速回复:[原创]CListCtrl详解
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.014734 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved