sample_keyhook_global.hsp

sample\rawinput\sample_keyhook_global.hsp » Plain Format

;============================================================
;   SetWindowsHookEx WH_KEYBOARD_LL サンプル: グローバルキーフック
;
;   Low-level keyboard hook で全プロセスのキーストロークを受信します。
;   ホットキーマネージャ、キー履歴、自動操作検出などに応用できます。
;
;   注意:
;     - setcallback が必要 (hsp3net 専用機能)
;     - ブロッキング動作のため重い処理は避ける
;     - 終了時に UnhookWindowsHookEx を必ず呼ぶ (さもないと全プロセスが固まる)
;     - Ctrl+Alt+X で終了
;============================================================

#include "hsp3_net_64.as"
#include "user32_gen2.as"
#include "win32_types_gen2.as"

	title "グローバル KeyHook サンプル"
	screen 0, 720, 520, screen_normal
	color 255, 255, 255 : boxf
	color 0, 0, 0
	pos 10, 10
	mes "Windows 全体のキーストロークを受信中..."
	mes "【終了】 Ctrl + Alt + X を押す"
	mes ""
	pos 10, 80
	log_y = 80

	; setcallback で LowLevelKeyboardProc を作成
	; プロトタイプ: LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
	setcallback *on_key_hook, 3
	cb_ptr = stat

	; SetWindowsHookExW(WH_KEYBOARD_LL=13, proc, hInstance=0, threadId=0)
	WH_KEYBOARD_LL = 13
	SetWindowsHookExW WH_KEYBOARD_LL, cb_ptr, 0, 0
	hhk = stat
	if hhk = 0 : dialog "SetWindowsHookEx failed" : end

	terminated = 0

*main_loop
	wait 2
	if terminated : goto *done
	goto *main_loop

; ---------------------------------------------------------
; LowLevelKeyboardProc (callback)
;   nCode: < 0 なら必ず CallNextHookEx を呼んで素通し
;   wParam: WM_KEYDOWN (0x100) / WM_KEYUP (0x101) /
;           WM_SYSKEYDOWN (0x104) / WM_SYSKEYUP (0x105)
;   lParam: KBDLLHOOKSTRUCT* へのポインタ
;     struct KBDLLHOOKSTRUCT {
;       DWORD vkCode;        // offset 0
;       DWORD scanCode;      // offset 4
;       DWORD flags;         // offset 8
;       DWORD time;          // offset 12
;       ULONG_PTR dwExtraInfo;  // offset 16 (8 byte on x64)
;     }
; ---------------------------------------------------------
*on_key_hook
	n_code = callbackarg(0)
	w_param = callbackarg(1)
	l_param = callbackarg(2)

	if n_code < 0 {
		; 素通し
		CallNextHookEx 0, n_code, w_param, l_param
		comret stat
		return
	}

	; l_param から KBDLLHOOKSTRUCT を読む
	; lparam は intptr なので dupptr でバッファに紐付け
	dupptr kbs, l_param, 24, 4          ; 24 byte, int 型
	vk_code = kbs(0)          ; offset 0
	scan    = kbs(1)          ; offset 4
	flags   = kbs(2)          ; offset 8

	; 終了判定: Ctrl+Alt+X (keyup のみ)
	if w_param == 0x101 {       ; WM_KEYUP
		if vk_code == 'X' {
			dim ks1, 1
			GetKeyState 0x11      ; VK_CONTROL
			if (stat & 0x8000) {
				GetKeyState 0x12  ; VK_MENU (Alt)
				if (stat & 0x8000) {
					terminated = 1
				}
			}
		}
	}

	; KEYDOWN のみログ表示
	if (w_param == 0x100) | (w_param == 0x104) {
		; ロック系は log 取らない (CapsLock/NumLock/ScrollLock 頻出)
		if (vk_code != 0x14) & (vk_code != 0x90) & (vk_code != 0x91) {
			redraw 0
			pos 10, log_y
			; 印字可能な文字は strf
			ch = ""
			if (vk_code >= 'A') & (vk_code <= 'Z') : ch = strf(" '%c'", vk_code)
			if (vk_code >= '0') & (vk_code <= '9') : ch = strf(" '%c'", vk_code)
			if vk_code == 0x08 : ch = " [BS]"
			if vk_code == 0x0D : ch = " [ENTER]"
			if vk_code == 0x20 : ch = " [SP]"
			if vk_code == 0x1B : ch = " [ESC]"
			color 0, 0, 0
			mes strf("  VK=0x%02X%s scan=0x%02X flags=0x%02X msg=0x%03X",
			         vk_code, ch, scan, flags, w_param)
			log_y += 18
			if log_y > 500 {
				color 255, 255, 255 : boxf 10, 80, 710, 515
				color 0, 0, 0
				log_y = 80
			}
		}
	}

	; 次のフック or 既定処理へ素通し
	CallNextHookEx 0, n_code, w_param, l_param
	comret stat
	return

*done
	UnhookWindowsHookEx hhk
	dialog "Hook removed. Bye!"
	end