Хуки в Windows
Доброго времени суток, уважаемые подписчики. Сегодня познакомимся с так называемыми хуками (это не ругательство, а русская итерпритация слова hook=крючок) и обсудим их использование в нашем проекте.
Существует много ситуаций, когда какие-нибудь сообщения окна нужно обрабатывать незамедлительно, а так как пришедшие на процедуру окна сообщения обрабатываются поочерёдно, то обработка важного сообщения может затянуться надолго. Выходом может создание двух потоков (вернее тредов=thread, но поток понятнее звучит), один из которых обрабатывает важные сообщения, другой - все остальные. Но часто хуки могут стать идеальным решением. Хуки позволяют перехватывать некоторые сообщения при их посылке (а не получении), что позволяет быстрее обработать нужные сообщения. Хуки устанавливаются функцией SetWindowsHookEx, которая имеет следующие параметры:
- Тип хука
- адрес хук-процедуры
- handle процесса, создающего хук
- Индекс треда на который ставиться хук
Первый параметр может принимать следующие значения:
WH_CALLWNDPROC - Перехватывает ВСЕ сообщения ДО того как их получает процедура окна
WH_CALLWNDPROCRET - Перехватывает ВСЕ сообщения ПОСЛЕ того как их обработала процедура окна
WH_CBT - Перехватывает сообщения связанные с изменениями окна
WH_DEBUG - Перехватывает ВСЕ сообщения прежде чем они попадают к хук-процедурам
WH_KEYBOARD - Перехватывает "клавиатурные" сообщения, такие как нажатие клавиши
WH_MOUSE - Перехватывает сообщения мышки
WH_MSGFILTER - Перехватывает сообщение посланые диалогом, MessageBox-ом, меню или ScrollBar-ом
WH_SHELL - Перехватывает сообщения оболочки (то есть Windows), такие как изменение текущего языка ввода текста
|
В нашем проекте я собираюсь использовать WM_MOUSE и WM_KEYBOARD. Именно процедура перехвата сообщений клавиатуры находиться в файле keyboard.asm нашего проекта. Давайте разберёмся, как же это работает, на примере нашего проекта:
AsmGL.asm (лишь интересующая нас часть, полный файл см. в выпуске №26):
...
_TEXT SEGMENT public USE32 'code'
_AsmGLWindow@40 proc
...
_AsmGLWindow@40 endp
_AsmGLResizeScene@8 proc
...
_AsmGLReSizeScene@8 endp
_start@12 proc
...
_start@12 endp
RegisterAsmGLClass proc
...
RegisterAsmGLClass endp
AsmGLWndProc proc
push ebp
mov ebp,esp
cmp dword ptr [ebp+0ch],WM_CREATE
je create_proc
run GetWindowLong, dword ptr [ebp+08h], 0
pop ebp
test eax,eax
jz not_yet
jmp eax
not_yet:
jmp DefWindowProcW
create_proc:
run GetCurrentThreadId, ebx
run SetWindowsHookExW, WH_KEYBOARD, offset HotKeys, ebx, eax
run SetWindowLong, dword ptr [ebp+08h], GWL_USERDATA, eax
mov ebx,[ebp+14h]
mov ebx,[ebx]
run SetWindowLong, dword ptr [ebp+08h], 0, ebx
mov eax,ebx
pop ebx
pop ebp
jmp eax
AsmGLWndProc endp
InitGL proc
...
InitGL endp
KillGLWindow proc
...
KillGLWindow endp
;Другие функции, которые будем рассматривать позже
include HotKeys.asm
include Draw.asm
;Инициализированные данные
ClearDepth dq 1.0f
...
|
HotKeys.asm:
HotKeys proc
push ebp
mov ebp,esp
pusha
null ebx
mov esi, [ebp+0Ch]
run CallNextHookEx, hHook, dword ptr [ebp+08h], esi, dword ptr [ebp+10h]
mov eax,esi
mov edi, offset Keys
mov ecx,(offset Kproc)-(offset Keys)
repne scasb
jne EndHookProc_1
mov eax,offset Keys
sub edi,eax
jmp dword ptr Kproc[edi*4-4]
escape_k:
mov ExitFlag,1
EndHookProc_1:
popa
null eax
pop ebp
ret 12
XXX_k:
...
jmp short EndHookProc_1
Keys db VK_ESCAPE
db VK_XXX
Kproc dd offset escape_k
dd offset XXX_k
HotKeys endp
|
К сожалению, это процедура не закончена, так как я ещё точно не знаю какие клавиши должны быть использованы, XXX означает любую клавишу. Рассмотрим, как же она работает! Она получает три параметра, тип операции, код виртуальной клавиши, информацию о нажатии клавиши. Так как хук-функция обязана заботиться о том, чтоб следующая хук-процедура тоже получила это сообщение, первым делом вызываем CallNextHookEx. После чего проверяем не нужная ли нам клавиша нажата следующим способом:
- Зансим указатель на массив нужных нам клавиш в edi
- в ecx помещаем количество клавиш в массиве
- и смотрим не совпадает ли хоть одна из них с полученной
- если совпала, то используем индекс найденной клавиши в качестве адреса процедуры
На сегодня это всё. В следующем уроке рассмотрим все типы хук-процедур. Если есть какие вопросы, пишите. Пишите на Dark_Lord@RusFAQ.ru или Dark_Lord@land.ru.