Тема: AHK: Установка хуков на события мыши и клавиатуры
Хук — это механизм, с помощью которого приложения могут перехватывать события — сообщения, действия мыши и нажатия клавиш. Функция, которая перехватывает определённые типы событий, называется хук-процедура (hook procedure). Хук-процедура может производить различные действия над каждым получаемым событием, модифицировать или исключать его. MSDN пишет, что если приложение устанавливает хук для отслеживания событий другого приложения, хук-процедура должна находиться в отдельной dll.
Однако замечено, что для отслеживания событий мыши и клавиатуры можно обойтись без написания dll и расположить хук-процедуру непосредственно в теле скрипта.
Клавиатурный хук:
OnExit, Exit
hHookKeybd := DllCall("SetWindowsHookEx"
, Int, WH_KEYBOARD_LL := 13
, Ptr, RegisterCallback("LowLevelKeyboardProc", "Fast")
, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
, UInt, 0, Ptr)
Return
Exit:
DllCall("UnhookWindowsHookEx", Ptr, hHookKeybd)
ExitApp
LowLevelKeyboardProc(nCode, wParam, lParam)
{
static msg, vk, sc, time
, oMsg := {0x100: "WM_KEYDOWN", 0x101: "WM_KEYUP", 0x104: "WM_SYSKEYDOWN", 0x105: "WM_SYSKEYUP"}
SetFormat, IntegerFast, H
msg := wParam . "" ; добавляем "", чтобы шестнадцатеричное число интерпретировалось,
vk := NumGet(lParam + 0, "UInt") . "" ; как строка, и не превратилось в десятичное после смены формата
ext := NumGet(lParam + 8, "UInt") & 1
sc := NumGet(lParam + 4, "UInt") | ext << 8 . ""
SetFormat, IntegerFast, D
time := NumGet(lParam + 12, "UInt")
SetTimer, EventHandling, -10 ; обработку событий "повесим" на таймер, чтобы не создавать помех в работе клавиатуры
Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, Ptr, wParam, Ptr, lParam)
EventHandling:
TrayTip,, % "Message = " . oMsg[msg]
. "`nvkCode = " . vk
. "`nscCode = " . sc
. "`nTime = " . time
Return
}
Esc::ExitApp
Хук на события мыши:
OnExit, Exit
hHookMouse := DllCall("SetWindowsHookEx"
, Int, WH_MOUSE_LL := 14
, Ptr, RegisterCallback("LowLevelMouseProc", "Fast")
, Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
, UInt, 0, Ptr)
Return
Exit:
DllCall("UnhookWindowsHookEx", Ptr, hHookMouse)
ExitApp
LowLevelMouseProc(nCode, wParam, lParam)
{
static msg, mouse_x, mouse_y, ext, time
, oMsg := { 0x200: "WM_MOUSEMOVE"
, 0x201: "WM_LBUTTONDOWN", 0x202: "WM_LBUTTONUP"
, 0x204: "WM_RBUTTONDOWN", 0x205: "WM_RBUTTONUP"
, 0x207: "WM_MBUTTONDOWN", 0x208: "WM_MBUTTONUP"
, 0x20B: "WM_XBUTTONDOWN", 0x20C: "WM_XBUTTONUP"
, 0x20A: "WM_MOUSEWHEEL" , 0x20E: "WM_MOUSEHWHEEL" }
, oMouseData := { 0: "0", 1: "XBUTTON1", 2: "XBUTTON2"
, 120: "WHEEL_DELTA forward", -120: "WHEEL_DELTA backward" }
msg := wParam
mouse_x := NumGet(lParam + 0, "Int")
mouse_y := NumGet(lParam + 4, "Int")
ext := NumGet(lParam + 10, "Short")
time := NumGet(lParam + 16, "UInt")
SetTimer, EventHandling, -10
Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, UInt, wParam, UInt, lParam)
EventHandling:
ToolTip, % "Message = " . oMsg[msg]
. "`nMouse_X = " . mouse_x
. "`nMouse_Y = " . mouse_y
. "`nMouseData = " . oMouseData[ext]
. "`nTime = " . time
Return
}
Esc::ExitApp
В случае, если параметр nCode хук-процедуры меньше нуля, она обязательно должна возвращать значение, возвращаемое функцией CallNextHookEx(). В остальных случаях также возвращение данного значения желательно, иначе другие приложения, где установлен такой же хук, не будут получать событий, что может привести к некорректной их работе.
Примеры использования:
Полная блокировка событий мыши
Инверсия мыши по вертикали
Определение символов, посылаемых с клавиатуры
Определение виртуальных и скан-кодов клавиатуры
Информация:
SetWindowsHookEx()
LowLevelKeyboardProc()
LowLevelMouseProc()