标签:c++ mfc clistctrl cgridlistctrlex 说明
原文出处: http://www.codeproject.com/Articles/29064/CGridListCtrlEx-Grid-Control-Based-on-CListCtrl
另见: https://code.google.com/p/cgridlistctrlex
转载请注明出处!
微软的ClistCtrl提供了以报表的形式在表格中显示数据的功能,但是功能有限, 我们不得不自己扩充一些功能, 如下:
本文演示如何使用CGridListCtrlEx,它实现了上述所有功能,同时保持Windows XP/ Vista的样子.
SubVersion(svn) 版本见 Google Code - CGridListCtrlEx ,他同样有 Doxygen Documentation.
有很多CListCtrl的高级扩展控件,其中有一个 Enhanced List Control (CGfxListCtrl).这个niubility的控件提供了上述所有功能,但是不支持XP和Vista.找一个好用的替代实为不易:
CGridListCtrlEx插入了一个抽象层,称之为”column traits”(列特性),用来绘制和编辑单元格.若Microsoft又扩展了CListCtrl,希望CGridListCtrlEx能继续工作.
CGridListCtrlEx 试图还原一个真实的CListCtrl,不会替换任何CListCtrlalready已经提供的特性.这意味着我们可以用CGridListCtrlEx 直接替换CListCtrl 而不必做任何额外操作.
建议不要直接使用CGridListCtrlEx ,而是派生一个CGridListCtrlEx 的子类.这将使其更容易兼容以后的任何更新.
默认情况下,当向CGridListCtrlEx插入一列,会被配置为只读不可编辑的.通过调用CGridListCtrlEx::InsertColumnTrait(),我们可以提供一个CGridColumnTrait 类来指定使用什么类型的编辑器.
CGridColumnTrait* pTrait = new CGridColumnTraitEdit; m_ListCtrl.InsertColumnTrait(nCol, title.c_str(),LVCFMT_LEFT, 100, nCol, pTrait);当编辑一个项时,一个标准LVN_ENDLABELEDIT消息会被发送至CListCtrl.当CGridListCtrlEx收到这个消息时,它会自动调用虚方法CGridListCtrlEx::OnEditComplete(),使派生类确认输入,并可能会更新底层数据模型.
调用CGridListCtrlEx::InsertColumnTrait(),,我们还可以提供一个CGridColumnTrait 类使之像CComboBox一样工作.
CGridColumnTraitCombo* pTrait = new CGridColumnTraitCombo; pTrait->AddItem(0, "Hello"); pTrait->AddItem(1, "Goodbye"); m_ListCtrl.InsertColumnTrait(nCol, title.c_str(),LVCFMT_LEFT, 100, nCol, pTrait);上边的代码展示了,当插入列时指定CComboBox 项.如果想动态提供CComboBox 项,我们可以覆盖CGridListCtrlEx::OnEditBegin().使用dynamic_cast<>得到安全类型,调用列特性方法CGridColumnTraitCombo::LoadList(),或者直接使用返回的CComboBox编辑器.
如果想获取已选中的CComboBox项的itemdata,可以重载CGridListCtrlEx::OnEditComplete()并检查pLVDI->item.lParam.该值需要被另外保存, 因为它不能保存在CListCtrl的本地数据模型中.
默认情况下,GridListCtrlEx 会对所有列启用排序,它会执行一个简单的文本比较.也可以重载CGridColumnTrait::OnSortRows()根据列特性实现自定义排序.
配置列特性使用数量比较排序:
CGridColumnTraitEdit* pTrait = new CGridColumnTraitEdit; pTrait->SetSortFormatNumber(true); // Numeric column m_ListCtrl.InsertColumnTrait(nCol, title.c_str(),LVCFMT_LEFT, 100, nCol, pTrait);列特性CGridColumnTraitDateTime 会自动比较日期排序.
我们也可以选择重载方法,那么我们所要做的仅仅是选择一个正正确方式执行排序.参见CListCtrl 和行排序.
默认情况下,CGridListCtrlEx 仅显示单元格内容提示.如果想显示一些其他提示信息,可以CGridListCtrlEx::OnDisplayCellTooltip()重载方法.
如果想要改变前景/背景颜色,或者字体样式(粗体,斜体, 下划线), 可以重载CGridListCtrlEx::OnDisplayCellColor()方法和CGridListCtrlEx::OnDisplayCellFont()方法.
bool MyGridCtrl::OnDisplayCellColor(int nRow, int nCol, COLORREF& textColor,COLORREF& backColor) { if (nRow == 3 && nCol == 3) { textColor = RGB(0,255,0); backColor = RGB(0,0,255); return true; // I want to override the color of this cell } return false; // Use default color }
默认情况下,CGridListCtrlEx 启用扩展样式LVS_EX_SUBITEMIMAGES,但是仍需使用CListCtrl::SetImageList()附加一个CImageList .
附加完图片后,可以将CImageList中的索引绑定到单元格/子项上.这可以通过CGridListCtrlEx::SetCellImage()完成,或者如果使用了I_IMAGECALLBACK,那么图片索引号会从重载的CGridListCtrlEx::OnDisplayCellImage()返回.
默认情况下,CGridListCtrlEx 也启用了扩展样式LVS_EX_GRIDLINES,这会导致子项图片和边框重叠.可以通过使用16像素中的15像素(第一像素透明)来解决这个问题.
当使用子项图片并在XP下运行应用程序,或使用经典样式时, 当选中一行会显示白色背景. 这问题可以使用CGridRowTraitXP解决.
m_ListCtrl.SetDefaultRowTrait(new CGridRowTraitXP);
CListCtrl supports checkboxes for the labelcolumn out of the box. Just apply the extended styleLVS_EX_CHECKBOXES:
只要应用扩展样式LVS_EX_CHECKBOXES,便可支持标题栏复选框:
m_ListCtrl.SetExtendedStyle(m_ListCtrl.GetExtendedStyle()| LVS_EX_CHECKBOXES);
切记不要使用InsertHiddenLabelColumn(),它会隐藏标题栏和复选框.可以使用GetCheck() / SetCheck()来检索/修改复选框的值.
如果想要在多列使用复选框,可以使用CGridColumnTraitImage(和它的特性).
// Appendsthe unchecked/checked state images to the list control image list int nStateImageIdx = CGridColumnTraitImage::AppendStateImages(m_ListCtrl, m_ImageList); m_ListCtrl.SetImageList(&m_ImageList, LVSIL_SMALL); // Createsan image column, that can switch between the 2 images CGridColumnTrait* pTrait = new CGridColumnTraitImage(nStateIdx, 2); m_ListCtrl.InsertColumnTrait(nCol, title.c_str(),LVCFMT_LEFT, 20, nCol, pTrait); for(int i=0; i < m_ListCtrl.GetItemCount();++i) m_ListCtrl.SetCellImage(i,nCol, nStateImageIdx); // Uncheck item当使用SetImageList()分配一个CImageList 时,标签栏会自动显示图片列.不能禁用此行为,但可以使用InsertHiddenLabelColumn()隐藏标题栏.
CGridColumnTraitImage 使用单元格图片绘制复选框,因此它不能在同一列同时拥有单元格图片和复选框.可以使用GetCellImage() / SetCellImage()来获取或设置checked/unchecked状态.
CGridColumnTraitImage 支持根据复选框是否选中排序,使用CGridColumnTraitImage::SetSortImageIndex() 启用这个功能.
CGridColumnTraitImage 也支持切换所有选中行的复选框状态.使用CGridColumnTraitImage::SetToggleSelection()启用这个功能.
超链接列可以将单元格文本显示为超链接,单击可以调用外部应用程序例如浏览器(http)或邮箱客户端(mailto)打开超链接.
The CGridColumnTraitHyperLink allows oneto supply a prefix (and suffix) for the celltext, which allows one to add extraprotocol details without it being displayed:
CGridColumnTraitHyperLink 允许我们为单元格文本(celltext)提供一个前缀(和后缀),它允许我们添加额外的协议细节而不显示它.
CGridColumnTraitHyperLink* pHyperLinkTrait = new CGridColumnTraitHyperLink; pHyperLinkTrait->SetShellFilePrefix(_T("http://en.wikipedia.org/wiki/UEFA_Euro_")); m_ListCtrl.InsertColumnTrait(nCol, title.c_str(),LVCFMT_LEFT, 100, nCol, pHyperLinkTrait);也可以使用 CGridColumnTraitHyperLink::SetShellApplication()指定启动一个自定义应用程序,代替仅靠协议前缀启动的默认应用程序.
超链接也可以被用来模拟按键.点击它会发送LVN_ENDLABELEDIT通知,父窗体可以将其当作单击一个按钮处理.
CGridListCtrlEx 使用自定义绘制(customdraw),所以只有如下解决方案可用:
· 指定一个CImageList ,图片高度便是行高.
· 行高会跟随单元格字体改变而改变.CGridListCtrlEx::SetCellMargin()使用这种方法增大单元格字体,但保持整行字体不变.
当CGridListCtrlEx 不包含任何项时,它会显示标记文本以表示该列表为空.
使用CGridListCtrlEx::SetEmptyMarkupText()来更改这个标记文本.如果指定空文本, 它会像一个普通CListCtrl.
If using CGridListCtrlGroups, it willinstead react to LVN_GETEMPTYMARKUP if runningon Windows Vista.
当运行在Vista系统时,如果使用CGridListCtrlGroups,它会对LVN_GETEMPTYMARKUP作出反应.
CViewConfigSectionWinApp 提供了存储列宽,位置的能力, 无论列是否被显示. 在CGridListCtrlEx添加了所有可用列后,使用CGridListCtrlEx::SetupColumnConfig()分配一个CViewConfigSectionWinApp的实例,它将通过CWinApp恢复上次保存的列配置.
m_ListCtrl.SetupColumnConfig(new CViewConfigSectionWinApp("MyList"));如果在应用程序多处使用了CGridListCtrlEx ,那么应该确保在每个地方单独创建一个CViewConfigSectionWinApp.
CGridListCtrlEx 可以同时作为OLE拖动源和OLE放置目标.这允许CGridListCtrlEx 和其他窗体和应用程序之间拖拽操作.
CGridListCtrlEx 支持通过拖拽重新排列行顺序.这通过一种特殊排序方法实现,所以项不会被删除/插入.
要实现你自己的特殊拖拽行为,无论是重载OnDropSelf()还是OnDropExternal(),取决与你要做什么处理.
要控制拖拽时的拖拽源,重载OnDisplayToDragDrop().
CGridListCtrlEx 规避所有令人讨厌的关于如何显示和编辑数据的细节,这些细节由CGridColumnTrait 类处理,如果想要修改数据的现实方式, “只需”创建一个新CGridColumnTrait 类.
当插入一列时,我们可以为其指定一个CGridColumnTrait .当需要绘制或编辑该列中的单元格时,CGridListCtrlEx 将激活相应的CGridColumnTrait.
CGridColumnTrait 包含一些被称为元数据(meta-data)的特殊成员.这些成员能被用于你自己派生自CGridListCtrlEx的类中,这样我们便可很容易的为一个列添加额外属性.
从CGridColumnTrait中继承时,我们需要考虑下列情况:
CGridRowTrait 跟CGridColumnTrait 异曲同工,只不过它操作的是行而不是列.这对于修改所有列的现实行为特别有用.
源码包含下列类:
CGridListCtrlEx 尽量不执行任何自绘(drawing itself).这意味着下列特性/bug不会获得很多关注:
实例化绘制整个单元格的CGridColumnTrait ,可以从ListCtrl - A WTL List Control with Windows Vista Style Item Selection中剽窃/借鉴.
非常欢迎向该项目贡献代码.
Version 1.0 (2008-09-04) First release
Version 1.1 (2008-09-18)
Version 1.2 (2008-09-24)
Version 1.3 (2008-10-09)
Version 1.4 (2008-11-07)
Version 1.5 (2009-03-29)
Version 1.6 (2009-09-13)
Version 1.7 (2009-12-12)
Version 1.8 (2010-10-01)
Version 1.9 (2011-05-30)
Version 2.0 (2012-05-01)
Version 2.1 (2012-06-20)
Version 2.2 (2012-11-11)
这篇文章,以及任何相关的源代码和文件,遵循The Code Project Open License (CPOL)
标签:c++ mfc clistctrl cgridlistctrlex 说明
原文地址:http://blog.csdn.net/ren0065/article/details/42824043