TN014: Vlastní ovládací prvky
Tato poznámka popisuje podporu MFC pro vlastní a samokreslené ovládací prvky. Popisuje také dynamické podtřídy a popisuje vztah mezi objekty CWnd a HWND
s.
Ukázková aplikace MFC CTRLTEST ukazuje, jak používat mnoho vlastních ovládacích prvků. Podívejte se na zdrojový kód obecné ukázky CTRLTEST a online nápovědy KNIHOVNY MFC.
Ovládací prvky/nabídky pro kreslení vlastníkem
Systém Windows poskytuje podporu ovládacích prvků a nabídek pro kreslení vlastníka pomocí zpráv systému Windows. Nadřazené okno libovolného ovládacího prvku nebo nabídky přijímá tyto zprávy a volá funkce v reakci. Tyto funkce můžete přepsat, abyste přizpůsobili vizuální vzhled a chování ovládacího prvku nebo nabídky pro kreslení vlastníka.
MFC přímo podporuje kreslení vlastníkem s následujícími funkcemi:
Tyto funkce v CWnd
odvozené třídě můžete přepsat, abyste implementovali vlastní chování kreslení.
Tento přístup neznamená opakovaně použitelný kód. Pokud máte dva podobné ovládací prvky ve dvou různých CWnd
třídách, musíte implementovat chování vlastního ovládacího prvku ve dvou umístěních. Tento problém řeší architektura ovládacích prvků podporovaných knihovnou MFC.
Ovládací prvky a nabídky pro samokreslení
MFC poskytuje výchozí implementaci (ve CWnd
třídách A CMenu ) pro standardní zprávy o kreslení vlastníkem. Tato výchozí implementace dekóduje parametry owner-draw a deleguje zprávy o kreslení vlastníka do ovládacích prvků nebo nabídky. To se nazývá samokreslení, protože kód výkresu je ve třídě ovládacího prvku nebo nabídky, ne v okně vlastníka.
Pomocí ovládacích prvků samokreslení můžete vytvářet opakovaně použitelné třídy ovládacích prvků, které používají sémantiku owner-draw k zobrazení ovládacího prvku. Kód pro kreslení ovládacího prvku je ve třídě ovládacího prvku, nikoli jeho nadřazený. Jedná se o objektově orientovaný přístup k programování vlastních ovládacích prvků. Přidejte následující seznam funkcí do tříd samokreslení:
Tlačítka pro samokreslení:
CButton:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw this button
Pro samoobslužné nabídky:
CMenu:MeasureItem(LPMEASUREITEMSTRUCT); // insert code to measure the size of an item in this menu CMenu:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw an item in this menu
Pro samokreslení seznamů:
CListBox:MeasureItem(LPMEASUREITEMSTRUCT); // insert code to measure the size of an item in this list box CListBox:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw an item in this list box CListBox:CompareItem(LPCOMPAREITEMSTRUCT); // insert code to compare two items in this list box if LBS_SORT CListBox:DeleteItem(LPDELETEITEMSTRUCT); // insert code to delete an item from this list box
Pro pole se seznamem pro samokreslení:
CComboBox:MeasureItem(LPMEASUREITEMSTRUCT); // insert code to measure the size of an item in this combo box CComboBox:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw an item in this combo box CComboBox:CompareItem(LPCOMPAREITEMSTRUCT); // insert code to compare two items in this combo box if CBS_SORT CComboBox:DeleteItem(LPDELETEITEMSTRUCT); // insert code to delete an item from this combo box
Podrobnosti o strukturách owner-draw (DRAWITEMSTRUCT, MEASUREITEMSTRUCT, COMPAREITEMSTRUCT a DELETEITEMSTRUCT) naleznete v dokumentaci MFC pro CWnd::OnDrawItem
, CWnd::OnCompareItem
CWnd::OnMeasureItem
, a CWnd::OnDeleteItem
v uvedeném pořadí.
Použití ovládacích prvků a nabídek pro samokreslení
U nabídek pro samokreslení je nutné přepsat obě OnMeasureItem
metody i OnDrawItem
metody.
V případě samokreslených seznamů a polí se seznamem je nutné přepsat OnMeasureItem
a OnDrawItem
. U polí se seznamem v šabloně dialogového okna je nutné zadat styl LBS_OWNERDRAWVARIABLE nebo styl CBS_OWNERDRAWVARIABLE. Styl OWNERDRAWFIXED nebude fungovat s položkami vlastního kreslení, protože pevná výška položky je určena před ovládacími prvky samokreslení jsou připojeny k seznamu. (Můžete použít metody .CListBox::SetItemHeight a CComboBox::SetItemHeight k vyřešení tohoto omezení.)
Přepnutí do stylu OWNERDRAWVARIABLE vynutí, aby systém na ovládací prvek použil styl NOINTEGRALHEIGHT. Vzhledem k tomu, že ovládací prvek nemůže vypočítat celočíselnou výšku s položkami s proměnlivou velikostí, je výchozí styl INTEGRALHEIGHT ignorován a ovládací prvek je vždy NOINTEGRALHEIGHT. Pokud jsou položky pevné výšky, můžete zabránit v vykreslení částečných položek zadáním velikosti ovládacího prvku na celočíselné násobení velikosti položky.
U polí se seznamem a polí se seznamem se seznamem se stylem LBS_SORT nebo CBS_SORT je nutné tuto metodu OnCompareItem
přepsat.
U samokreslených seznamů a polí OnDeleteItem
se seznamem se obvykle nepřepíše. Pokud chcete provést jakékoli speciální zpracování, můžete je přepsat OnDeleteItem
. Jedním z případů, kdy by to bylo možné použít, je, když jsou s každým seznamem nebo položkou pole se seznamem uloženy další prostředky nebo další prostředky.
Příklady ovládacích prvků a nabídek samokreslení
Ukázka OBECNÉ KNIHOVNY MFC CTRLTEST obsahuje ukázky nabídky pro vlastní kreslení a seznam se samokreslením.
Nejběžnějším příkladem tlačítka samokreslení je rastrové tlačítko. Rastrové tlačítko je tlačítko, které zobrazuje jeden, dva nebo tři rastrové obrázky pro různé stavy. Příklad je k dispozici ve třídě MFC CBitmapButton.
Dynamické podtřídy
Někdy budete chtít změnit funkčnost objektu, který již existuje. Předchozí příklady vyžadovaly přizpůsobení ovládacích prvků před jejich vytvořením. Dynamické podtřídy umožňují přizpůsobit ovládací prvek, který už byl vytvořen.
Podtřídy jsou termínem Windows pro nahrazení WndProc okna přizpůsobeným WndProc
a voláním starého WndProc
pro výchozí funkce.
Nemělo by se zaměňovat s odvozením třídy jazyka C++. Pro objasnění jsou termíny C++ základní třídy a odvozené třídy podobné supertřídě a podtřídě v objektovém modelu Windows. Odvození C++ pomocí mfc a podtřídy Windows jsou funkčně podobné, s výjimkou jazyka C++ nepodporuje dynamické podtřídy.
Třída CWnd
poskytuje propojení mezi objektem jazyka C++ (odvozeným zCWnd
) a objektem okna Systému Windows (označovaným jako ).HWND
Existují tři běžné způsoby, jak souvisí:
CWnd
vytvoří .HWND
Chování v odvozené třídě můžete upravit vytvořením třídy odvozené zCWnd
. Vytvoří seHWND
při volání aplikace CWnd::Create.Aplikace připojí existující
CWnd
.HWND
Chování existujícího okna se nezmění. Jedná se o případ delegování, který je možný voláním CWnd::Attach aliasu existujícíhoHWND
objektuCWnd
.CWnd
je připojen k existujícíHWND
a můžete upravit chování v odvozené třídě. To se nazývá dynamické podtřídy, protože měníme chování, a proto třídu objektu Windows za běhu.
Dynamické podtřídy můžete dosáhnout pomocí metod CWnd::SubclassWindow aCWnd::SubclassDlgItem.
Obě rutiny připojují CWnd
objekt k existujícímu HWND
objektu . SubclassWindow
HWND
vezme přímo. SubclassDlgItem
je pomocná funkce, která přebírá ID ovládacího prvku a nadřazené okno. SubclassDlgItem
je určen pro připojení objektů C++ k dialogovým ovládacím prvkům vytvořeným ze šablony dialogového okna.
Podívejte se na příklad CTRLTEST pro několik příkladů, kdy použít SubclassWindow
a SubclassDlgItem
.
Viz také
Technické poznámky podle čísel
Technické poznámky podle kategorií