Informacje dotyczące procedur obsługi okien
Każde okno jest elementem członkowskim określonej klasy okna. Klasa okna określa domyślną procedurę okna używaną przez poszczególne okna do przetwarzania komunikatów. Wszystkie okna należące do tej samej klasy używają tej samej domyślnej procedury okna. Na przykład system definiuje procedurę okna dla klasy pola kombi (COMBOBOX); wszystkie pola kombi następnie używają tej procedury okna.
Aplikacja zazwyczaj rejestruje co najmniej jedną nową klasę okien i skojarzona z nią procedurę okna. Po zarejestrowaniu klasy aplikacja może utworzyć wiele okien tej klasy, z których wszystkie korzystają z tej samej procedury okna. Ponieważ oznacza to, że kilka źródeł może jednocześnie wywoływać ten sam fragment kodu, należy zachować ostrożność podczas modyfikowania udostępnionych zasobów z procedury okna. Aby uzyskać więcej informacji, zobacz Klasy okien .
Procedury okien dla okien dialogowych (nazywane procedurami okna dialogowego) mają podobną strukturę i działają jak zwykłe procedury okien. Wszystkie punkty odwołujące się do procedur okien w tej sekcji mają również zastosowanie do procedur okna dialogowego. Aby uzyskać więcej informacji, zobacz okna dialogowe .
W tej sekcji omówiono następujące tematy.
- Struktura procedury okna
- domyślna procedura okna
-
Podklasowanie (tworzenie podklasy) procedury okna
- Subclassowanie wystąpień
- Globalne podklasowanie
- pl-PL: Superklasowanie procedury okna
Struktura procedury okna
Procedura okna to funkcja, która ma cztery parametry i zwraca wartość ze znakiem. Parametry obejmują uchwyt okna, identyfikator komunikatu UINT oraz dwa parametry komunikatów zadeklarowane za pomocą typów danych WPARAM i LPARAM. Aby uzyskać więcej informacji, zobacz WindowProc.
Parametry komunikatu często zawierają informacje zarówno w wyrazach o niskiej kolejności, jak i wysokiej kolejności. Istnieje kilka makr, których aplikacja może użyć do wyodrębnienia informacji z parametrów komunikatu. Makro LOWORD, na przykład wyodrębnia wyraz o niskiej kolejności (bity od 0 do 15) z parametru komunikatu. Inne makra obejmują HIWORD, LOBYTEi HIBYTE makro.
Interpretacja wartości zwracanej zależy od konkretnego komunikatu. Zapoznaj się z opisem każdego komunikatu, aby określić odpowiednią wartość zwracaną.
Ponieważ można wywołać procedurę okna rekursywnie, ważne jest zminimalizowanie liczby zmiennych lokalnych, których używa. Podczas przetwarzania poszczególnych komunikatów aplikacja powinna wywoływać funkcje poza procedurą okna, aby uniknąć nadmiernego użycia zmiennych lokalnych, co może spowodować przepełnienie stosu podczas głębokiej rekursji.
Domyślna procedura okna
Domyślna funkcja procedury okna DefWindowProc definiuje pewne podstawowe zachowanie współużytkowane przez wszystkie okna. Domyślna procedura okna zapewnia minimalną funkcjonalność okna. Procedura okna zdefiniowanego przez aplikację powinna przekazać wszystkie komunikaty, które nie są przetwarzane do funkcji DefWindowProc na potrzeby przetwarzania domyślnego.
Podklasa procedury okna
Gdy aplikacja tworzy okno, system przydziela blok pamięci do przechowywania informacji specyficznych dla okna, w tym adresu procedury okna, która przetwarza komunikaty dla okna. Gdy system musi przekazać komunikat do okna, przeszukuje informacje specyficzne dla okna w celu znalezienia adresu procedury okna i przekazuje komunikat do tej procedury.
podklasy to technika umożliwiająca aplikacji przechwytywanie i przetwarzanie komunikatów wysyłanych lub wysyłanych do określonego okna przed ich przetworzeniem. Po sklasyfikowaniu okna aplikacja może rozszerzyć, zmodyfikować lub monitorować zachowanie okna. Aplikacja może podklasować okno należące do klasy globalnej systemu, takie jak kontrolka edycji lub pole listy. Na przykład aplikacja może podklasować kontrolkę edycji, aby uniemożliwić kontrolce akceptowanie niektórych znaków. Nie można jednak podklasować okna ani klasy należącej do innej aplikacji. Wszystkie podklasy muszą być wywoływane w ramach tego samego procesu.
Aplikacja tworzy podklasę okna, zastępując adres oryginalnej procedury okna adresem nowej procedury okna, nazywanej procedurą podklasy . Następnie procedura podklasy odbiera wszystkie komunikaty wysłane lub opublikowane w oknie.
Procedura podklasy może wykonać trzy akcje po otrzymaniu komunikatu: może przekazać komunikat do oryginalnej procedury okna, zmodyfikować komunikat i przekazać go do oryginalnej procedury okna lub przetworzyć komunikat i nie przekazać go do oryginalnej procedury okna. Jeśli procedura podklasy przetwarza komunikat, może to zrobić przed, po lub zarówno przed, jak i po przekazaniu komunikatu do oryginalnej procedury okna.
System udostępnia dwa typy podklas: wystąpienia i globalne. W podklasy wystąpieńaplikacja zastępuje adres procedury okna pojedynczego wystąpienia okna okna. Aplikacja musi używać dziedziczenia instancji, aby tworzyć podklasę istniejącego okna. W globalnej podklasyaplikacja zastępuje adres procedury okna w strukturze WNDCLASSEX klasy okien. Wszystkie kolejne okna utworzone za pomocą klasy mają adres procedury podklasy, ale nie ma to wpływu na istniejące okna klasy.
Podklasy instancji
Aplikacja tworzy podklasę wystąpienia okna przy użyciu funkcji SetWindowLongPtr. Aplikacja przekazuje flagę GWL_WNDPROC, dojście do okna, które ma być podklasowane, oraz adres procedury podklasy do funkcji SetWindowLongPtr. Procedura podklasy może znajdować się w pliku wykonywalnym aplikacji lub w pliku DLL.
Po przekazaniu flagi GWL_WNDPROCSetWindowLongPtr zwraca adres oryginalnej procedury okna okna. Aplikacja musi zapisać ten adres, używając go w kolejnych wywołaniach funkcji CallWindowProc, aby przekazać przechwycone komunikaty do oryginalnej procedury okna. Aplikacja musi również mieć oryginalny adres procedury okna, aby usunąć podklasę z okna. Aby usunąć podklasę, aplikacja ponownie wywołuje SetWindowLongPtr, przekazując adres oryginalnej procedury okna z flagą GWL_WNDPROC i uchwytem do okna.
System jest właścicielem klas globalnych systemu, a aspekty kontrolek mogą ulec zmianie z jednej wersji systemu na następną. Jeśli aplikacja musi podklasować okno należące do klasy globalnej systemu, deweloper może potrzebować zaktualizować aplikację po wydaniu nowej wersji systemu.
Ponieważ podklasowanie wystąpienia występuje po utworzeniu okna, nie można dodać żadnych dodatkowych bajtów do okna. Aplikacje, które podklasują okno, powinny używać listy właściwości okna do przechowywania wszelkich danych potrzebnych dla wystąpienia okna podklasyfikowanego. Aby uzyskać więcej informacji, zobacz Właściwości okna.
Gdy aplikacja podklasuje okno już podklasowane, musi usunąć podklasy w odwrotnej kolejności, w jakiej zostały utworzone. Jeśli kolejność usuwania nie zostanie odwrócona, może wystąpić nieodwracalny błąd systemu.
Podklasy globalne
Aby globalnie podklasować klasę okien, aplikacja musi mieć dojście do okna klasy. Aplikacja wymaga również uchwytu, aby usunąć podklasę. Aby uzyskać dojście, aplikacja zazwyczaj tworzy ukryte okno klasy do podklasy. Po uzyskaniu uchwytu aplikacja wywołuje funkcję SetClassLongPtr, określając uchwyt, flagę GCL_WNDPROC i adres procedury podklasy. SetClassLongPtr zwraca adres oryginalnej procedury okna dla klasy.
Oryginalny adres procedury okna jest używany w podklasie globalnej w taki sam sposób, jak w podklasach wystąpień. Procedura podklasy przekazuje komunikaty do oryginalnej procedury okna, wywołując CallWindowProc. Aplikacja usuwa podklasę z klasy okna, ponownie wywołując SetClassLongPtr i określając adres oryginalnej procedury okna, flagę GCL_WNDPROC oraz uchwyt do okna klasy, której utworzono podklasę. Aplikacja, która globalnie podklasuje klasę sterowania, musi usunąć podklasę po zakończeniu działania aplikacji; w przeciwnym razie może wystąpić nieodwracalny błąd systemu.
Podklasy globalne mają takie same ograniczenia jak podklasy instancji, jak również pewne dodatkowe restrykcje. Aplikacja nie powinna używać dodatkowych bajtów dla klasy lub wystąpienia okna, nie wiedząc dokładnie, jak używa ich oryginalna procedura okna. Jeśli aplikacja musi skojarzyć dane z oknem, powinna używać właściwości okna.
Nadklasowanie procedury okna
nadklasowanie to technika, która umożliwia aplikacji utworzenie nowej klasy okna z podstawową funkcjonalnością istniejącej klasy oraz ulepszeniami dostarczanymi przez aplikację. Superklasa jest oparta na istniejącej klasie okien o nazwie klasy bazowej. Często klasa bazowa jest systemową globalną klasą okien, taką jak kontrolka edycji, ale może to być dowolna klasa okna.
Superklasa ma własną procedurę okna, nazywaną procedurą superklasy. Procedura superklasy może wykonać trzy akcje po otrzymaniu komunikatu: może przekazać komunikat do oryginalnej procedury okna, zmodyfikować komunikat i przekazać go do oryginalnej procedury okna lub przetworzyć komunikat i nie przekazać go do oryginalnej procedury okna. Jeśli procedura superklasy przetwarza komunikat, może to zrobić przed, po, lub zarówno przed, jak i po przekazaniu komunikatu do oryginalnej procedury okna.
W przeciwieństwie do procedury podklasy, procedura superklasy może przetwarzać komunikaty tworzenia okien (WM_NCCREATE, WM_CREATEitd.), ale musi również przekazać je do oryginalnej procedury okna klasy bazowej, aby procedura okna klasy bazowej mogła wykonać procedurę inicjowania.
Aby zastąpić klasę okien, aplikacja najpierw wywołuje funkcję GetClassInfoEx w celu pobrania informacji o klasie bazowej. GetClassInfoEx wypełnia strukturę WNDCLASSEX wartościami z struktury WNDCLASSEX klasy bazowej. Następnie aplikacja kopiuje własne dojście wystąpienia do hInstance członu WNDCLASSEX struktury i kopiuje nazwę superklasy do członu lpszClassName. Jeśli klasa bazowa ma menu, aplikacja musi podać nowe menu z tymi samymi identyfikatorami menu i skopiować nazwę menu do elementu członkowskiego lpszMenuName. Jeśli procedura superklasy przetwarza komunikat WM_COMMAND i nie przekazuje go do procedury okna klasy bazowej, menu nie musi mieć odpowiednich identyfikatorów. GetClassInfoEx nie zwraca elementu członkowskiego lpszMenuName, lpszClassNameani hInstance w strukturze WNDCLASSEX.
Aplikacja musi również ustawić lpfnWndProc składową struktury WNDCLASSEX. Funkcja GetClassInfoEx wypełnia to pole adresem oryginalnej procedury okna danej klasy. Aplikacja musi zapisać ten adres, aby przekazać komunikaty do oryginalnej procedury okna, a następnie skopiować adres procedury nadrzędnej klasy do członka lpfnWndProc. Aplikacja może w razie potrzeby zmodyfikować inne elementy członkowskie struktury WNDCLASSEX. Po wypełnieniu struktury WNDCLASSEX aplikacja rejestruje superklasę, przekazując adres struktury do funkcji RegisterClassEx. Następnie tej superklasy można użyć do utworzenia okien.
Ponieważ rejestrowanie nowej klasy okien przez nadklasowanie pozwala aplikacji dodawać zarówno dodatkowe bajty klasy, jak i dodatkowe bajty okien. Superklasa nie może używać oryginalnych dodatkowych bajtów dla klasy bazowej lub okna z tych samych powodów, dla których podklasa instancji lub podklasa globalna nie powinna ich używać. Ponadto, jeśli aplikacja dodaje dodatkowe bajty do użycia w klasie lub instancji okna, musi odnosić się do dodatkowych bajtów w stosunku do liczby dodatkowych bajtów używanych przez oryginalną klasę bazową. Ponieważ liczba bajtów używanych przez klasę bazową może się różnić od jednej wersji klasy bazowej do następnej, przesunięcie początkowe dla własnych dodatkowych bajtów superklasy może również różnić się od jednej wersji klasy bazowej do następnej.