Wyjście Spis treści Poprzedni Następny
Autor:
©Iczelion |
©2008 mgr
Jerzy Wałaszek |
|
Na tej lekcji dowiemy się o podpinaniu się do systemu Windows (Windows hooks), które jest bardzo potężnym narzędziem. Przy jego pomocy możesz zaglądać do wnętrza innych procesów, a czasami nawet zmieniać sposób ich działania.
Kod źródłowy możesz pobrać {z tego archiwum}.
Podpięcia do Windows można uważać za jedną z najpotężniejszych cech tego systemu. Dzięki nim możesz przechwycić zdarzenia, które wystąpią albo w twoim własnym procesie, albo w innych procesach. "Podpięcie" oznacza nakazanie systemowi Windows wywołania pewnej funkcji filtrującej, zwanej procedurą podpięcia (hook procedure) za każdym razem, gdy pojawi się interesujące nas zdarzenie. Istnieją dwa rodzaje podpięć: lokalne i odległe.
Gdy instalujesz podpięcia, pamiętaj, iż wpływają one na wydajność systemu. Podpięcia ogólnosystemowe są tutaj najbardziej zniesławione. Ponieważ WSZYSTKIE zdarzenia będą przechodziły poprzez twoją funkcję filtrującą, to twój system może zauważalnie zwolnić. Zatem jeśli używasz podpięcie ogólnosystemowe, powinieneś robić to inteligentnie i rozłączyć się natychmiast, gdy przestanie ci to być potrzebne. Również masz większą szansę zablokowania innych procesów, ponieważ wtrącasz się w ich pracę i jeśli twoja funkcja filtrująca pracuje nieprawidłowo, to może puścić inne procesy w niepamięć. Pamiętaj: władza oznacza odpowiedzialność.
Zanim będziesz mógł wykorzystać efektywnie podpięcia, musisz poznać sposób ich działania. Gdy tworzysz podpięcie, system Windows buduje w pamięci strukturę danych zawierającą informację o danym podpięciu i dodaje ją do listy istniejących podpięć. Nowe podpięcie dodawane jest przed starymi. Gdy następuje jakieś zdarzenie, a zainstalowałeś lokalne podpięcie, to w twoim procesie zostaje wywołana funkcja filtrująca, zatem jest to operacja bezpośrednia. Lecz jeśli zainstalowałeś odległe podpięcie, to system musi wstrzyknąć kod procedury podpięcia w przestrzeń adresową innego procesu. A system może to wykonać tylko wtedy, gdy funkcja ta znajduje się w bibliotece DLL. Stąd, jeśli chcesz użyć odległego podpięcia, twoja procedura musi znaleźć się w bibliotece DLL. Istnieją dwa odstępstwa od tej reguły: podpięcia do nagrywania i odtwarzania dziennika systemu Procedury podpięć dla tych dwóch przypadków muszą znajdować się w wątkach, które je zainstalowały. Powodem jest to, iż oba podpięcia mają do czynienia z przechwytywaniem niskopoziomowych zdarzeń pochodzących od sprzętu. Zdarzenia wejściowe muszą być nagrywane i odtwarzane w tej samej kolejności, w której wystąpiły. Gdyby kod tych podpięć znajdował się w bibliotece DLL, to zdarzenia wejściowe rozproszyłyby się po kilku wątkach i nie moglibyśmy odgadnąć ich kolejności. Stąd rozwiązaniem jest umieszczenie ich procedur w pojedynczym wątku, tj. wątku, który zainstalował te podpięcia.
Istnieje 14 typów podpięć:
Teraz, gdy poznaliśmy już nieco teorii, możemy przejść do sposobów instalowania i odinstalowywania podpięć.
Aby zainstalować podpięcie, wywołujesz funkcję SetWindowsHookEx o następującej składni:
SetWindowsHookEx PROTO HookType: DWORD,\ pHookProc: DWORD,\ hInstance: DWORD,\ ThreadID: DWORD
Jeśli wywołanie się powiedzie, zwraca w rejestrze eax uchwyt podpięcia. Jeśli nie, zwracana jest wartość NULL. Musisz zachować ten uchwyt do późniejszego usunięcia podpięcia.
Podpięcie możesz odinstalować wywołując funkcję UnhookWindowsHookEx, która akceptuje tylko jeden parametr - uchwyt podpięcia do odinstalowania. Jeśli wywołanie się powiedzie, to zwraca niezerową wartość w rejestrze eax. W przeciwnym razie zwraca NULL.
Teraz, gdy znasz sposoby instalowania i usuwania podpięć, możemy zbadać procedurę podpięcia.
Procedura ta zostanie wywołana za każdym razem, gdy wystąpi zdarzenie powiązane z zainstalowanym typem podpięcia. Na przykład, jeśli zainstalowałeś podpięcie WH_MOUSE, to przy wystąpieniu zdarzenia myszki zostanie wywołana twoja procedura. Bez względu na typ zainstalowanego podpięcia jego procedura zawsze posiada następujący prototyp:
HookProc PROTO nCode:DWORD, wParam:DWORD, lParam:DWORD
HookProc jest właściwie szablonem nazwy funkcji. Możesz funkcję tę nazwać w dowolny sposób, o ile zachowasz zgodność z powyższym prototypem. Interpretacja parametrów nCode, wParam i lParam zależy od typu zainstalowanego podpięcia. Również odnosi się to do wartości zwrotnej z procedury podpięcia. Na przykład:
WH_CALLWNDPROC | |
---|---|
nCode | może mieć jedynie wartość HC_ACTION, która oznacza wysłanie wiadomości do okna. |
wParam | zawiera wysyłaną wiadomość |
lParam | wskazuje strukturę CWPSTRUCT |
wartość zwrotna | nie używana, zwracaj zero |
WH_MOUSE | |
---|---|
nCode | może mieć wartość HC_ACTION lub HC_NOREMOVE |
wParam | zawiera wiadomość myszki |
lParam | wskazuje strukturę MOUSEHOOKSTRUCT |
wartość zwrotna | zero, jeśli wiadomość powinna być obsłużona i jeden, jeśli wiadomość należy porzucić. |
Zawsze skonsultuj się z plikiem pomocy dla biblioteki API Win32 odnośnie szczegółowych znaczeń poszczególnych parametrów oraz wartości zwrotnej w procedurze podpięcia, którą planujesz zainstalować.
Istnieje mały haczyk odnośnie procedury podpięcia. Pamiętaj, iż podpięcia tworzą połączoną ze sobą listę, w której ostatnio zainstalowane podpięcie znajduje się na samym początku. Gdy wystąpi zdarzenie, system Windows wywoła jedynie pierwsze podpięcie na liście. Od twojej procedury zależy, czy wywoła ona następne podpięcie na liście. Możesz zdecydować się nie wywoływać go, lecz lepiej upewnij się, co robisz. W większości przypadków dobrą praktyką jest wywoływanie następnej procedury, aby inne podpięcia mogły również spojrzeć na to zdarzenie. Następne podpięcie możesz wywołać za pomocą funkcji CallNextHookEx o następującym prototypie:
CallNextHookEx PROTO hHook:DWORD, nCode:DWORD, wParam:DWORD, lParam:DWORD
Istotna uwaga na temat odległych podpięć: procedura podpięcia musi znajdować się w bibliotece DLL, która zostanie odwzorowana w inne procesy. Gdy system Windows odwzorowuje bibliotekę DLL w przestrzeń adresową innych procesów, nie przenosi sekcji danych do tych procesów. W skrócie, wszystkie procesy dzielą pojedynczą kopię kodu, lecz każdy z nich posiada prywatną kopię sekcji danych biblioteki DLL! Może to być wielką niespodzianką dla niezorientowanych. Możesz sądzić, iż jeśli wpiszesz wartość do zmiennej w sekcji danych biblioteki DLL, to wartość ta będzie dzielona przez wszystkie procesy, które załadują tę bibliotekę DLL w swoją przestrzeń adresową. A to po prostu nieprawda. W normalnych warunkach zachowanie takie jest pożądane, ponieważ dostarcza iluzji posiadania przez każdy proces własnej kopii biblioteki DLL. - ale nie, gdy rozważamy podpięcie systemu Windows. Chcemy, aby biblioteka pozostawała identyczna we wszystkich procesach, łącznie z jej danymi. Rozwiązanie: musisz zaznaczyć sekcję danych jako współdzieloną. Możesz tego dokonać określając atrybut sekcji w przełączniku konsolidatora. Dla MASM'a powinieneś użyć przełącznika:
/SECTION:<nazwa sekcji>, S
Nazwą zainicjowanej sekcji danych jest .data, a sekcji niezainicjowanej jest .bss. Na przykład, jeśli chcesz dokonać asemblacji biblioteki DLL zawierającej procedurę podpięcia z wspólną dla procesów sekcją danych niezainicjowanych, musisz użyć następującego wiersza polecenia:
link /section:.bss,S /DLL /SUBSYSTEM:WINDOWS ...
Atrybut S oznacza tę sekcję jako współdzieloną (shared).
Występują dwa moduły: jeden jest programem głównym, który obsłuży graficzny interfejs użytkownika, a drugi jest biblioteką DLL instalującą o usuwającą doczepienie.
Plik programu głównego MOUSEHOOK.ASM
.386 .MODEL FLAT, STDCALL OPTION CASEMAP:NONE INCLUDE \masm32\include\windows.inc INCLUDE \masm32\include\user32.inc INCLUDE \masm32\include\kernel32.inc INCLUDE HookDLL.inc INCLUDELIB HookDLL.lib INCLUDELIB \masm32\lib\user32.lib INCLUDELIB \masm32\lib\kernel32.lib DlgFunc PROTO :DWORD, :DWORD, :DWORD, :DWORD .CONST IDD_MAINDLG EQU 101 IDC_CLASSNAME EQU 1000 IDC_HANDLE EQU 1001 IDC_WNDPROC EQU 1002 IDC_HOOK EQU 1004 IDC_EXIT EQU 1005 WM_MOUSEHOOK EQU WM_USER+6 .DATA HookFlag DD FALSE HookText DB "&Podepnij", 0 UnhookText DB "&Odepnij", 0 template DB "%lx", 0 .DATA? hInstance DD ? hHook DD ? .CODE start: INVOKE GetModuleHandle, NULL mov hInstance, eax INVOKE DialogBoxParam, hInstance, IDD_MAINDLG, NULL, ADDR DlgFunc, NULL INVOKE ExitProcess, NULL DlgFunc PROC hDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD LOCAL hLib: DWORD LOCAL buffer[128]: BYTE LOCAL buffer1[128]: BYTE LOCAL rect: RECT .IF uMsg==WM_CLOSE .IF HookFlag==TRUE INVOKE UninstallHook .ENDIF INVOKE EndDialog, hDlg, NULL .ELSEIF uMsg==WM_INITDIALOG INVOKE GetWindowRect, hDlg, ADDR rect INVOKE SetWindowPos, hDlg, HWND_TOPMOST,\ rect.left, rect.top,\ rect.right, rect.bottom, SWP_SHOWWINDOW .ELSEIF uMsg==WM_MOUSEHOOK INVOKE GetDlgItemText, hDlg, IDC_HANDLE, ADDR buffer1, 128 INVOKE wsprintf, ADDR buffer, ADDR template, wParam INVOKE lstrcmpi, ADDR buffer, ADDR buffer1 .IF eax!=0 INVOKE SetDlgItemText, hDlg, IDC_HANDLE, ADDR buffer .ENDIF INVOKE GetDlgItemText, hDlg, IDC_CLASSNAME, ADDR buffer1, 128 INVOKE GetClassName, wParam, ADDR buffer, 128 INVOKE lstrcmpi, ADDR buffer, ADDR buffer1 .IF eax!=0 INVOKE SetDlgItemText, hDlg, IDC_CLASSNAME, ADDR buffer .ENDIF INVOKE GetDlgItemText, hDlg, IDC_WNDPROC, ADDR buffer1, 128 INVOKE GetClassLong, wParam, GCL_WNDPROC INVOKE wsprintf, ADDR buffer, ADDR template, eax INVOKE lstrcmpi, ADDR buffer, ADDR buffer1 .IF eax!=0 INVOKE SetDlgItemText, hDlg, IDC_WNDPROC, ADDR buffer .ENDIF .ELSEIF uMsg==WM_COMMAND .IF lParam!=0 mov ax, WORD PTR wParam mov dx, WORD PTR wParam + 2 .IF dx==BN_CLICKED .IF ax==IDC_EXIT INVOKE SendMessage, hDlg, WM_CLOSE, 0, 0 .ELSE .IF HookFlag==FALSE INVOKE InstallHook, hDlg .IF eax!=NULL mov HookFlag, TRUE INVOKE SetDlgItemText, hDlg, IDC_HOOK, ADDR UnhookText .ENDIF .ELSE INVOKE UninstallHook INVOKE SetDlgItemText, hDlg, IDC_HOOK, ADDR HookText mov HookFlag, FALSE INVOKE SetDlgItemText, hDlg, IDC_CLASSNAME, NULL INVOKE SetDlgItemText, hDlg, IDC_HANDLE, NULL INVOKE SetDlgItemText, hDlg, IDC_WNDPROC, NULL .ENDIF .ENDIF .ENDIF .ENDIF .ELSE mov eax, FALSE ret .ENDIF mov eax, TRUE ret DlgFunc ENDP END start
Plik zasobów MOUSEHOOK.RC:
#define IDD_MAINDLG 101 #define DS_MODALFRAME 0x80 #define ES_AUTOHSCROLL 0x80 #define IDC_CLASSNAME 1000 #define IDC_HANDLE 1001 #define IDC_WNDPROC 1002 #define IDC_HOOK 1004 #define IDC_EXIT 1005 #define ES_READONLY 0x800 #define IDC_STATIC -1 #define DS_MODALFRAME 0x80 #define WS_POPUP 0x80000000 #define WS_CAPTION 0xC00000 #define WS_SYSMENU 0x80000 #define ES_AUTOHSCROLL 0x80 #define ES_READONLY 0x800 IDD_MAINDLG DIALOG 0, 0, 226, 79 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Podpięcie do Myszki" FONT 8, "MS Sans Serif" { GROUPBOX "Informacje o oknie", IDC_STATIC, 7, 7, 213, 67 LTEXT "Nazwa klasy:", IDC_STATIC, 13, 22, 57, 8, 0 EDITTEXT IDC_CLASSNAME, 75, 21, 139, 12, ES_AUTOHSCROLL | ES_READONLY LTEXT "Uchwyt:", IDC_STATIC, 13, 36, 58, 8, 0 EDITTEXT IDC_HANDLE, 75, 37, 77, 12, ES_AUTOHSCROLL | ES_READONLY LTEXT "Procedura okna:", IDC_STATIC, 13, 52, 57, 8, 0 EDITTEXT IDC_WNDPROC, 75, 52, 77, 12, ES_AUTOHSCROLL | ES_READONLY DEFPUSHBUTTON "&Podepnij", IDC_HOOK, 163, 35, 50, 14 PUSHBUTTON "&Koniec", IDC_EXIT, 163, 50, 50, 14 }
To jest kod źródłowy biblioteki DLL - plik HOOKDLL.ASM:
.386 .MODEL FLAT, STDCALL OPTION CASEMAP:NONE INCLUDE \masm32\include\windows.inc INCLUDE \masm32\include\kernel32.inc INCLUDE \masm32\include\user32.inc INCLUDELIB \masm32\lib\kernel32.lib INCLUDELIB \masm32\lib\user32.lib .CONST WM_MOUSEHOOK EQU WM_USER+6 .DATA hInstance DD 0 .DATA? hHook DD ? hWnd DD ? .CODE DllEntry PROC hInst:HINSTANCE, reason:DWORD, reserved1:DWORD push hInst pop hInstance mov eax, TRUE ret DllEntry ENDP MouseProc PROC nCode:DWORD, wParam:DWORD, lParam:DWORD INVOKE CallNextHookEx, hHook, nCode, wParam, lParam mov edx, lParam ASSUME edx:PTR MOUSEHOOKSTRUCT INVOKE WindowFromPoint, [edx].pt.x, [edx].pt.y INVOKE PostMessage, hWnd, WM_MOUSEHOOK, eax, 0 ASSUME edx:NOTHING xor eax, eax ret MouseProc ENDP InstallHook PROC hwnd:DWORD push hwnd pop hWnd INVOKE SetWindowsHookEx, WH_MOUSE, ADDR MouseProc, hInstance, NULL mov hHook, eax ret InstallHook ENDP UninstallHook PROC INVOKE UnhookWindowsHookEx, hHook ret UninstallHook ENDP END DllEntry
Plik HOOKDLL.DEF
LIBRARY HookDLL EXPORTS MouseProc InstallHook UninstallHook
Plik MAKEFILE dla biblioteki HookDLL. Jeśli asembler ml.exe i konsolidator link.exe nie znajdują się w systemowej ścieżce dostępu, to w pliku MAKEFILE należy określić odpowiednie ścieżki dostępu (również do bibliotek).
NAME=HookDLL $(NAME).dll: $(NAME).obj Link /SECTION:.bss,S /DLL /DEF:$(NAME).def /SUBSYSTEM:WINDOWS /LIBPATH:c:\masm\lib $(NAME).obj $(NAME).obj: $(NAME).asm ml /c /coff /Cp $(NAME).asm
Uwaga: jeśli korzystasz z pakietu RadASM (tak jak tłumacz), to utwórz projekt biblioteki DLL, a następnie w polu Link wprowadź poniższy tekst:
7,O,$B\LINK.EXE /SECTION:.bss|S /SUBSYSTEM:WINDOWS /RELEASE /DLL /DEF:$6 /LIBPATH:"$L",3
Chodzi tutaj głównie o wysłanie do konsolidatora przełącznika /SECTION:.bss,S. Jednakże jeśli dopiszesz ten przełącznik do treści pola Link, to interpreter poleceń środowiska RadASM źle zinterpretuje przecinek przed S - należy zamiast przecinka koniecznie wpisać znak |, który pełni właśnie rolę przecinka wysyłanego w wierszu polecenia do konsolidatora. |
Przykład wyświetli okno dialogowe z trzema kontrolkami edycyjnymi, które będą wypełniane nazwą klasy, uchwytem okna oraz adresem procedury okna związanymi z oknem pod kursorem myszki. W oknie dialogowym znajdują się dwa przyciski, Podepnij oraz Koniec. Gdy klikniesz przycisk Podepnij, program dokona doczepienia do danych pochodzących od myszki i tekst na przycisku zostanie zmieniony na Odepnij. Gdy przesuwasz kursor myszki ponad jakimś oknem, w głównym oknie przykładu wyświetlane są odpowiednie informacje. Gdy klikniesz przycisk Odepnij, program usunie doczepienie myszki.
Główny program stosuje okno dialogowe w charakterze swojego okna głównego. Definiuje on prywatną wiadomość WM_MOUSEHOOK, która będzie wykorzystywana pomiędzy programem głównym a biblioteką DLL. Gdy główny program otrzyma tę wiadomość, wParam będzie zawierało uchwyt okna, nad którym znajduje się kursor myszki. Oczywiście można to zrobić w sposób dowolny. Ja zdecydowałem się na wykorzystanie wParam do przekazywania uchwytu dla prostoty rozwiązania. Ty możesz wybrać swą własną metodę wymiany danych pomiędzy programem głównym a tą biblioteką DLL.
.IF HookFlag==FALSE INVOKE InstallHook, hDlg .IF eax!=NULL mov HookFlag, TRUE INVOKE SetDlgItemText, hDlg, IDC_HOOK, ADDR UnhookText .ENDIF
Program stosuje znacznik HookFlag do monitorowania stanu podpięcia. Ma on wartość FALSE, gdy podpięcie nie jest zainstalowane, a TRUE, gdy jest.
Gdy użytkownik kliknie przycisk Podepnij, program sprawdza, czy podpięcie jest już zainstalowane. Jeśli nie jest, to wywołuje funkcję InstallHook w bibliotece DLL, aby je zainstalować. Zwróć uwagę, iż jako parametr tej funkcji przekazujemy uchwyt głównego okna dialogowego, aby biblioteka DLL mogła przesyłać wiadomości WM_MOUSEHOOK do właściwego okna, tj. do naszego własnego.
Gdy program jest ładowany, wraz z nim zostaje również załadowana biblioteka DLL podpięcia. Właściwie biblioteki DLL są ładowane natychmiast po umieszczeniu programu w pamięci. Przed pierwszą instrukcja w programie wywoływana jest funkcja wejściowa biblioteki DLL. Zatem gdy program rozpocznie swoją pracę, biblioteki DLL są zainicjowane. W funkcji wejściowej biblioteki DLL podpięcia umieszczamy następujący kod:
DllEntry PROC hInst:HINSTANCE, reason:DWORD, reserved1:DWORD push hInst pop hInstance mov eax, TRUE ret DllEntry ENDP
Kod ten po prostu zachowuje uchwyt egzemplarza samej biblioteki DLL w globalnej zmiennej o nazwie hInstance do użytku wewnątrz funkcji InstallHook.
InstallHook PROC hwnd:DWORD push hwnd pop hWnd INVOKE SetWindowsHookEx, WH_MOUSE, ADDR MouseProc, hInstance, NULL mov hHook, eax ret InstallHook ENDP
Funkcja InstallHook jest sama w sobie bardzo prosta. Zachowuje ona przekazany jej jako parametr uchwyt okna w zmiennej globalnej o nazwie hWnd dla przyszłego użytku. Następnie wywołuje SetWindowsHookEx, aby zainstalować podpięcie do myszki. Wartość zwrotna z tego wywołania jest umieszczana w zmiennej globalnej o nazwie hHook do użycia przez funkcję UnhookWindowsHookEx.
Po wywołaniu SetWindowsHookEx podpięcie do myszki już działa. Gdy wystąpi w systemie jakieś zdarzenie myszki, zostanie wywołana procedura MouseProc (twoja procedura podpięcia).
MouseProc PROC nCode:DWORD, wParam:DWORD, lParam:DWORD INVOKE CallNextHookEx, hHook, nCode, wParam, lParam mov edx, lParam ASSUME edx:PTR MOUSEHOOKSTRUCT INVOKE WindowFromPoint, [edx].pt.x, [edx].pt.y INVOKE PostMessage, hWnd, WM_MOUSEHOOK, eax, 0 ASSUME edx:NOTHING xor eax, eax ret MouseProc ENDP
Pierwszą rzeczą jest wywołanie CallNextHookEx, aby dać szansę przetworzenia zdarzenia myszki innym podpięciom. Następnie wywołuje funkcję WindowFromPoint, aby pobrać uchwyt okna zajmującego określone współrzędne na ekranie. Zauważ, iż korzystamy tutaj z podstruktury POINT wewnątrz struktury MOUSEHOOKSTRUCT wskazywanej przez lParam jako bieżących współrzędnych myszki. I dalej wysyłamy ten uchwyt okna do programu głównego poprzez funkcję PostMessage z wiadomością WM_MOUSEHOOK. Musisz pamiętać, iż nie powinieneś używać wewnątrz procedury podpięcia funkcji SendMessage, ponieważ może ona doprowadzić do zakleszczenia. Zalecane jest użycie PostMessage. Strukturę MOUSEHOOKSTRUCT definiujemy poniżej:
MOUSEHOOKSTRUCT STRUCT DWORD pt POINT <> hwnd DWORD ? wHitTestCode DWORD ? dwExtraInfo DWORD ? MOUSEHOOKSTRUCT ENDS
Gdy główne okno otrzyma wiadomość WM_MOUSEHOOK, użyje uchwytu okna z parametru wParam do pobrania informacji o tym oknie.
.ELSEIF uMsg==WM_MOUSEHOOK INVOKE GetDlgItemText, hDlg, IDC_HANDLE, ADDR buffer1, 128 INVOKE wsprintf, ADDR buffer, ADDR template, wParam INVOKE lstrcmpi, ADDR buffer, ADDR buffer1 .IF eax!=0 INVOKE SetDlgItemText, hDlg, IDC_HANDLE, ADDR buffer .ENDIF INVOKE GetDlgItemText, hDlg, IDC_CLASSNAME, ADDR buffer1, 128 INVOKE GetClassName, wParam, ADDR buffer, 128 INVOKE lstrcmpi, ADDR buffer, ADDR buffer1 .IF eax!=0 INVOKE SetDlgItemText, hDlg, IDC_CLASSNAME, ADDR buffer .ENDIF INVOKE GetDlgItemText, hDlg, IDC_WNDPROC, ADDR buffer1, 128 INVOKE GetClassLong, wParam, GCL_WNDPROC INVOKE wsprintf, ADDR buffer, ADDR template, eax INVOKE lstrcmpi, ADDR buffer, ADDR buffer1 .IF eax!=0 INVOKE SetDlgItemText, hDlg, IDC_WNDPROC, ADDR buffer .ENDIF
Aby uniknąć migotania, sprawdzamy tekst znajdujący się już w kontrolkach edycyjnych i tekst do wprowadzenia do nich. Jeśli teksty są identyczne, opuszczamy operację uaktualnienia zawartości kontrolki edycyjnej.
Nazwę klasy otrzymamy wywołując GetClassName, a adres procedury okna wywołując GetClassLong z wartością GCL_WNDPROC, a następnie formatujemy je i umieszczamy w odpowiednich kontrolkach edycyjnych.
INVOKE UninstallHook INVOKE SetDlgItemText, hDlg, IDC_HOOK, ADDR HookText mov HookFlag, FALSE INVOKE SetDlgItemText, hDlg, IDC_CLASSNAME, NULL INVOKE SetDlgItemText, hDlg, IDC_HANDLE, NULL INVOKE SetDlgItemText, hDlg, IDC_WNDPROC, NULL
Gdy użytkownik kliknie przycisk Odepnij, program wywołuje funkcję UninstallHook w bibliotece DLL. UninstallHook po prostu wywołuje UnhookWindowsHookEx. Po tej operacji zmienia tekst przycisku z powrotem na Podepnij, a HookFlag na FALSE i wymazuje zawartość kontrolek edycyjnych.
Autorem
kursu jest
Iczelion. Kurs
programowania Windows znalazł się na serwerze I LO w Tarnowie za pisemną
zgodą autora. |
I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe