1.2 Změna barev
Častým požadavkem je změna barev ovládacích prvků (pozadí, text, ...). Pro
vyřešení tohoto problému máme dvě možnosti. Barvu může nastavovat rodič
ovládacího prvku (nejčastěji dialog), nebo ovládací prvek sám. Druhá možnost je
vhodná tam, kde chceme vytvořit speciální prvek uživatelského rozhraní a nechceme
opakovat kód změny barvy v každém použitém dialogu. Na následujícím příkladě
je demonstrována první varianta.
2.2 Ať se snaží rodič
V dialogu, jež obsahuje daný ovládací prvek musíme reagovat na zprávu WM_CTLCOLOR,
kterou svému rodiči zasílají všechny ovládací prvky. Pomocí této zprávy dává
prvek svému rodiči k dispozici svůj obrazový kontext (device context), který
tak může měnit jeho atributy - např. barvy. Hlavička metody, která bude obsluhovat
tuto zprávu je následující.
HBRUSH OnCtlColor( CDC* pDC, CWnd* pWnd,
UINT nCtlColor );
|
pDC
Ukazatel na obrazový kontext dětského okna.
pWnd Ukazatel na okno,
které zasílá zprávu (jež se dotazuje na barvu).
nCtlColor Typ dětského okna.
Návratovou hodnotou této metody je štětec, který se použije pro
vyplnění pozadí okna. Pozorného čtenáře jistě napadne, že změnou tohoto štětce
lze měnit barvu pozadí dialogu..
V následující tabulce si ještě uveďme, jakých hodnot může
poslední parametr - nCtlColor nabývat.
CTLCOLOR_BTN
CTLCOLOR_DLG
CTLCOLOR_EDIT
CTLCOLOR_LISTBOX
CTLCOLOR_MSGBOX
CTLCOLOR_SCROLLBAR
CTLCOLOR_STATIC |
Button control
Dialog box
Edit control
List-box ontrol
Message box
Scroll-bar control
Static control |
Pokud tedy budeme chtít změnit barvu textu ve všech editačních
řádcích, včetně editačních řádků kombo-boxů, bude implementace této metody
následující.
HBRUSH CColorComboDlg::OnCtlColor(CDC* pDC, CWnd* pWnd,
UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd,
nCtlColor);
switch (nCtlColor)
{
case CTLCOLOR_EDIT:
pDC->SetTextColor(RGB(255, 0, 0));
break;
}
return hbr;
}
|

3.2 Já sám
Pokud nechceme měnit barvu u všech ovládacích prvků stejného typu, nebo potřebujeme
vytvořit takový prvek, který si bude barvy měnit sám (nemusíme pak opakovat kód v
dialogu, kde je použitý) použijeme druhý způsob, který souvisí s mechanismem Message
Reflection.
Ve Windows obvykle zasílají dětská okna svým rodičům
notifikační zprávy. Od verze MFC 4.0 je však implementován speciální mechanismus message
reflection, který umožňuje zpracovat tuto zprávu přímo v dětském okně.
Ukažme si použití tohoto mechanismu nejdříve na změně barev v editačním řádku.
3.2.1 Příklad změny barev v editačním řádku
Pomocí ClassWizardu si vygenerujeme třídu PRO_ColorEdit, která bude
reprezentovat náš obarvený editační řádek. Tato třída bude dědit ze třídy CEdit.
Ve třídě založíme dvě členské proměnné, které budou definovat barvu textu (m_clrText)
a barvu pozadí (m_brBkgnd), typ těchto proměnných je vidět na
následující částečné ukázce zdrojového kódu.
class PRO_ColorEdit : public CEdit
{
// ...
// Attributes
public:
COLORREF m_clrText;
CBrush m_brBkgnd;
// ...
};
|
V konstruktoru naší třídy obě proměnné inicializujeme...
PRO_ColorEdit::PRO_ColorEdit()
{
m_clrText = RGB(0, 255, 0);
m_brBkgnd.CreateSolidBrush(RGB(0, 255, 255));
}
|
Opět pomocí ClassWizardu vygenerujeme reakci na
notifikační (odraženou) zprávu =WM_CTLCOLOR. Pozor neplést se
zprávou WM_CTLCOLOR, která je zasílána rodiči! V této metodě pak
můžeme jednoduchým způsobem nastavit atributy obrazového kontextu editačního
řádku. Podívejme se opět na následující ukázku.
HBRUSH PRO_ColorEdit::CtlColor(CDC* pDC, UINT nCtlColor)
{
pDC->SetTextColor(m_clrText);
pDC->SetBkMode(TRANSPARENT);
return m_brBkgnd;
}
|
Do připravené dialogové šablony vložíme kombo-box a pomocí ClassWizardu
(opět) na tento ovládací prvek "namapujeme" členskou proměnnou m_oComboBox.
Tato proměnná bude náležet do kategorie Control a její typ bude PRO_ColorEdit.
3.2.1 Příklad změny barev v combo-boxu
Nyní si ukážeme změnu barev v kombíčku. Zde je situace poněkud složitější,
protože kombo (combo-box) je prvek složený s editačního řádku (edit)
a seznamu (list-box). Musíme tedy tuto architekturu brát v úvahu. Podobně
jako v předchozí kapitole vygenerujeme třídu PRO_ColorComboBox, která bude
reprezentovat obarvené kombíčko. Tato třída bude opět obsahovat dvě členské
proměnné, které definují barvy a jsou inicializované v konstruktoru.
Vygenerujeme reakci na zprávu WM_CTLCOLOR (ne
notifikaci). Pozor, zde nevyužíváme mechanismu message reflection,
protože kombo-box (jako rodič) obdrží tuto standardní zprávu od svých dětských
oken - editačního řádku a list-boxu. Obarvený tedy bude jak list-box, tak i
editační řádek kombo-boxu.
Následující kód ukazuje implementaci naší metody.
HBRUSH PRO_ColorComboBox::OnCtlColor( CDC* pDC,
CWnd* pWnd, UINT nCtlColor )
{
HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd,
nCtlColor);
switch (nCtlColor)
{
case CTLCOLOR_EDIT:
case CTLCOLOR_LISTBOX:
pDC->SetTextColor(m_clrText);
pDC->SetBkMode(TRANSPARENT);
break;
}
return m_brBkgnd;
}
|
Do připravené dialogové šablony můžeme nyní vložit ovládací
prvek kombo a "namapovat" proměnnou např. m_oColorCombo, která naleží do
kategorie Control a je typu PRO_ColorComboBox. Naše barevné kombo má
však v tuti chvíli ještě jeden drobný nedostatek. Pokud spustíte testovací aplikaci
uvidíte následující detail.

Vnitřní okraj kombíčka zůstal neobarvený (bílý). To je
způsobeno tím, že editační řádek nezabírá celou vnitřní plochu komba a část
je viditelná (okraj). Musíme, nyní již s použitím mechanismu message reflection
obarvit ještě pozadí kombo-boxu. Princip je stejný jako v předchozí kapitole, takže
vygenerujeme reakci na notifikační zprávu =WM_CTLCOLOR. Implementace
této metody bude následující.
HBRUSH PRO_ColorComboBox::CtlColor(CDC* pDC,
UINT nCtlColor)
{
return m_brBkgnd;
}
|
Nyní je již všechno jak má být.

|