Udostępnij za pośrednictwem


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

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::OnCompareItemi 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 HWNDokna systemu Windows (znanym jako ).

Istnieją trzy typowe sposoby związane z nimi:

  • CWnd tworzy element HWND. Zachowanie klasy pochodnej można zmodyfikować, tworząc klasę pochodzącą z CWndklasy . Element HWND jest tworzony, gdy aplikacja wywołuje element CWnd::Create.

  • Aplikacja dołącza element CWnd do istniejącego HWNDelementu . Zachowanie istniejącego okna nie jest modyfikowane. Jest to przypadek delegowania i jest możliwe przez wywołanie CWnd ::Attach do aliasu istniejącego HWNDCWnd obiektu.

  • CWnd jest dołączony do istniejącego HWND 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 HWNDobiektu . SubclassWindowHWND 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