TheLostJedi Ответов: 1

Как изменить цвет фона флажка в MFC?


Я разрабатываю графический интерфейс, который использует флажок. Мне нужно, чтобы цвет chechbox, то есть область, где появляется черная галочка, менялся, когда флажок установлен.

Что я уже пробовал:

Я читал о различных подходах в интернете, которые предлагают использовать WM_CTLCOLOR сообщение и использование OnCtlColor функция, но это меняет цвет сразу же после инициализации. Поэтому я попытался изменить цвет, когда флажок установлен следующим образом:

void CMyAppDlg::OnBnClickedCheckTxpow()
{
	if (m_chkTxPow.GetState() == 9)
	{
		CDC *pDC;
		CWnd *pWnd;

		//pWnd->SetDlgCtrlID(IDC_CHECK_TXPOW);
		pDC = m_chkTxPow.GetDC();
		pDC->SetBkColor(RGB(0,255,0));
	}	
}


m_chkTxPow это управляющая переменная, назначенная флажку. Я пытался подражать OnCtlColor функции доступны онлайн как можно ближе. Но это не работает.
Кроме того, я не думаю, что изменение цвета фона влияет на цвет внутри коробки. Кто-нибудь может мне помочь?

1 Ответов

Рейтинг:
11

Jochen Arndt

Нет простого способа изменить цвет фона флажков. Причина в том, что флажки MFC-это системные элементы управления, которые не предоставляют возможности изменить цвет фона для области стрелок, и эта область не является прозрачной.

Единственный вариант сделать это-получить CButton класс, использующий чертеж владельца. Там вы можете нарисовать непроверенный флажок, используя системные функции. Для галочек заполните затем фон и нарисуйте стрелку вручную.

Это можно сделать для классических флажков с помощью CDC::DrawFrameControl, заполняя фон с CDC::FillSolidRect (использовать InflateRect(-2, -2) с помощью флажка размер) и рисование стрелки.

Но в настоящее время приложения не используют классический стиль. Тогда вы должны использовать DrawThemeBackground, заполните фон с помощью CDC::GradientFill, и нарисуйте стрелку затененной тоже. Но это будет выглядеть не совсем так, как нарисованные системой флажки.

// Draw default sized check box.
// Classic        Themed
//
// LLLLLLLLLLLLW  BBBBBBBBBBBBB
// LGGGGGGGGGGSW  B           B
// LG         SW  B           B
// LG       K SW  B        G  B
// LG      KK SW  B       GG  B
// LG K   KKK SW  B  G	 GGG  B
// LG KK KKK  SW  B  GG GGG   B
// LG KKKKK   SW  B  GGGGG    B
// LG  KKK    SW  B   GGG     B
// LG   K     SW  B    G      B
// LSSSSSSSSSSSW  B           B
// WWWWWWWWWWWWW  BBBBBBBBBBBBB
// 
// L = light gray, G = dark gray, S =very light gray, B/K = black, W = white
//
// rcBox:  Rect containing the check box
// clrBk:  Background colour
// clrArr: Colour for arrow (COLOR_BTNSHADOW if disabled; else COLOR_WINDOWTEXT)

// save bk color; is changed by drawing functions
int nBkClr = pDC->GetBkColor(); 

#if 1
// Add aditional states (inactive, pushed) as required
pDC->DrawFrameControl(rcBox, DFC_BUTTON, DFCS_BUTTONCHECK);
#else
// Themed (set nThemedState accordingly):
DrawThemeBackground(m_hTheme, 
    lpDrawItemStruct->hDC, 
    BP_CHECKBOX, nThemedState, 
    &rcBox, NULL);
#endif

CRect rcBk(rcBox);
// Use -3 when themed and CBS_UNCHECKEDHOT
rcBk.InflateRect(-2, -2);
#if 1
pDC->FillSolidRect(&rcBk, clrBk);
#else
// Themed:
// Two triangles: upper left and lower right
static GRADIENT_TRIANGLE TriG[2] = { { 0, 1, 3 }, { 0, 3, 2} };
#define GetR(rgb)   ((int)((rgb) & 0xFF)) // extract R/G/B values fro COLORREF
#define GetG(rgb)   ((int)(((rgb) >> 8) & 0xFF))
#define GetB(rgb)   ((int)(((rgb) >> 16) & 0xFF))
#define Darken(a)   ((a) - ((a) >> 1)) // make R/G/B part darker
#define Brighten(a) ((a) + ((0xFF - (a)) >> 1))	// make R/G/B part brighter
#define Col16(c)    ((COLOR16)((c) << 8)) // convert R/G/B part to COLOR16 value
#define Bright16(a) (Col16(Brighten(a)))
TRIVERTEX TriV[4] = {
{rc.left, rc.top, Col16(GetR(clr)), Col16(GetG(clr)), Col16(GetB(clr)), 0},
{rc.right, rc.top, Bright16(GetR(clr)), Bright16(GetG(clr)), Bright16(GetB(clr)), 0},
{rc.left, rc.bottom, Bright16(GetR(clr)), Bright16(GetG(clr)), Bright16(GetB(clr)), 0},
{rc.right, rc.bottom, 0xff00, 0xff00, 0xff00, 0}
};
pDC->GradientFill(TriV, 4, TriG, 2, GRADIENT_FILL_TRIANGLE);
#endif

// Themed: clrArr = RGB(76, 97, 152); // not shaded!
CRect rcArr(rcBox.left + 3, // left start position
    rcBox.top + 5, // top start position
    rcBox.left + 4, // width 1 pixel
    rcBox.top + 8); // height 3 pixels
for (int i = 0; i < 7; i++) 
{
    pDC->FillSolidRect(&rcArr, clrArr);
    rcArr.OffsetRect(1, (i < 2) ? 1 : -1);
}

pDC->SetBkColor(nBkClr); // restore bk color


TheLostJedi

Спасибо!! Эта стратегия работает!! Я никогда не думал, что мне придется тратить столько времени на чекбокс. Есть идеи, почему Microsoft не допускает более тонкого контроля над своими элементами управления, такими как (например) Qt?

Jochen Arndt

Спасибо вам за ваши отзывы и принятие моего решения.

Классические элементы управления Windows были созданы давным-давно, и текущие версии Windows должны быть совместимы со старыми интерфейсами.

Они могли бы сделать это лучше с тематическими версиями, но только MS знала бы, почему они этого не сделали. Возможно, есть лучшее решение, но я его не знаю (существует не так много документации о тематических элементах управления).

TheLostJedi

Учитывая невыгодное положение, в котором мы находимся, это лучшее возможное решение. Так что спасибо!