mfc中设置static text的颜色

本文介绍如何通过WM_CTLCOLOR消息更改MFC应用程序中Static Text控件的背景颜色及字体样式,包括变量定义、消息响应及具体实现步骤。

在实际的应用中,可以用WM_CTLCOLOR 消息改变mfc中控件的颜色,比如现在就来改变一个static text孔家的

背景色和字体

1 在对话框的类中添加两个变量:

CBrush m_brush;
 CFont m_font;

在OnInitDialog()函数中添加:

// TODO: 在此添加额外的初始化代码
 m_font.CreatePointFont(150,"华文行楷");
 m_brush.CreateSolidBrush(RGB(0,255,0));

2 添加WM_CTLCOLOR 消息响应,添加的方法为:

     在对话框类中声明:afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) ;

    在消息映射中添加: ON_WM_CTLCOLOR()

     如:

      BEGIN_MESSAGE_MAP(CtestEnvDlg, CDialog)
 
        ON_WM_CTLCOLOR()
        //}}AFX_MSG_MAP
      END_MESSAGE_MAP()

 

3 添加响应函数:

HBRUSH CYourDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
 HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
 if(m_yourStatic.m_hWnd == pWnd->m_hWnd)
 {
  pDC->SetBkColor(RGB(0,255,0));
  pDC->SelectObject(&m_font);
  return m_brush;
 }
 return hbr;
}

 

这样就可以改变static text的颜色和字体了

<think> 我们正在解决的是:在初始化中默认为GB单位,当复选框被点击时显示MB单位,取消点击时恢复GB单位。 用户提供的代码中,已经有一个复选框点击事件处理函数OnBnClickedCheck1(),但是里面直接写死了m_bShowMB=TRUE,并且重复写了很多更新列表控件的代码。 我们的目标: 1. 初始化时默认以GB显示(即复选框未选中状态) 2. 当复选框被点击时,根据复选框的选中状态切换单位(选中显示MB,未选中显示GB) 修改思路: - 在对话框类中,我们可以用一个成员变量(比如m_bShowMB)来记录当前是否以MB显示。 - 在初始化函数OnInitDialog()中,设置m_bShowMB为FALSE(因为默认是GB),并调用更新函数(或者直接初始化显示GB)。 - 在OnBnClickedCheck1()中,根据复选框的选中状态设置m_bShowMB,然后调用一个公共的更新函数(比如UpdateDiskInfo())来刷新显示。 但是,观察用户提供的代码,里面已经有一个被注释掉的UpdateDiskInfo()函数。我们建议将更新磁盘信息的代码封装到一个单独的函数中,然后在需要的地方调用(比如初始化和复选框点击时)。 然而,用户提供的代码中,OnBnClickedCheck1()函数中已经包含了更新两个列表(Clist2和Clist3)的代码,只是重复写了两份(一份MB,一份GB)。我们可以将其重构为一个更新函数,根据m_bShowMB的值来决定显示的单位。 步骤: 1. 在对话框类中声明一个BOOL类型成员变量m_bShowMB,并在构造函数中初始化为FALSE(默认GB)。 2. 在OnInitDialog()中,除了初始化其他内容,还要根据m_bShowMB的值来初始化显示(调用更新函数)。 3. 重构一个更新函数,比如UpdateDiskInfo(),在这个函数中根据m_bShowMB的值来更新两个列表的显示。 4. 在OnBnClickedCheck1()中,只需要设置m_bShowMB的值(根据复选框状态),然后调用UpdateDiskInfo()。 但是注意,用户提供的代码中,两个磁盘(C盘和D盘)的数据存储在变量dCTotalGB, dCFreeGB, dDTotalGB, dDFreeGB中。这些变量应该是已经获取好的(单位是GB)。所以我们在显示时: - 如果m_bShowMB为TRUE,则乘以1024转换为MB,并显示MB单位。 - 如果m_bShowMB为FALSE,则直接使用原值,显示GB单位。 具体修改如下: 首先,在头文件中声明成员变量和更新函数: BOOL m_bShowMB; // 是否以MB显示 void UpdateDiskInfo(); // 更新磁盘信息显示 然后,在.cpp文件中: 步骤1:在构造函数中初始化m_bShowMB为FALSE。 步骤2:在OnInitDialog()中,在获取了磁盘信息后,调用UpdateDiskInfo()来初始化显示。 步骤3:实现UpdateDiskInfo()函数,将原来OnBnClickedCheck1()中的代码搬进去,并根据m_bShowMB分支。 步骤4:修改OnBnClickedCheck1(),让其根据复选框状态设置m_bShowMB,然后调用UpdateDiskInfo()。 注意:原OnBnClickedCheck1()函数中,对于列表Clist3的操作是插入项目(InsertItem)和设置子项(SetItemText)。但是,在更新时,如果已经插入过,再次插入会导致重复。所以我们需要改变更新方式:要么在更新前删除所有项,要么在初始化时插入一次,更新时只改变文本。这里建议在更新时,先判断列表是否已经有项目,如果有则使用SetItemText,没有则插入。或者每次更新前清空列表再重新插入。 根据用户原有代码,它是在每次切换单位时都重新插入列表项。这样会导致每次切换都增加新项(因为InsertItem会添加新行)。所以我们需要在更新前清空列表。 修改UpdateDiskInfo()函数: 在更新Clist2时,我们使用SetItemText设置已经存在的行(假设在初始化时已经插入了行,并且有两行,分别代表C盘和D盘)。所以Clist2不需要重新插入行,只需要更新第4列和第5列。 对于Clist3,用户原有代码是插入两行(第0行和第1行),然后设置第1列和第2列。这样每次切换都会插入新的行,所以我们需要在更新前先删除所有行。 因此,在UpdateDiskInfo()中,对于Clist3,我们可以先调用DeleteAllItems(),然后重新插入。 具体代码修改如下(基于用户原有代码): 由于用户原有代码较长,我们将其重构到UpdateDiskInfo()中,并添加条件分支。 注意:这里假设用户已经正确初始化了Clist2和Clist3控件,并且Clist2中已经有两行(C盘和D盘)。 修改后的OnBnClickedCheck1()函数: ```cpp void CTxt2Dlg::OnBnClickedCheck1() { // 获取复选框状态 m_bShowMB = ((CButton*)GetDlgItem(IDC_CHECK1))->GetCheck(); // 如果复选框是IDC_CHECK1 // 或者如果已经关联了控件变量(比如m_checkMB),则可以这样: // m_bShowMB = (m_checkMB.GetCheck() == BST_CHECKED); // 调用更新函数 UpdateDiskInfo(); } ``` 然后,我们将原来OnBnClickedCheck1()中的代码搬移到UpdateDiskInfo()中,并修改: ```cpp void CTxt2Dlg::UpdateDiskInfo() { if (m_bShowMB) { // 显示MB单位 // 更新Clist2(C盘和D盘的信息) CString CstrTotalGB, CstrFreeGB; CstrTotalGB.Format(_T("%.2fMB"), dCTotalGB * 1024); CstrFreeGB.Format(_T("%.2fMB"), dCFreeGB * 1024); Clist2.SetItemText(0, 4, CstrTotalGB); Clist2.SetItemText(0, 5, CstrFreeGB); // D盘 CString DstrTotalGB, DstrFreeGB; DstrTotalGB.Format(_T("%.2fMB"), dDTotalGB * 1024); DstrFreeGB.Format(_T("%.2fMB"), dDFreeGB * 1024); Clist2.SetItemText(1, 4, DstrTotalGB); Clist2.SetItemText(1, 5, DstrFreeGB); // 更新Clist3(需要先清空) Clist3.DeleteAllItems(); CString CT, CF, DT, DF; CT.Format(TEXT("总容量%.2fMB"), dCTotalGB * 1024); CF.Format(_T("剩余容量%.2fMB"), dCFreeGB * 1024); DT.Format(_T("总容量%.2fMB"), dDTotalGB * 1024); DF.Format(_T("剩余容量%.2fMB"), dDFreeGB * 1024); Clist3.InsertItem(0, CT); Clist3.InsertItem(1, CF); Clist3.SetItemText(0, 1, DT); Clist3.SetItemText(1, 1, DF); } else { // 显示GB单位 CString CstrTotalGB, CstrFreeGB; CstrTotalGB.Format(_T("%.2fGB"), dCTotalGB); CstrFreeGB.Format(_T("%.2fGB"), dCFreeGB); Clist2.SetItemText(0, 4, CstrTotalGB); Clist2.SetItemText(0, 5, CstrFreeGB); // D盘 CString DstrTotalGB, DstrFreeGB; DstrTotalGB.Format(_T("%.2fGB"), dDTotalGB); DstrFreeGB.Format(_T("%.2fGB"), dDFreeGB); Clist2.SetItemText(1, 4, DstrTotalGB); Clist2.SetItemText(1, 5, DstrFreeGB); // 更新Clist3 Clist3.DeleteAllItems(); CString CT, CF, DT, DF; CT.Format(TEXT("总容量%.2fGB"), dCTotalGB); CF.Format(_T("剩余容量%.2fGB"), dCFreeGB); DT.Format(_T("总容量%.2fGB"), dDTotalGB); DF.Format(_T("剩余容量%.2fGB"), dDFreeGB); Clist3.InsertItem(0, CT); Clist3.InsertItem(1, CF); Clist3.SetItemText(0, 1, DT); Clist3.SetItemText(1, 1, DF); } } ``` 最后,在OnInitDialog()中,在获取了磁盘信息后(即dCTotalGB等变量赋值之后),调用UpdateDiskInfo()进行初始显示。 注意:在OnInitDialog()中,需要确保m_bShowMB是初始值FALSE。 这样,当程序启动时,显示GB单位;点击复选框选中时,显示MB单位;取消复选框时,恢复GB单位。 另外,需要确保在对话框类中声明了UpdateDiskInfo()函数。 补充:在对话框头文件中声明: ```cpp class CTxt2Dlg : public CDialogEx { ... // 其他成员 BOOL m_bShowMB; // 是否以MB显示 void UpdateDiskInfo(); // 更新磁盘信息显示 ... }; ``` 在构造函数中初始化: ```cpp CTxt2Dlg::CTxt2Dlg(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_TXT2_DIALOG, pParent) , m_bShowMB(FALSE) // 初始化为FALSE,即默认GB { // 其他初始化 } ``` 在OnInitDialog()中,在获取磁盘信息后,调用: ```cpp BOOL CTxt2Dlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 获取磁盘信息(假设这里已经获取了dCTotalGB, dCFreeGB, dDTotalGB, dDFreeGB) // 设置复选框初始状态为未选中 ((CButton*)GetDlgItem(IDC_CHECK1))->SetCheck(BST_UNCHECKED); // 更新显示 UpdateDiskInfo(); return TRUE; } ``` 这样修改后,代码结构更清晰,避免重复代码,并且实现了需求。 注意:如果用户界面中还有其他需要更新的控件,也应该在UpdateDiskInfo()中更新。 由于用户原有代码中,在OnBnClickedCheck1()中直接对控件进行操作,我们将其移到了UpdateDiskInfo()中,所以需要确保在UpdateDiskInfo()中访问的控件变量(如Clist2, Clist3)已经正确关联。 如果遇到问题,比如列表控件没有正确更新,请检查: - 在OnInitDialog()中是否已经正确初始化了列表控件(插入行等)? - 在UpdateDiskInfo()中,对于Clist2,我们直接使用SetItemText设置第4列和第5列,因此需要确保在初始化时已经创建了这些行(至少两行)。 如果初始化时没有创建行,则需要在UpdateDiskInfo()中添加插入行的代码(但这样每次更新都会插入新行,所以需要先删除所有行再插入?)。但根据用户原有代码,Clist2应该是已经存在行的(索引0和1),所以我们只是更新。 如果Clist2在初始化时没有插入行,那么需要先插入行。我们建议在OnInitDialog()中插入行(只插入一次),然后在UpdateDiskInfo()中更新这些行的文本。 例如,在OnInitDialog()中: ```cpp // 插入Clist2的行(假设有两行,C盘和D盘) Clist2.InsertItem(0, _T("C:")); // 设置其他列... Clist2.InsertItem(1, _T("D:")); // 然后再调用UpdateDiskInfo()更新数据 ``` 这样,在UpdateDiskInfo()中就可以直接使用SetItemText更新了。 同样的,对于Clist3,我们在UpdateDiskInfo()中每次都会删除所有项然后重新插入,所以不会重复。 以上修改应该能满足需求。 </think> ### MFCStatic Text边框设置方法总结 在MFC设置Static Text控件的边框样式主要有以下几种方法,我将按实现难度从低到高介绍: #### 方法1:通过属性面板直接设置(最简单) ```cpp // 在资源编辑器中操作: 1. 打开对话框资源(.rc文件) 2. 右键选择Static Text控件 → 属性 3. 在"外观"选项卡中设置: - Border: True (添加单线边框) - Client Edge: True (添加3D凹陷边框) - Static Edge: True (添加静态边框) ``` ![Static Text边框属性设置示例](property-border.png)[^1] #### 方法2:动态修改控件样式 ```cpp // 在OnInitDialog()中添加: BOOL CYourDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 获取控件指针 CWnd* pStatic = GetDlgItem(IDC_YOUR_STATIC); // 添加边框样式 pStatic->ModifyStyle(0, WS_BORDER); // 单线边框 // 或者添加3D边框 // pStatic->ModifyStyleEx(0, WS_EX_CLIENTEDGE); return TRUE; } ``` #### 方法3:自定义绘制边框(最灵活) ```cpp // 在对话框类中添加消息处理 BEGIN_MESSAGE_MAP(CYourDlg, CDialogEx) ON_WM_CTLCOLOR() END_MESSAGE_MAP() HBRUSH CYourDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { if (pWnd->GetDlgCtrlID() == IDC_YOUR_STATIC) { // 设置红色边框(示例) pDC->SetBkMode(TRANSPARENT); // 透明背景[^2] pDC->SetTextColor(RGB(255, 0, 0)); // 文字颜色 // 创建边框画笔 CPen pen(PS_SOLID, 2, RGB(255, 0, 0)); CPen* pOldPen = pDC->SelectObject(&pen); // 绘制矩形边框 CRect rect; pWnd->GetWindowRect(&rect); ScreenToClient(&rect); pDC->Rectangle(rect); pDC->SelectObject(pOldPen); return (HBRUSH)::GetStockObject(NULL_BRUSH); } return CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor); } ``` #### 方法4:使用自绘控件(高级) ```cpp // 创建CStatic派生类 class CBorderedStatic : public CStatic { public: DECLARE_MESSAGE_MAP() afx_msg void OnPaint() { CPaintDC dc(this); CRect rect; GetClientRect(&rect); // 绘制自定义边框 dc.SelectStockObject(BLACK_PEN); dc.Rectangle(rect); // 绘制文本 CString strText; GetWindowText(strText); dc.SetBkMode(TRANSPARENT); dc.DrawText(strText, rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); } }; BEGIN_MESSAGE_MAP(CBorderedStatic, CStatic) ON_WM_PAINT() END_MESSAGE_MAP() ``` ### 使用建议: 1. **简单需求** → 使用属性面板直接设置 2. **动态切换** → 使用`ModifyStyle`修改样式 3. **自定义样式** → 使用`OnCtlColor`绘图 4. **复杂边框** → 创建自绘控件 > 注意:如果同时设置背景色和边框,需要处理背景绘制顺序,避免覆盖边框[^3]。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值