MFC是一种用c++设计交互界面的的开发工具,在二三十年前比较流行,但目前比较少用了。所以现在使用MFC进行开发,相关资料的查找也比较困难。最近做了一个与MFC有关的项目,其中用到的相关知识总结于此。在使用工具时,最好的资料其实就是那个库本身,查看库内的代码总会有意想不到的收获。本人用的是VS2017专业版里面的MFC。本章主要是复现老外使用CGridListCtrlEx绘制表格。老外的链接如下:
CGridListCtrlEx,文末附老外和个人代码地址。
上面网址上有两个下载地址,里面的例子都是可以用的,这里只展示一个例子,运行界面,有图表,日期,checkbox还有超链接。
如果能够连接维基百科,点击超链接是可以打开的
表格还可以进行排序,拖动等操作。
新建项目的过程请参照总结一,现在项目已经创建好了
首先将cgridlistctrlex_demo里面的CGridListCtrlEx文件夹全体复制到创建的.sln目录中
将CListCtrl_DataModel.h复制到.h和.cpp的那个目录下。
在项目的属性页中将CGridListCtrlEx文件里面的文件和CListCtrl_DataModel.h部添加到项目中
将原文夹res中的国旗图标复制到现在的res中
在资源视图的Icon添加这些资源,选中Icon,选择导入,可以更具需求更不更改名称都行
从工具箱中拖入List Control
查看器属性页,一定要将View选项选成Report,个人因为这个原因复现好久都一直报错。
之后得到的界面就变成下面这个样子了
在GridlistDlg.h中添加头文件
#include "afxcmn.h"
#include "..\CGridListCtrlEx\CGridListCtrlGroups.h"
#include "CListCtrl_DataModel.h"
添加定义
private:
CGridListCtrlGroups m_ListCtrl;
CListCtrl_DataModel m_DataModel;
CImageList m_ImageList;
CGridlistDlg(const CGridlistDlg&);
CGridlistDlg& operator=(const CGridlistDlg&);
在GridlistDlg.cpp中添加头文件
#include "..\CGridListCtrlEx\CGridColumnTraitDateTime.h"
#include "..\CGridListCtrlEx\CGridColumnTraitEdit.h"
#include "..\CGridListCtrlEx\CGridColumnTraitCombo.h"
#include "..\CGridListCtrlEx\CGridColumnTraitHyperLink.h"
#include "..\CGridListCtrlEx\CGridRowTraitXP.h"
#include "..\CGridListCtrlEx\ViewConfigSection.h"
在void CGridlistDlg::DoDataExchange(CDataExchange* pDX)添加绑定
void CGridlistDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST1, m_ListCtrl);
}
在BOOL CGridlistDlg::OnInitDialog()添加代码区添加片段
// Create and attach image list
m_ImageList.Create(16, 16, ILC_COLOR16 | ILC_MASK, 1, 0);
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON1));
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON2));
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON3));
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON4));
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON5));
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON6));
int nStateImageIdx = CGridColumnTraitDateTime::AppendStateImages(m_ListCtrl, m_ImageList); // Add checkboxes
m_ListCtrl.SetImageList(&m_ImageList, LVSIL_SMALL);
// Give better margin to editors
m_ListCtrl.SetCellMargin(1.2);
CGridRowTraitXP* pRowTrait = new CGridRowTraitXP;
m_ListCtrl.SetDefaultRowTrait(pRowTrait);
m_ListCtrl.EnableVisualStyles(true);
// Create Columns
m_ListCtrl.InsertHiddenLabelColumn(); // Requires one never uses column 0
for (int col = 0; col < m_DataModel.GetColCount(); ++col)
{
const CString& title = m_DataModel.GetColTitle(col);
CGridColumnTrait* pTrait = NULL;
if (col == 0) // Country
{
CGridColumnTraitCombo* pComboTrait = new CGridColumnTraitCombo;
const vector& countries = m_DataModel.GetCountries();
for (size_t i = 0; i < countries.size(); ++i)
pComboTrait->AddItem((DWORD_PTR)i, countries[i]);
pTrait = pComboTrait;
}
if (col == 1) // City
{
pTrait = new CGridColumnTraitEdit;
}
if (col == 2) // Year won
{
CGridColumnTraitDateTime* pDateTimeTrait = new CGridColumnTraitDateTime;
pDateTimeTrait->AddImageIndex(nStateImageIdx, _T(""), false); // Unchecked (and not editable)
pDateTimeTrait->AddImageIndex(nStateImageIdx + 1, COleDateTime(1970, 1, 1, 0, 0, 0).Format(), true); // Checked (and editable)
pDateTimeTrait->SetToggleSelection(true);
pTrait = pDateTimeTrait;
}
if (col == 3) // Year won
{
CGridColumnTraitHyperLink* pHyperLinkTrait = new CGridColumnTraitHyperLink;
pHyperLinkTrait->SetShellFilePrefix(_T("http://en.wikipedia.org/wiki/UEFA_Euro_"));
pTrait = pHyperLinkTrait;
}
m_ListCtrl.InsertColumnTrait(col + 1, title, LVCFMT_LEFT, 100, col, pTrait);
}
// Insert data into list-control by copying from datamodel
int nItem = 0;
for (size_t rowId = 0; rowId < m_DataModel.GetRowIds(); ++rowId)
{
nItem = m_ListCtrl.InsertItem(++nItem, m_DataModel.GetCellText(rowId, 0));
m_ListCtrl.SetItemData(nItem, rowId);
for (int col = 0; col < m_DataModel.GetColCount(); ++col)
{
int nCellCol = col + 1; // +1 because of hidden column
const CString& strCellText = m_DataModel.GetCellText(rowId, col);
m_ListCtrl.SetItemText(nItem, nCellCol, strCellText);
if (nCellCol == 3)
{
if (strCellText == _T(""))
m_ListCtrl.SetCellImage(nItem, nCellCol, nStateImageIdx); // unchecked
else
m_ListCtrl.SetCellImage(nItem, nCellCol, nStateImageIdx + 1); // checked
}
}
m_ListCtrl.SetCellImage(nItem, 1, nItem); // Assign flag-images
}
CViewConfigSectionWinApp* pColumnProfile = new CViewConfigSectionWinApp(_T("Sample List"));
pColumnProfile->AddProfile(_T("Default"));
pColumnProfile->AddProfile(_T("Special"));
m_ListCtrl.SetupColumnConfig(pColumnProfile);
之前要是有比较认真的小伙伴把那个ICON的名字该成和原代码一样的,请用如下代码替换对应部分
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_FLGDEN));
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_FLGGERM));
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_FLGFRAN));
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_FLGGREEC));
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_FLGSWED));
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_FLGSPAIN));
至此,整个项目好像都复制过来了,试着运行一下应该没问题,结果发现好多错。
还有最后一个很重要的地方就是预编译器(stdafx.h)里面还需要引入头文件。这种使用预编译器的项目,这个也是一个大坑,至于要在其中加入下面几行代码就没错了
#include
#include
#include
using namespace std;
各种功能基本都实现了,但还是有一个小遗憾,表格中上下之间不能拖动交换顺序,而原代码中是可以的,个人找了好久,未果,但没有寻病终(哈哈哈!),在此,寻好心人求解。
老外代码链接.
个人代码链接.