1、目的
简单描述MFC的表格控件使用方法。Qt适用习惯了以后MFC用的比较别扭,因此记录一下以备后续复制代码使用。由于MFC原生的CListCtrl比较局限,比如无法改变表格的背景色、文字颜色等设定,因此先对CListCtrl类进行重写,以便满足要求。
2、CListCtrl类改造
#pragma once
class CustomListCtrl : public CListCtrl
{
DECLARE_DYNAMIC(CustomListCtrl)
public:
CustomListCtrl();
virtual ~CustomListCtrl();
protected:
DECLARE_MESSAGE_MAP()
virtual void PreSubclassWindow();
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
public:
afx_msg void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct);
void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
public:
CPtrList m_ptrListCol; //保存列颜色
CPtrList m_ptrListItem; //保存Item颜色表
CPtrList m_colTextColor; //保存列字体颜色
CPtrList m_ItemTextColor; //保存单元格字体颜色
bool FindColColor(int col, COLORREF& color); //查找列颜色
bool FindItemColor(int col, int row, COLORREF& color);
void SetColColor(int col, COLORREF color); //设置列颜色
void SetItemColor(int col, int row, COLORREF color); //设置Item颜色
void SetColTextColor(int col, COLORREF color); //设置列文本颜色
void SetItemTextColor(int col, int row, COLORREF color);
COLORREF m_color;
BOOL SetTextColor(COLORREF cr);
public:
// 字体高度
int m_fontHeight;
// 字体宽度
int m_fontWith;
};
#include "pch.h"
#include "CustomListCtrl.h"
// CustomListCtrl.cpp : 实现文件
//
struct stColor
{
int nRow;
int nCol;
COLORREF rgb;
};
// CustomListCtrl
IMPLEMENT_DYNAMIC(CustomListCtrl, CListCtrl)
CustomListCtrl::CustomListCtrl()
:m_fontHeight(12)
,m_fontWith(0)
{
m_color = RGB(0, 0, 0);
}
CustomListCtrl::~CustomListCtrl()
{
}
BEGIN_MESSAGE_MAP(CustomListCtrl, CListCtrl)
ON_WM_MEASUREITEM()
ON_WM_MEASUREITEM_REFLECT()
END_MESSAGE_MAP()
// CustomListCtrl 消息处理程序
void CustomListCtrl::PreSubclassWindow()
{
// TODO: 在此添加专用代码和/或调用基类
ModifyStyle(0, LVS_OWNERDRAWFIXED);
CListCtrl::PreSubclassWindow();
}
void CustomListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: 添加您的代码以绘制指定项
TCHAR lpBuffer[256];
LV_ITEM lvi;
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.iItem = lpDrawItemStruct->itemID;
lvi.iSubItem = 0;
lvi.pszText = lpBuffer;
lvi.cchTextMax = sizeof(lpBuffer);
VERIFY(GetItem(&lvi));
LV_COLUMN lvc, lvcprev;
::ZeroMemory(&lvc, sizeof(lvc));
::ZeroMemory(&lvcprev, sizeof(lvcprev));
lvc.mask = LVCF_WIDTH | LVCF_FMT;
lvcprev.mask = LVCF_WIDTH | LVCF_FMT;
CDC* pDC;
pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
CRect rtClient;
GetClientRect(&rtClient);
for (int nCol = 0; GetColumn(nCol, &lvc); nCol++)
{
if (nCol > 0)
{
// Get Previous Column Width in order to move the next display item
GetColumn(nCol - 1, &lvcprev);
lpDrawItemStruct->rcItem.left += lvcprev.cx;
lpDrawItemStruct->rcItem.right += lpDrawItemStruct->rcItem.left;
}
CRect rcItem;
if (!GetSubItemRect(lpDrawItemStruct->itemID, nCol, LVIR_LABEL, rcItem))
continue;
::ZeroMemory(&lvi, sizeof(lvi));
lvi.iItem = lpDrawItemStruct->itemID;
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.iSubItem = nCol;
lvi.pszText = lpBuffer;
lvi.cchTextMax = sizeof(lpBuffer);
VERIFY(GetItem(&lvi));
CRect rcTemp;
rcTemp = rcItem;
if (nCol == 0)
{
rcTemp.left -= 2;
}
if (lpDrawItemStruct->itemState & ODS_SELECTED)
{
pDC->FillSolidRect(&rcTemp, GetSysColor(COLOR_HIGHLIGHT));
pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
}
else
{
COLORREF color;
color = GetBkColor();
pDC->FillSolidRect(rcTemp, color);
if (FindColColor(nCol, color))
{
pDC->FillSolidRect(rcTemp, color);
}
if (FindItemColor(nCol, lpDrawItemStruct->itemID, color))
{
pDC->FillSolidRect(rcTemp, color);
}
}
pDC->SelectObject(GetStockObject(DEFAULT_GUI_FONT));
UINT uFormat = DT_CENTER;
TEXTMETRIC metric;
pDC->GetTextMetrics(&metric);
int ofst;
ofst = rcItem.Height() - metric.tmHeight;
rcItem.OffsetRect(0, ofst / 2);
pDC->SetTextColor(m_color);
CFont nFont, * nOldFont;
nFont.CreateFont(m_fontHeight, m_fontWith, 0, 0, 0, FALSE, FALSE, 0, 0, 0, 0, 0, 0, _TEXT("宋体"));//创建字体
nOldFont = pDC->SelectObject(&nFont);
DrawText(lpDrawItemStruct->hDC, lpBuffer, strlen(lpBuffer), &rcItem, uFormat);
pDC->SelectStockObject(SYSTEM_FONT);
}
}
void CustomListCtrl::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CListCtrl::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
}
void CustomListCtrl::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
}
bool CustomListCtrl::FindColColor(int col, COLORREF& color) //查找列颜色
{
int flag = 0;
for (POSITION pos = m_ptrListCol.GetHeadPosition(); pos != NULL;)
{
stColor* pColor = (stColor*)m_ptrListCol.GetNext(pos);
if (pColor->nCol == col)
{
flag = 1;
color = pColor->rgb;
break;
}
}
if (1 == flag)
{
return true;
}
return false;
}
bool CustomListCtrl::FindItemColor(int col, int row, COLORREF& color) //查找颜色
{
int flag = 0;
for (POSITION pos = m_ptrListItem.GetHeadPosition(); pos != NULL;)
{
stColor* pColor = (stColor*)m_ptrListItem.GetNext(pos);
if (pColor->nCol == col && pColor->nRow == row)
{
flag = 1;
color = pColor->rgb;
break;
}
}
if (1 == flag)
{
return true;
}
return false;
}
void CustomListCtrl::SetColColor(int col, COLORREF color) //设置列颜色
{
stColor* pColor = new stColor;
pColor->nCol = col;
pColor->rgb = color;
m_ptrListCol.AddTail(pColor);
}
void CustomListCtrl::SetItemColor(int col, int row, COLORREF color) //设置格子颜色
{
stColor* pColor = new stColor;
pColor->nCol = col;
pColor->nRow = row;
pColor->rgb = color;
m_ptrListItem.AddTail(pColor);
}
BOOL CustomListCtrl::SetTextColor(COLORREF cr) //设置字体颜色
{
m_color = cr;
return TRUE;
}
void CustomListCtrl::SetColTextColor(int col, COLORREF color)
{
stColor* pColor = new stColor;
pColor->nCol = col;
pColor->rgb = color;
m_colTextColor.AddTail(pColor);
}
void CustomListCtrl::SetItemTextColor(int col, int row, COLORREF color)
{
stColor* pColor = new stColor;
pColor->nCol = col;
pColor->nRow = row;
pColor->rgb = color;
m_ItemTextColor.AddTail(pColor);
}
3、表格初始化
初始化表格界面效果
// 初始化表格界面
CustomListCtrl m_listInput;
void CTestDlg::OnInitInputCtrl()
{
CRect rect;
m_listInput.GetClientRect(&rect);
int nWidth = rect.Width() - 15;
m_listInput.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP | LVS_EX_SUBITEMIMAGES | LVS_EX_FULLROWSELECT);
m_listInput.InsertColumn(0, _T("分支号"), LVCFMT_CENTER, nWidth * 0.08);
m_listInput.InsertColumn(1, _T("名称"), LVCFMT_CENTER, nWidth * 0.1);
m_listInput.InsertColumn(2, _T("始节点"), LVCFMT_CENTER, nWidth * 0.08);
m_listInput.InsertColumn(3, _T("终节点"), LVCFMT_CENTER, nWidth * 0.08);
m_listInput.InsertColumn(4, _T("需风类型"), LVCFMT_CENTER, nWidth * 0.1);
m_listInput.InsertColumn(5, _T("风阻R"), LVCFMT_CENTER, nWidth * 0.1);
m_listInput.InsertColumn(6, _T("风阻△R"), LVCFMT_CENTER, nWidth * 0.1);
m_listInput.InsertColumn(7, _T("需风量Q(m3/s)"), LVCFMT_CENTER, nWidth * 0.15);
m_listInput.InsertColumn(8, _T("风量△Q"), LVCFMT_CENTER, nWidth * 0.14);
m_listInput.InsertColumn(9, _T("调节性"), LVCFMT_CENTER, nWidth * 0.1);
}
4、表格插入内容
// 表格插入内容
void CTestDlg::setInputData()
{
m_listInput.DeleteAllItems();
std::sort(m_vecInit.begin(), m_vecInit.end());
for (int i = 0; i < m_vecInit.size(); ++i)
{
stu_GraphParams& windResult = m_vecInit[i];
CString sTmp;
// 分支号
sTmp.Format("%d", windResult.nNumber);
m_listInput.InsertItem(i, sTmp);
// 名称
m_listInput.SetItemText(i, 1, windResult.sName);
// 始节点
sTmp.Format("%d", windResult.nStartJunction);
m_listInput.SetItemText(i, 2, sTmp);
// 终节点
sTmp.Format("%d", windResult.nEndJunction);
m_listInput.SetItemText(i, 3, sTmp);
// 需风类型
m_listInput.SetItemText(i, 4, _T("自然"));
// 风阻
CString strResistance;
strResistance.Format("%.6f", windResult.dResistance);
m_listInput.SetItemText(i, 5, strResistance);
// △风阻
CString strResistanceEx;
strResistanceEx.Format("%.6f", windResult.dResistanceEx);
m_listInput.SetItemText(i, 6, strResistanceEx);
// 数值改变的话修改单元格颜色
bool bChange = (strResistanceEx.CompareNoCase(strResistance) != 0) ? true : false;
if(windResult.dResistanceEx > 0.000001f && bChange)
{
COLORREF cf = RGB(255, 0, 0);
m_listInput.SetItemColor(6,i,cf);
}
// 需风量
sTmp.Format("%.3f", windResult.dFlowRate);
m_listInput.SetItemText(i, 7, sTmp);
// 风量
sTmp.Format("%.3f", windResult.dFlowRateEx);
m_listInput.SetItemText(i, 8, sTmp);
// 调节性
bool bAdjust = windResult.bAdjust;
if (bAdjust)
{
m_listInput.SetItemText(i, 9, _T("是"));
}
else
{
m_listInput.SetItemText(i, 9, _T("否"));
}
}
}
5、双击获取表格选中行的内容
// 双击事件
void CTestDlg::OnNMDblclkInputList(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
*pResult = 0;
// TODO: 在此添加控件通知处理程序代码
int nIndex = m_listInput.GetNextItem(-1, LVIS_SELECTED);
POSITION ps = m_listInput.GetFirstSelectedItemPosition();
if (NULL == ps)
{
return;
}
int nItem = m_listInput.GetNextSelectedItem(ps);
stu_WindEdgeInfo windEdgeInfo;
windEdgeInfo.sEdgeId = m_listInput.GetItemText(nItem, 0);
windEdgeInfo.sName = m_listInput.GetItemText(nItem, 1);
windEdgeInfo.sStartIndex = m_listInput.GetItemText(nItem, 2);
}