Sdílet prostřednictvím


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 HWNDs.

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::OnCompareItemCWnd::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í:

  • CWndvytvoří .HWND Chování v odvozené třídě můžete upravit vytvořením třídy odvozené z CWnd. Vytvoří se HWND 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ího HWND objektu CWnd .

  • 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 HWNDobjektu . SubclassWindowHWND 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í