如何修改MFC中工具栏的颜色?求可行实现方案
如何修改MFC工具栏的颜色
当然可以修改MFC工具栏的颜色!折腾两天确实闹心,我来给你捋捋靠谱的实现方式——你试过的几个方法其实方向对,但可能细节没做对,咱们一步步来:
首先明确:MFC工具栏本身没有直接设置背景色的原生接口,但通过自定义绘制可以完美实现,下面是最稳定的方案:
方案一:自定义工具栏类+重写绘制方法
这是最推荐的方式,能完全控制工具栏的背景和按钮样式,步骤如下:
- 创建一个继承自
CToolBar的自定义工具栏类(比如命名为CMyToolBar) - 重写
OnEraseBkgnd()、OnPaint()方法,同时处理NM_CUSTOMDRAW消息实现按钮的自定义绘制
具体代码实现
1. 自定义工具栏头文件(MyToolBar.h)
class CMyToolBar : public CToolBar { DECLARE_DYNAMIC(CMyToolBar) public: CMyToolBar(); virtual ~CMyToolBar(); protected: DECLARE_MESSAGE_MAP() afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnPaint(); afx_msg LRESULT OnCustomDraw(WPARAM wParam, LPARAM lParam); };
2. 实现文件(MyToolBar.cpp)
#include "pch.h" #include "MyToolBar.h" IMPLEMENT_DYNAMIC(CMyToolBar, CToolBar) CMyToolBar::CMyToolBar() { } CMyToolBar::~CMyToolBar() { } BEGIN_MESSAGE_MAP(CMyToolBar, CToolBar) ON_WM_ERASEBKGND() ON_WM_PAINT() ON_MESSAGE(NM_CUSTOMDRAW, &CMyToolBar::OnCustomDraw) END_MESSAGE_MAP() // 处理背景擦除,避免闪烁并绘制自定义背景色 BOOL CMyToolBar::OnEraseBkgnd(CDC* pDC) { CRect rect; GetClientRect(rect); // 这里替换成你想要的背景色,示例是浅灰色 pDC->FillSolidRect(rect, RGB(240, 240, 240)); return TRUE; // 返回TRUE表示已自行处理,不需要系统默认擦除 } // 重写OnPaint,确保自定义背景和按钮绘制生效 void CMyToolBar::OnPaint() { CPaintDC dc(this); // 先绘制自定义背景 OnEraseBkgnd(&dc); // 调用默认绘制逻辑保留按钮等元素 CToolBar::OnPaint(); } // 处理自定义绘制,控制按钮的背景/状态颜色 LRESULT CMyToolBar::OnCustomDraw(WPARAM wParam, LPARAM lParam) { NMCUSTOMDRAW* pNMCustomDraw = reinterpret_cast<NMCUSTOMDRAW*>(lParam); if (pNMCustomDraw->dwDrawStage == CDDS_PREPAINT) { return CDRF_NOTIFYITEMDRAW; // 通知系统需要绘制每个按钮项目 } else if (pNMCustomDraw->dwDrawStage == CDDS_ITEMPREPAINT) { CDC* pDC = CDC::FromHandle(pNMCustomDraw->hdc); CRect itemRect(pNMCustomDraw->rc); // 处理按钮选中/悬停状态的颜色 if (pNMCustomDraw->uItemState == CDIS_SELECTED || pNMCustomDraw->uItemState == CDIS_HOT) { pDC->FillSolidRect(itemRect, RGB(200, 220, 255)); return CDRF_SKIPDEFAULT; // 跳过系统默认绘制,用自定义样式 } else { // 普通状态下按钮背景和工具栏保持一致 pDC->FillSolidRect(itemRect, RGB(240, 240, 240)); return CDRF_SKIPDEFAULT; } } return CDRF_DODEFAULT; }
3. 替换主框架中的默认工具栏
打开主框架类(比如CMainFrame)的头文件,把原来的CToolBar m_wndToolBar;替换成CMyToolBar m_wndToolBar;,然后在OnCreate方法中正常创建工具栏即可,不需要修改其他创建代码。
为什么你之前的方法没生效?
OnCtlColor():这个方法只针对编辑框、静态文本这类子控件,工具栏属于顶层窗口类,不会触发这个消息,所以没用。PreparePaint():这是CToolBarCtrl的内部方法,直接重写时机不对,必须配合自定义绘制消息才能生效。GetToolBarCtrl().SetBkColor():这个方法会被Windows系统主题覆盖(尤其是Win7及以上版本),除非你禁用工具栏的主题样式,否则不会生效。
额外小技巧:禁用主题快速设置背景(可选)
如果你不想写太多自定义代码,也可以试试禁用工具栏主题,让SetBkColor()生效,在创建工具栏后添加这段代码:
// 禁用工具栏的系统主题 m_wndToolBar.SetWindowTheme(L"", L""); // 设置背景色 m_wndToolBar.GetToolBarCtrl().SetBkColor(RGB(240,240,240));
不过这种方法会让工具栏样式变得比较朴素,不如自定义绘制灵活,适合快速测试。
内容的提问来源于stack exchange,提问作者user11607830




