Change color of background and title in MFC Contro

2020-04-23 07:41发布

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 .

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.

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

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.

Pleas help me.

标签: winapi mfc
1条回答
可以哭但决不认输i
2楼-- · 2020-04-23 07:50

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

All you have to do is:

  • For changing background color, you need to create a brush that still exists outside that function and return its HBRUSH with

    return (HBRUSH) m_brush.GetSafeHandle();

    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 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!

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.

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:

  • 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)

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

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

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

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.

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

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")
    }
};

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.

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.

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 :(

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.

查看更多
登录 后发表回答