Доброго времени суток, уважаемые подписчики. Сегодня, как и было обещано, мы рассмотрим возможности Windows-hook процедуры, созданной с типом WH_CBT.
Процедура типа WH_CBT отличается от других типов тем, что может не только предотвратить посылку сообщения, но и полностью аннулировть некоторые изменения в системе. Как и все хук-процедуры она получает три параметра, причём два последних зависят от первого. Первый параметр определяет тип сообщения и может принимать следующие значения:
Код
Название
Значение
0
HCBT_MOVESIZE*
Запрос на перемещение или изменение размера окна
1
HCBT_MINMAX*
Запрос на минимизацию или максимизацию окна
2
HCBT_QS
Тредом получено сообщение, посылаемое при создании хук-процедуры типа WH_JOURNALPLAYBACK на этот тред
3
HCBT_CREATEWND*
Запрос на создание окна
4
HCBT_DESTROYWND*
Запрос на уничтожение окна
5
HCBT_ACTIVATE*
Запрос на активизацию окна
6
HCBT_CLICKSKIPPED
Сообщение мышки было убрано из очереди приходящих сообщениий
7
HCBT_KEYSKIPPED
Сообщение клавиатуры было убрано из очереди приходящих сообщениий
8
HCBT_SYSCOMMAND*
Запрос на выполнение системной команды
9
HCBT_SETFOCUS*
Запрос на изменение выделенного окна
* - возвращение ненулевого значения в ответ на такой запрос аннулирует операцию
Последние два параметра, как уже было замечено, зависят от первого параметра.
первый парам.
второй парам.
третий парам.
HCBT_MOVESIZE
handle окна
указатель на структуру RECT, значения которой можно изменять из хук-процедуры
HCBT_MINMAX
handle окна
младшее слово = значение вида окна (как в ShowWindow)
HCBT_QS
ноль
ноль
HCBT_CREATEWND
handle окна
указател на структуру CBT_CREATEWND
HCBT_DESTROYWND
handle окна
ноль
HCBT_ACTIVATE
handle окна
указатель на структуру CBTACTIVATESTRUCT
HCBT_CLICKSKIPPED
Сообщение, убранное из очереди
указатель на сообщение MOUSEHOOKSTRUCT
HCBT_KEYSKIPPED
Код виртуальной клавиши (VK_...)
как lParam сообщения WM_KEYDOWN
HCBT_SYSCOMMAND
Код системной команды (SC_...)
как lParam сообщения WM_SYSCOMMAND
HCBT_SETFOCUS
handle выделяемого окна
handle окна, теряющего выделение
Для лучшего понимания напишем простую программу, после запуска которой попытка изменить размер любого окна приводит к тому, что окно становится 300х200 пикселей. Причём происходит это так, что система думает, что это юзер изменил размер окна! Для этого нам нужно создать динамическую библиотеку (процедуры глобальных хуков должны находиться в динамической библиотеке) и саму программу. Начнём с библиотеки:
cbt_dll.asm:
include kernel32.inc
include user32.inc
include def32.inc
include macros.inc
.386
.model flat
public _InstallHook@4
public _UninstallHook@0
.data
hInstance dd 0
hWnd dd 0
hHook dd 0
.code
_InstallHook@4 proc
mov eax,[esp+04h]
mov hWnd,eax
run SetWindowsHookEx, WH_CBT, offset HookProc, hInstance, 0
mov hHook,eax
ret 4
_InstallHook@4 endp
HookProc proc
push ebp
mov ebp,esp
mov eax,[ebp+08h]
test eax,eax
js no_processing
test eax,eax ;cmp eax,HCBT_MOVESIZE
jnz EndHookProc
run GetWindowLong, dword ptr [ebp+0ch], GWL_HWNDPARENT
test eax,eax
jnz EndHookProc
EndHookProc:
leave
null eax
ret 12
no_processing:
leave
pop eax
push hHook
push eax
jmp CallNextHookEx
HookProc endp
_UninstallHook@0 proc
run UnhookWindowsHookEx, hHook
ret
_UninstallHook@0 endp
_start@12:
mov eax,[esp+04h]
mov hInstance,eax
null eax
inc eax
ret 12
end _start@12
Думаю, здесь нет ничего сложного, функции Install/UninstallHook инсталируют/деинсталируют хук, а HookProc, после убеждения в том, что текущее сообщение стоит обрабатывать, изменяет размеры передаваемые системе. Для компиляции также понадобится файл линковки(cbt_dll.lnk):
include kernel32.inc
include user32.inc
include macros.inc
include def32.inc
include cbt_dll.inc
.386
.model flat
.data
HookFlag dd ?
ButtonHook db 'Hook it!',0
ButtonUnhook db 'Unhook',0
.code
_start:
null ebx
run GetModuleHandle, ebx
run DialogBoxParam, eax, 1, ebx, offset WndProc, ebx
run ExitProcess, ebx
WndProc proc
push ebp
mov ebp,esp
pusha
mov edi,[ebp+08h]
null ebx
mov eax,[ebp+0Ch]
cmp eax,WM_COMMAND
je command_proc
cmp eax,WM_INITDIALOG
je init_proc
cmp eax,WM_CLOSE
je close_proc
popa
null eax
leave
ret 16
close_proc:
run EndDialog, edi, ebx
EndWndProc:
popa
null eax
inc eax
leave
ret 16
init_proc:
run SetDlgItemText, edi, 100, offset ButtonHook
jmp short EndWndProc
command_proc:
cmp word ptr [ebp+10h], 100
jne EndWndProc
cmp HookFlag,ebx
jz hook_proc
run UninstallHook
run SetDlgItemText, edi, 100, offset ButtonHook
dec HookFlag
jmp EndWndProc
hook_proc:
run InstallHook, edi
run SetDlgItemText, edi, 100, offset ButtonUnhook
inc HookFlag
jmp EndWndProc
WndProc endp
end _start
Я считаю, что ничего нового здесь нет, единственное, что следует отметить это то, что нужно создать .inc файл для использования нашей библиотеки (cbt_dll.inc):
Компилировать саму программу следует лишь после успешной компиляции библиотеки, так как указанный в cbt_dll.inc файл cbt_dll.lib будет создан лишь в процессе успешной комниляции динамической библиотеки! Компиляцию программы можно произвести следующим батником(cbt.bat):
Если компилятор выдаст ошибку в связи с незаданными константами, то скачайте .inc файлы из дополнения к выпуску.
Дополнения к выпуску: 0030asm - набранный вариант примеров, приведённых в выпуске 0030inc - файлы дополнения kernel32.inc, user32.inc, def32.inc и cbt_dll.inc 0030exe - скомпилированные примеры выпуска
На сегодня это всё. В следующем уроке рассмотрим хук-процедуру WH_CBT. Если есть какие вопросы, пишите. Пишите на Dark_Lord@RusFAQ.ru или Dark_Lord@land.ru.