Udostępnij przez


Tworzenie podklas dla kontrolek

Jeśli kontrolka wykonuje prawie wszystko, czego potrzebujesz, ale potrzebujesz jeszcze kilku funkcji, możesz zmienić lub dodać funkcje do oryginalnej kontrolki, tworząc podklasę. Podklasa może zawierać wszystkie funkcje istniejącej klasy, a także wszelkie dodatkowe funkcje, które chcesz nadać.

W tym dokumencie omówiono sposób tworzenia podklas i zawiera następujące tematy.

Podklasowanie kontrolek przed wersją ComCtl32.dll 6

Kontrolkę można umieścić w podklasie i przechowywać dane użytkownika w kontrolce. Należy to zrobić, gdy używasz wersji ComCtl32.dll wcześniejszych niż wersja 6. Istnieją pewne wady tworzenia podklas z wcześniejszymi wersjami ComCtl32.dll.

Aby utworzyć nową kontrolkę, najlepiej zacząć od jednej ze wspólnych kontrolek systemu Windows i rozszerzyć ją tak, aby odpowiadała konkretnym potrzebom. Aby rozszerzyć kontrolkę, utwórz kontrolkę i zastąp istniejącą procedurę okna nową. Nowa procedura przechwytuje wiadomości kontrolne i albo działa na nie, albo przekazuje je do oryginalnej procedury w celu przetwarzania domyślnego. Użyj funkcji SetWindowLong lub SetWindowLongPtr, aby zastąpić funkcję WNDPROC kontrolki. Poniższy przykładowy kod pokazuje, jak zastąpić WNDPROC.

OldWndProc = (WNDPROC)SetWindowLongPtr (hButton,
GWLP_WNDPROC, (LONG_PTR)NewWndProc);

Przechowywanie danych użytkownika

Możesz chcieć przechowywać dane użytkownika przy użyciu pojedynczego okna. Te dane mogą być używane przez nową procedurę okna, aby określić sposób rysowania kontrolki lub miejsca wysyłania niektórych komunikatów. Na przykład możesz użyć danych do przechowywania wskaźnika klasy C++ do klasy reprezentującej kontrolkę. Poniższy przykładowy kod pokazuje, jak używać SetProp do przechowywania danych za pomocą okna.

SetProp (hwnd, TEXT("MyData"), (HANDLE)pMyData);

Wady starego podejścia podklasyfikacji

Poniższa lista wskazuje niektóre wady używania wcześniej opisanego podejścia do podklasowania kontrolki.

  • Procedurę okna można zastąpić tylko raz.
  • Usunięcie podklasy po jej utworzeniu jest trudne.
  • Kojarzenie prywatnych danych z oknem jest nieefektywne.
  • Aby wywołać następną procedurę w łańcuchu podklas, nie można przekształcać starej procedury okna i jej wywoływać, musisz ją wywołać, korzystając z funkcji CallWindowProc.

Podklasowanie kontrolek przy użyciu ComCtl32.dll w wersji 6

Notatka

ComCtl32.dll wersja 6 jest wyłącznie Unicode. Typowe kontrolki obsługiwane przez ComCtl32.dll w wersji 6 nie powinny być podklasowane (lub superklasowane) za pomocą procedur okien ANSI.

 

ComCtl32.dll wersja 6 zawiera cztery funkcje, które ułatwiają tworzenie podklas i eliminują wcześniej omówione wady. Nowe funkcje hermetyzują zarządzanie związane z wieloma zestawami danych referencyjnych, dlatego deweloper może skupić się na funkcjach programowania, a nie na zarządzaniu podklasami. Funkcje podklasy to:

SetWindowSubclass

Ta funkcja jest używana do początkowej podklasy okna. Każda podklasa jest unikatowo identyfikowana przez adres pfnSubclass i jej uIdSubclass. Oba są parametrami funkcji SetWindowSubclass. Wiele podklas może współużytkować tę samą procedurę dla podklas, a identyfikator może identyfikować każde wywołanie. Aby zmienić dane referencyjne, możesz wykonywać kolejne wywołania SetWindowSubclass. Ważną zaletą jest to, że każde wystąpienie podklasy ma własne dane referencyjne.

Deklaracja procedury podklasy jest nieco inna niż zwykła procedura okna, ponieważ zawiera dwa dodatkowe elementy danych: identyfikator podklasy i dane referencyjne. Ostatnie dwa parametry następującej deklaracji funkcji pokazują to.

LRESULT CALLBACK MyWndProc (HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass,
DWORD_PTR dwRefData);

Za każdym razem, gdy komunikat jest odbierany przez nową procedurę okna, dołączany jest identyfikator podklasy i dane referencyjne.

Notatka

Wszystkie ciągi przekazywane do procedury są ciągami Unicode, nawet jeśli unicode nie jest określony jako definicja preprocesora.

 

W poniższym przykładzie przedstawiono szkieletową implementację procedury okna dla kontrolki podklasowanej.

LRESULT CALLBACK OwnerDrawButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam,
                               LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    switch (uMsg)
    {
    case WM_PAINT:
        .
        .
        .
        return TRUE;
    // Other cases...
    } 
    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}

Procedura okna może być dołączona do kontrolki w procedurze WM_INITDIALOG okna dialogowego, jak pokazano w poniższym przykładzie.

case WM_INITDIALOG:
{
    HWND button = GetDlgItem(hDlg, IDC_OWNERDRAWBUTTON);
    SetWindowSubclass(button, OwnerDrawButtonProc, 0, 0);
    return TRUE;
}

GetWindowSubclass

Ta funkcja pobiera informacje o podklasie. Na przykład możesz użyć GetWindowSubclass, aby uzyskać dostęp do danych referencyjnych.

RemoveWindowSubclass

Ta funkcja usuwa podklasy. RemoveWindowSubclass w połączeniu z SetWindowSubclass umożliwia dynamiczne dodawanie i usuwanie podklas.

DefSubclassProc

Funkcja DefSubclassProc wywołuje następną procedurę obsługi w łańcuchu podklas. Funkcja pobiera również prawidłowy identyfikator i dane referencyjne oraz przekazuje informacje do następnej procedury okna.