最近的项目中须要用到 MFC 的列表控件,列表控件中须要动态插入产品不一样的测试状态,产品的不一样状态下的测试结果分为 PASS 和 FAIL 两种状况,这两种测试结果插入的状态字符串颜色分别呈现为绿色和红色。而且双击状态 Item,绘制出对应状态下的测试结果曲线。web
ListBox 没法直接设置字体颜色,所以须要本身实现对字体重绘功能。建立一个继承 ListBox 的类
CColorListBox,重写ListBox 中如下虚函数svg
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
以及重载函数函数
int AddString(LPCTSTR lpszItem, COLORREF itemColor);
实现以下:post
void CColorListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // Losing focus ? if (lpDrawItemStruct->itemID == -1) { DrawFocusRect(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem); return; } CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); COLORREF clrOld; CString sText; // get color info from item data COLORREF clrNew = (COLORREF)(lpDrawItemStruct->itemData); // item selected ? if ((lpDrawItemStruct->itemState & ODS_SELECTED) && (lpDrawItemStruct->itemAction & (ODA_SELECT | ODA_DRAWENTIRE))) { CBrush brush(::GetSysColor(COLOR_HIGHLIGHT)); pDC->FillRect(&lpDrawItemStruct->rcItem, &brush); } // item deselected ? if (!(lpDrawItemStruct->itemState & ODS_SELECTED) && (lpDrawItemStruct->itemAction & ODA_SELECT)) { CBrush brush(::GetSysColor(COLOR_WINDOW)); pDC->FillRect(&lpDrawItemStruct->rcItem, &brush); } // item has focus ? if ((lpDrawItemStruct->itemAction & ODA_FOCUS) && (lpDrawItemStruct->itemState & ODS_FOCUS)) { pDC->DrawFocusRect(&lpDrawItemStruct->rcItem); } // lost focus ? if ((lpDrawItemStruct->itemAction & ODA_FOCUS) && !(lpDrawItemStruct->itemState & ODS_FOCUS)) { pDC->DrawFocusRect(&lpDrawItemStruct->rcItem); } // set the background mode to TRANSPARENT int nBkMode = pDC->SetBkMode(TRANSPARENT); if (lpDrawItemStruct->itemState & ODS_SELECTED) clrOld = pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT)); else if (lpDrawItemStruct->itemState & ODS_DISABLED) clrOld = pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT)); else clrOld = pDC->SetTextColor(clrNew); // get item text GetText(lpDrawItemStruct->itemID, sText); CRect rect = lpDrawItemStruct->rcItem; // text format UINT nFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER; if (GetStyle() & LBS_USETABSTOPS) nFormat |= DT_EXPANDTABS; // draw the text pDC->DrawText(sText, -1, &rect, nFormat); // restore old values pDC->SetTextColor(clrOld); pDC->SetBkMode(nBkMode); }
void CColorListBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) { lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_CYMENUCHECK); }
int CColorListBox::AddString(LPCTSTR lpszItem, COLORREF itemColor) { // Add the string to the list box int nIndex = CListBox::AddString(lpszItem); // save color data if (nIndex >= 0) SetItemData(nIndex, itemColor); return nIndex; }
右击工程进入类向导,选择自定义的 CColorListBox 类,添加 WM_LBUTTONDBLCLK 消息响应函数。进入响应函数便可添加相应的响应代码。测试
void CColorListBox::OnLButtonDblClk(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 int nIndex = GetCurSel();//双击了哪一个 Item int nCount = GetCount();//获得总共的 Item 数 if (nIndex >= 0 && nIndex < nCount) { //回调函数,具体实现取决于给它注册的类 m_dbClick(m_result[nIndex - 1]); } CListBox::OnLButtonDblClk(nFlags, point); }
本项目采用回调的方式,即在建立列表时,给 CColorListBox 类注册一个双击事件的回调函数,如此能够在其余类中响应这一双击事件。固然,也能够在捕获到双击事件后,将消息post到指定窗口进行响应。字体
回调函数原型:this
//回调函数:双击列表中的姿态,图表进行响应切换,参数为自定义的测试结果结构体 typedef void(CALLBACK DBCLICKBOXCALLBACK) (ANTRes res); typedef DBCLICKBOXCALLBACK FAR *LPDBCLICKBOXCALLBACK;
回调函数注册spa
//m_dbClick为 LPDBCLICKBOXCALLBACK 类型的成员,参数为具体实现的函数指针,在建立列表时调用该函数进行回调注册 void CColorListBox::setDbClickFunc(LPDBCLICKBOXCALLBACK DbClick) { m_dbClick = DbClick; }
#include <vector> using namespace std; //回调函数:双击列表中的姿态,图标进行响应切换,能够设置参数 typedef void(CALLBACK DBCLICKBOXCALLBACK) (); typedef DBCLICKBOXCALLBACK FAR *LPDBCLICKBOXCALLBACK; class CColorListBox : public CListBox { public: CColorListBox(); virtual ~CColorListBox(); virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct); //重载 int AddString(LPCTSTR lpszItem, COLORREF itemColor); DECLARE_MESSAGE_MAP() afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); public: void setDbClickFunc(LPDBCLICKBOXCALLBACK DbClick); LPDBCLICKBOXCALLBACK m_dbClick;//双击回调函数 };
#include "CColorListBox.h" CColorListBox::CColorListBox() { } CColorListBox::~CColorListBox() { } BEGIN_MESSAGE_MAP(CColorListBox, CListBox) ON_WM_LBUTTONDBLCLK() END_MESSAGE_MAP() void CColorListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // Losing focus ? if (lpDrawItemStruct->itemID == -1) { DrawFocusRect(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem); return; } CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); COLORREF clrOld; CString sText; // get color info from item data COLORREF clrNew = (COLORREF)(lpDrawItemStruct->itemData); // item selected ? if ((lpDrawItemStruct->itemState & ODS_SELECTED) && (lpDrawItemStruct->itemAction & (ODA_SELECT | ODA_DRAWENTIRE))) { CBrush brush(::GetSysColor(COLOR_HIGHLIGHT)); pDC->FillRect(&lpDrawItemStruct->rcItem, &brush); } // item deselected ? if (!(lpDrawItemStruct->itemState & ODS_SELECTED) && (lpDrawItemStruct->itemAction & ODA_SELECT)) { CBrush brush(::GetSysColor(COLOR_WINDOW)); pDC->FillRect(&lpDrawItemStruct->rcItem, &brush); } // item has focus ? if ((lpDrawItemStruct->itemAction & ODA_FOCUS) && (lpDrawItemStruct->itemState & ODS_FOCUS)) { pDC->DrawFocusRect(&lpDrawItemStruct->rcItem); } // lost focus ? if ((lpDrawItemStruct->itemAction & ODA_FOCUS) && !(lpDrawItemStruct->itemState & ODS_FOCUS)) { pDC->DrawFocusRect(&lpDrawItemStruct->rcItem); } // set the background mode to TRANSPARENT int nBkMode = pDC->SetBkMode(TRANSPARENT); if (lpDrawItemStruct->itemState & ODS_SELECTED) clrOld = pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT)); else if (lpDrawItemStruct->itemState & ODS_DISABLED) clrOld = pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT)); else clrOld = pDC->SetTextColor(clrNew); // get item text GetText(lpDrawItemStruct->itemID, sText); CRect rect = lpDrawItemStruct->rcItem; // text format UINT nFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER; if (GetStyle() & LBS_USETABSTOPS) nFormat |= DT_EXPANDTABS; // draw the text pDC->DrawText(sText, -1, &rect, nFormat); // restore old values pDC->SetTextColor(clrOld); pDC->SetBkMode(nBkMode); } void CColorListBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) { lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_CYMENUCHECK); } int CColorListBox::AddString(LPCTSTR lpszItem, COLORREF itemColor) { // Add the string to the list box int nIndex = CListBox::AddString(lpszItem); // save color data if (nIndex >= 0) SetItemData(nIndex, itemColor); return nIndex; } void CColorListBox::OnLButtonDblClk(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 int nIndex = GetCurSel(); int nCount = GetCount(); if (nIndex >= 0 && nIndex < nCount) { m_dbClick(); } CListBox::OnLButtonDblClk(nFlags, point); } void CColorListBox::setDbClickFunc(LPDBCLICKBOXCALLBACK DbClick) { m_dbClick = DbClick; }
//回调函数具体实现,必须和回调声明类型一致 static void WINAPI OnDbClickListItem() { //此处实现双击事件具体须要作的事,如刷新图表 } //建立一个 CColorListBox 类指针,注意不用时释放 CColorListBox *listBox = new CColorListBox(); listBox->Create(LBS_HASSTRINGS | LBS_OWNERDRAWFIXED | WS_HSCROLL | LBS_NOTIFY | WS_CHILD | WS_VISIBLE | WS_TABSTOP, CRect(0, 0, 60, 60), this, IDC_LISTBOX + iAnt); //为列表注册双击回调函数 listBox->setDbClickFunc(OnDbClickListItem); //插入字符串,第二个参数为可选的颜色 listBox->AddString("所有姿态", RGB(255, 0, 0));//红色
界面在显示测试结果时,常常采用 Static 控件,有时候须要让结果看起来很醒目,这时也须要设置控件的背景颜色以达到醒目效果。那么顺便简单说一下 Static 控件的背景颜色与字体的设置,效果以下:
指针
HBRUSH CDlgControl::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor); // TODO: 在此更改 DC 的任何特性 int n = pWnd->GetDlgCtrlID(); if (n == IDC_STATIC_RESULT_TOTAL) { pDC->SetBkColor(RGB(255, 0, 0)); pDC->SetTextColor(RGB(0, 0, 0)); hbr = CreateSolidBrush(RGB(255, 0, 0)); } else if (n == IDC_STATIC_TIME) { pDC->SetTextColor(RGB(0, 0, 0)); //设置字体颜色 pDC->SetBkMode(TRANSPARENT); //设置字体背景为透明 hbr = CreateSolidBrush(RGB(255, 255, 0));//控件背景色 } // TODO: 若是默认的不是所需画笔,则返回另外一个画笔 return hbr; }
设置 Static 控件字体与字号rest
CFont m_font; m_font.CreatePointFont(580, _T("宋体")); GetDlgItem(IDC_STATIC_RESULT_TOTAL)->SetFont(&m_font);