3.1 Dětská okna kombo-boxu
Ve třetím díle našeho seriálu o kombíčku použijeme mechanismu subclassing
pro přímý přístup k dětským oknům kombo-boxu. V předchozím díle jsme se
dozvěděli, že těmito dětskými okny jsou edit a list-box. Pokud
měníme chování těchto dětských oken (nejen barvy) ve větší míře, je ideální
mít vlastní třídy, které reprezentují všechny tři části tohoto kombinovaného
prvku (obvykle máme pouze třídu, která představuje celý kombo-box). Tato konstrukce
nám pak dovoluje, jednoduše reagovat na všechny zprávy přicházející všem třem
oknům.
3.2 Příklad
Pomocí ClassWizardu si vygenerujeme tři třídy, které budou reprezentovat
jednotlivá okna. Následující tabulka uvádí jejich výčet a předky.
Jméno třídy |
Předek |
PRO_CustomEdit |
CEdit |
PRO_CustomListBox |
CListBix |
PRO_CustomComboBox |
CComboBox |
Jediným větším problémem, který musíme v našem příkladu
řešit je získání HWND obou zmíněných dětských oken. Pro
vyřešení tohoto problému použijeme zprávy WM_CTLCOLOR, které tato
okna posílají svému rodiči. Při prvním výskytu této zprávy pak provedeme subclassing.
V prvním kroku provedeme subclass rodiče (tzn. vlastního komba).
Vytvoříme dialogovou šablonu (samozřejmě také vygenerujeme odpovídající
dialogovou třídu) a vložíme do ní ovládací prvek uživatelského rozhraní combo-box.
Následně na tento prvek ClassWizardem "namapujeme" členskou
proměnnou, která bude z kategorie Control a její typ bude PRO_CustomComboBox
(tento postup jsme již několikrát opakovali v předchozích dílech).
Ve třídě PRO_CustomComboBox založíme dvě členské
proměnné - instance tříd PRO_CustomEdit a PRO_CustomListBox. Tyto
proměnné budou reprezentovat dětská okna. Následující ukázka zdrojového kódu
znázorňuje stav naší třídy
class PRO_CustomComboBox : public CComboBox
{
// ...
// Attributes
protected:
PRO_CustomEdit m_oEdit;
PRO_CustomListBox m_oListBox;
// ...
}; |
Nyní můžeme ve třídě PRO_CustomComboBox vygenerovat
reakci na zprávu WM_CTLCOLOR, ve které budeme provádět sublassing
dětských oken. Nově implementované tělo metody OnCtlColor můžete vidět na další
ukázce zdrojového kódu.
HBRUSH PRO_CustomComboBox::OnCtlColor( CDC* pDC, CWnd* pWnd,
UINT nCtlColor)
{
HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor);
if (nCtlColor == CTLCOLOR_EDIT)
{
if (m_oEdit.GetSafeHwnd() == NULL)
m_oEdit.SubclassWindow(pWnd->GetSafeHwnd());
}
else if (nCtlColor == CTLCOLOR_LISTBOX)
{
if (m_oListBox.GetSafeHwnd() == NULL)
m_oListBox.SubclassWindow(pWnd->GetSafeHwnd());
}
return hbr;
} |
Pozorný čtenář si jistě uvědomí, že k subclassingu dojde v
době prvního vykreslování dětských oken. V případě list-boxu je to tedy
v okamžiku prvního zobrazení pomocí tlačítka.
Abychom se přesvědčili, že náš mechanismus skutečně funguje
vygenerujeme ve třídách PRO_CustomEdit a PRO_CustomListBox reakci na
zprávu WM_LBUTTONDBLCLK a vyvoláme v reakci na ni textové okno pomocí AfxMessageBox.
Podívejme se zdrojový kódu, který ukazuje obě tyto metody.
void PRO_CustomEdit::OnLButtonDblClk(UINT nFlags, CPoint point)
{
AfxMessageBox("PRO_CustomEdit::OnLButtonDblClk");
CEdit::OnLButtonDblClk(nFlags, point);
} void PRO_CustomListBox::OnLButtonDblClk(UINT nFlags, CPoint point)
{
AfxMessageBox("PRO_CustomListBox::OnLButtonDblClk");
CListBox::OnLButtonDblClk(nFlags, point);
} |
Pokud spustíte naši testovací aplikaci a pokusíte se poklepat na
editační řádek, nebo na seznam, objeví se naše textové okno.
Důležitou vlastností našich tříd, je jejich samostatná
použitelnost. To znamená, že třídy PRO_CustomEdit a PRO_CustomListBox, lze použít
pro vytvoření instancí, které jsou "namapované" na odpovídající prvky
uživatelského rozhraní (tj. edit a list-box).
|