在 MFC 控件中更改背景和标题的颜色

2022-01-12 00:00:00 winapi mfc

我想在 MFC 应用程序中更改我的 EDIT CONTROL、STATIC CONTROL 和 BUTTON CONTROL 的文本颜色和背景颜色.该控件位于 CDialogEx 对话框中.

I want to change text color and background color for my EDIT CONTROL, STATIC CONTROL and BUTTON CONTROL in MFC application. The control is in a CDialogEx dialogue .

我尝试添加 OnCtlColor(在 Visual Studio 中使用向导,在 WM_CTLCOLR 消息上),但我无法设置可能静态控件和按钮控件的颜色.

I try to add the OnCtlColor (with wizard in visual studio, on the WM_CTLCOLR message) but I can't set the color of may static control and button control.

我还在 OnCtlColor 函数中(在 IF 构造中)设置了一个断点,但我没有收到任何东西.

I put also a break point in the OnCtlColor function (in the IF construct), but I don't receive anything.

我也尝试使用 SetTextColor 函数从 GetDlgItem 检索控件的句柄,但我无法随意更改颜色.

I also tried to use the SetTextColor function retrieving the handle of the control from GetDlgItem, but I can't change the color as I want.

请帮帮我.

推荐答案

我可以断言我尝试在 CDialog 中的 OnCtlColor 中使用它并且它适用于静态和编辑控件.

I can assert that I tried to use in OnCtlColor in a CDialog and it worked for the static and for the edit controls.

你所要做的就是:

  • 要更改背景颜色,您需要创建一个仍然存在于该函数之外的画笔并返回其 HBRUSH with

返回 (HBRUSH) m_brush.GetSafeHandle();

所以你必须创建一个成员变量或静态变量(此代码中的 m_brush)(我推荐第一个),并且在对话框初始化中你必须创建你想要的画笔.

So you have to make a variable (m_brush in this code) that is member or a static (I recommend the first), and in the dialog initialization you have to create the brush you want.

我认为也许某些控件不适用于此功能,对于那些我也使用过的控件

I thought maybe some controls will not work with this, and for those I also did

pDC->SetBkColor(RGB(0,0,255));

但似乎什么也没做;它在代码中是为了安全.

But seems to do nothing; it is in the code for safety.

为了改变文字颜色,我做到了

For changing the text color,I did

pDC->SetTextColor(RGB(255,0,0));

这些体验对于编辑和静态效果很好,但对组合框完全不适用!

These experiences worked well for edits and statics, but did not work at all for groupboxes!

Groupboxes 在 MFC 中是一个奇怪的实体,有点像 platyplus:它们是带有 BS_GROUPBOXCButton,但在这个函数中,它的 nCtlColorCTLCOLOR_STATIC 而不是 CTLCOLOR_BTN!我为他们做了这个

Groupboxes are a strange entity in MFC, some kind of a platyplus: they are a CButton with the BS_GROUPBOX, but in this function, its nCtlColor is CTLCOLOR_STATIC instead of CTLCOLOR_BTN! I did this for them

UINT nStyle = (UINT)(pWnd->GetStyle() & 0x0F);

if(nStyle == BS_GROUPBOX)
{
    return (HBRUSH) m_brush2.GetSafeHandle();
}

绘制的是组框标题后面的小矩形!

and what got painted was the little rectangle behind the groupbox title!

我无法更改组框的文本颜色!

I could not get the text colour of groupboxes changed!

如果您有分组框并且更改其标题的文本颜色非常重要,您可以从 http://www.codeproject.com/Articles/29016/XGroupBox-an-MFC-groupbox-control-to-display-text并获取其基本代码部分:从 CStaticOnPaint()DrawItem() 方法派生而来.不要忘记消息映射上的 ON_WM_PAINT().我不知道 OnEraseBkgnd() 及其 is ON_WM_ERASEBKGND() 消息映射是否如此重要.还需要将它们更改为资源中的静态文本控件,声明一个XGroupBox变量并对其进行DDX_Control.我测试了它,它确实有效.

If you have groupboxes and it is really important to change their titles' text color, you can get the one from http://www.codeproject.com/Articles/29016/XGroupBox-an-MFC-groupbox-control-to-display-text and get its essential code parts: to be derived from CStatic, the OnPaint() and DrawItem() methods. Do not forget also the ON_WM_PAINT() on the message map. I don't know if the OnEraseBkgnd() and its is ON_WM_ERASEBKGND() message mapping are so essential. It is also needed to change them to be Static text controls in the resources, declare a XGroupBox variable and do a DDX_Control of it. I tested it and it really works.

对于按钮,CButtons 不起作用.但是,对于每个按钮,我只是在类中声明了一个 CMFCButton 变量,并对每个按钮执行了一个 DDX_Control.之后,我有两个选择:

For buttons, with CButtons it did not work. But, for each button, I simply declared a CMFCButton variable in the class and did a DDX_Control of each one. After, I had two choices:

  • 在表单构造函数中将其 m_bTransparent 属性设置为 TRUE(在 afxbutton.cpp 文件中搜索此变量以供参考)以获得我想要的那些与表单颜色相同(我还绘制了表单;在我的情况下,我正在应用程序上实现主题)

  • Set its m_bTransparent property to TRUE in the form constructor (search this variable on afxbutton.cpp file for reference) for the ones I wanted to have the same color as the form (I also painted the form; in my case I was implementing themes on an application)

在表单初始化中用SetFaceColor()设置背景颜色,用SetTextColor()设置文本颜色.

Set the Background color with SetFaceColor() and set the Text Color with SetTextColor() in form initialization.

CMFCButton 没有设置这些东西时,它的颜色来自当前选择的 CMFCVisualManager 的主题混合.

When the CMFCButton does not have these things set, it got its color from theme blending of the currently selected CMFCVisualManager.

注意:我还将 CSpinButton 实体替换为 CMFCSpinButon 实体,因为我想要所选主题的颜色.

Note: I also replaced my CSpinButton entities with CMFCSpinButon ones, because I wanted colors from the selected theme.

OnCtlColor 中,nCtlColor 变量很重要,因为它允许您将不同的颜色个性化为不同的类型,而无需测试 dynamic_cast 是否成功或每个控件都失败.

In the OnCtlColor, the nCtlColor variable is important because it will allow you to personalize different colors to different types, without testing dynamic_cast success or failure for every control.

不要忘记将 ON_WM_CTLCOLOR() 添加到您的消息映射中.

Do not forget to add ON_WM_CTLCOLOR() to your message map.

更新 1:在遵循 http://social.msdn.microsoft.com/Forums/vstudio/en-US/53f47162-078a-418f-8067-ee61a81ceeac/checkbox-transparent-color-not-working-in-vs2008?forum=vcgeneral ,我做了自己的 Groupbox 类,现在是这样的:

UPDATE 1: After following the advice of the accepted answer on http://social.msdn.microsoft.com/Forums/vstudio/en-US/53f47162-078a-418f-8067-ee61a81ceeac/checkbox-transparent-color-not-working-in-vs2008?forum=vcgeneral , I did my own Groupbox class, and now it is like:

class CMyGroupBox: public CButton
{
protected:
    virtual void PreSubclassWindow()
    {
        SetWindowTheme(*this, _T(""), _T(""));
        #pragma comment(lib, "UxTheme.lib")
    }
};

我刚刚声明了其中一个,并使用其各自的控件 ID 执行了 DDX_Control,现在我可以看到我提供给 SetTextColor 的颜色的文本.如果您为此控件返回 HBRUSH,则绘制的是围绕组框标题绘制的未填充矩形.

I just declared one of this, and did DDX_Control with its respective control ID, and now I can see the text in the color I supplied to SetTextColor. If you return a HBRUSH for this control, what gets painted is a non-filled rectangle drawn around the groupbox's title.

更新 2: 我只是将 CMyGroupBox 概括为 CMyButton,因为使用它的 PreSubClassWindow 方法不仅在组框中,但也在复选框和按钮中.在复选框中效果很好,在按钮中,我对结果不太满意.

UPDATE 2: I just generalized the CMyGroupBox to be CMyButton, for using its PreSubClassWindow method not only in groupboxes, but also in checkboxes and buttons. In checkboxes it works well, in buttons, I am not so satisfied with the results.

更新 3: 我试图消除对文本呈现的一些奇怪影响,我只是评论了 pDC->SetBkColor(RGB(0,0,255));行;结果是文本后面的一个丑陋的矩形:(.然后我用 pDC->SetBkMode(TRANSPARENT); 替换它,我也看到了奇怪的效果:(

UPDATE 3: I was trying to remove some weird effect on the rendering of the text and I just commented the pDC->SetBkColor(RGB(0,0,255)); line; the result was an ugly while rectangle behind the text :( . Then I replaced it with pDC->SetBkMode(TRANSPARENT); and I also see tht weird effect :(

更新 4: 为了避免必须将我所有的复选框、组框和按钮声明为包含 PreSubClassWindow 方法的类,我研究并发现不需要这样做.代码

UPDATE 4: In order to avoid to have to declare all my checkboxes, groupboxes and buttons as the class that contains the PreSubClassWindow method, I researched and discovered that it is not needed to do it. The code

SetThemeAppProperties(0);
#pragma comment(lib, "UxTheme.lib")
AfxGetMainWnd()->SendMessage(WM_THEMECHANGED, 0U, 0L);

在整个应用程序级别禁用所有控件的主题化.

disables theming for all controls at the whole application level.

相关文章