1、目的
简单描述MFC的表格控件使用方法。Qt适用习惯了以后MFC用的比较别扭,因此记录一下以备后续复制代码使用。由于MFC原生的CListCtrl比较局限,比如无法改变表格的背景色、文字颜色等设定,因此先对CListCtrl类进行重写,以便满足要求。
2、CListCtrl类改造
#pragma onceclass 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;
};
// CustomListCtrlIMPLEMENT_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 itemGetColumn(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);
}