TN014: formanty niestandardowe
W tej notatce opisano obsługę MFC dla kontrolek niestandardowych i samorysowania. Opisuje również dynamiczne podklasy i opisuje relację między obiektami CWnd i HWND
s.
Przykładowa aplikacja MFC CTRLTEST ilustruje sposób używania wielu kontrolek niestandardowych. Zobacz kod źródłowy przykładu MFC General CTRLTEST i pomocy online.
Kontrolki/menu Właściciela rysuj
System Windows zapewnia obsługę kontrolek i menu rysowania właściciela przy użyciu komunikatów systemu Windows. Okno nadrzędne dowolnej kontrolki lub menu odbiera te komunikaty i wywołuje funkcje w odpowiedzi. Możesz zastąpić te funkcje, aby dostosować wygląd i zachowanie kontrolki lub menu rysowania właściciela.
Usługa MFC bezpośrednio obsługuje rysowanie właściciela przy użyciu następujących funkcji:
Te funkcje można zastąpić w klasie pochodnej, CWnd
aby zaimplementować niestandardowe zachowanie rysowania.
Takie podejście nie prowadzi do wielokrotnego użycia kodu. Jeśli masz dwie podobne kontrolki w dwóch różnych CWnd
klasach, musisz zaimplementować zachowanie niestandardowej kontrolki w dwóch lokalizacjach. Architektura sterowania samorysowania obsługiwana przez MFC rozwiązuje ten problem.
Kontrolki i menu samorysuj
MFC udostępnia domyślną implementację (w CWnd
klasach i CMenu ) dla standardowych komunikatów rysowania właściciela. Ta domyślna implementacja spowoduje dekodowanie parametrów rysowania właściciela i delegowanie komunikatów rysowania właściciela do kontrolek lub menu. Jest to nazywane rysowaniem własnym, ponieważ kod rysunku znajduje się w klasie kontrolki lub menu, a nie w oknie właściciela.
Za pomocą kontrolek samodzielnie rysujących można tworzyć klasy kontrolek wielokrotnego użytku, które używają semantyki rysowania właściciela do wyświetlania kontrolki. Kod do rysowania kontrolki znajduje się w klasie formantu, a nie w jej obiekcie nadrzędnym. Jest to podejście obiektowe do niestandardowego programowania kontrolek. Dodaj następującą listę funkcji do klas samodzielnego rysowania:
W przypadku przycisków samodzielnego rysowania:
CButton:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw this button
W przypadku menu samodzielnego rysowania:
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
W przypadku pól listy z własnym rysowaniem:
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
W przypadku pól kombi z własnym rysowaniem:
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
Szczegółowe informacje na temat struktur rysowania właściciela (DRAWITEMSTRUCT, MEASUREITEMSTRUCT, COMPAREITEMSTRUCT i DELETEITEMSTRUCT) można znaleźć w dokumentacji MFC dla CWnd::OnDrawItem
, CWnd::OnMeasureItem
, CWnd::OnCompareItem
i CWnd::OnDeleteItem
odpowiednio.
Korzystanie z kontrolek i menu samodzielnego rysowania
W przypadku menu samodzielnego rysowania należy zastąpić metody OnMeasureItem
i .OnDrawItem
W przypadku pól listy samodzielnej rysowania i pól kombi należy zastąpić OnMeasureItem
wartości i OnDrawItem
. Należy określić styl LBS_OWNERDRAWVARIABLE pól listy lub styl CBS_OWNERDRAWVARIABLE dla pól kombi w szablonie okna dialogowego. Styl OWNERDRAWFIXED nie będzie działać z elementami samorysowania, ponieważ stała wysokość elementu jest określana przed dołączeniu kontrolek samorysowania do pola listy. (Można użyć metod CListBox::SetItemHeight i CComboBox::SetItemHeight , aby przezwyciężyć to ograniczenie).
Przełączenie do stylu OWNERDRAWVARIABLE spowoduje, że system zastosuje styl NOINTEGRALHEIGHT do kontrolki. Ponieważ kontrolka nie może obliczyć całkowitej wysokości ze zmiennymi rozmiarami elementów, domyślny styl INTEGRALHEIGHT jest ignorowany, a kontrolka jest zawsze NOINTEGRALHEIGHT. Jeśli elementy są stałej wysokości, możesz uniemożliwić rysowanie częściowych elementów, określając rozmiar kontrolki jako mnożnik liczby całkowitej rozmiaru elementu.
W przypadku pól listy samodzielnej i pól kombi z stylem LBS_SORT lub CBS_SORT należy zastąpić metodę OnCompareItem
.
W przypadku pól listy samorysowania i pól OnDeleteItem
kombi nie jest zwykle zastępowane. Możesz zastąpić OnDeleteItem
, jeśli chcesz wykonać dowolne specjalne przetwarzanie. Jednym z przypadków, w których ma to zastosowanie, jest to, że dodatkowa pamięć lub inne zasoby są przechowywane w każdym polu listy lub elemencie pola kombi.
Przykłady kontrolek i menu samodzielnego rysowania
Przykładowy przykład MFC General CTRLTEST zawiera przykłady menu samodzielnego rysowania i pola listy samorysowania.
Najbardziej typowym przykładem przycisku samodzielnego rysowania jest przycisk mapy bitowej. Przycisk mapy bitowej to przycisk przedstawiający jeden, dwa lub trzy obrazy mapy bitowej dla różnych stanów. Przykład jest podany w klasie MFC CBitmapButton.
Dynamiczne podklasy
Czasami warto zmienić funkcjonalność obiektu, który już istnieje. Poprzednie przykłady wymagały dostosowania kontrolek przed ich utworzeniem. Dynamiczne podklasy umożliwiają dostosowanie kontrolki, która została już utworzona.
Podklasa to termin systemu Windows zastępujący WndProc okno dostosowanym WndProc
i wywołując stary WndProc
dla funkcji domyślnych.
Nie należy tego mylić z wyprowadzeniem klas języka C++. Aby wyjaśnić, terminy C++ klasy bazowej i klasy pochodnej są analogiczne do superklasy i podklasy w modelu obiektów systemu Windows. Wyprowadzanie języka C++ z podklasami MFC i Windows jest funkcjonalnie podobne, z wyjątkiem języka C++ nie obsługuje dynamicznej podklasy.
Klasa CWnd
zapewnia połączenie między obiektem C++ (pochodzącym z CWnd
) i obiektem HWND
okna systemu Windows (znanym jako ).
Istnieją trzy typowe sposoby związane z nimi:
CWnd
tworzy elementHWND
. Zachowanie klasy pochodnej można zmodyfikować, tworząc klasę pochodzącą zCWnd
klasy . ElementHWND
jest tworzony, gdy aplikacja wywołuje element CWnd::Create.Aplikacja dołącza element
CWnd
do istniejącegoHWND
elementu . Zachowanie istniejącego okna nie jest modyfikowane. Jest to przypadek delegowania i jest możliwe przez wywołanie CWnd ::Attach do aliasu istniejącegoHWND
CWnd
obiektu.CWnd
jest dołączony do istniejącegoHWND
elementu i można zmodyfikować zachowanie w klasie pochodnej. Jest to nazywane podklasą dynamiczną, ponieważ zmieniamy zachowanie, a zatem klasę obiektu systemu Windows w czasie wykonywania.
Dynamiczne podklasy można osiągnąć przy użyciu metod CWnd::SubclassWindow iCWnd::SubclassDlgItem.
Obie procedury dołączają CWnd
obiekt do istniejącego HWND
obiektu . SubclassWindow
HWND
pobiera bezpośrednio. SubclassDlgItem
to funkcja pomocnika, która przyjmuje identyfikator kontrolki i okno nadrzędne. SubclassDlgItem
jest przeznaczony do dołączania obiektów języka C++ do kontrolek okien dialogowych utworzonych na podstawie szablonu okna dialogowego.
Zobacz przykład CTRLTEST, aby zapoznać się z kilkoma SubclassWindow
przykładami użycia i SubclassDlgItem
.
Zobacz też
Uwagi techniczne według numerów
Uwagi techniczne według kategorii