sample_rawinput_multi_keyboard.hsp

sample\rawinput\sample_rawinput_multi_keyboard.hsp » Plain Format

;============================================================
;   RawInput API サンプル: 複数キーボード識別
;
;   Windows の Raw Input API を使って、複数のキーボードデバイスを
;   区別して入力を受け取ります。バーコードリーダー、USB テンキー、
;   内蔵キーボードなどが別々の Device ID で表示されます。
;
;   物理的に 2 つ以上のキーボードを接続して実行してみてください。
;   ウィンドウを閉じれば終了。
;============================================================

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

	title "RawInput 複数キーボード識別サンプル"
	screen 0, 720, 520, screen_normal
	color 255, 255, 255 : boxf
	color 0, 0, 0
	pos 10, 10
	mes "複数キーボードを繋いでキーを押してください。発生元を Device ID"
	mes "ごとに区別して表示します。[ウィンドウの × ] で終了"
	mes ""

	; --- RAWINPUTDEVICE 構造体 (16 byte on x64) を組み立て ---
	; offset 0  USHORT UsagePage  = 0x01 (Generic Desktop)
	; offset 2  USHORT Usage      = 0x06 (Keyboard)
	; offset 4  DWORD  Flags      = RIDEV_INPUTSINK (フォーカス無くても受信)
	; offset 8  HWND   Target     = hwnd
	sdim rid, 16
	wpoke rid, 0, 0x01
	wpoke rid, 2, 0x06
	lpoke rid, 4, RIDEV_INPUTSINK
	lpoke rid, 8,  hwnd
	lpoke rid, 12, 0

	RegisterRawInputDevices rid, 1, 16
	if stat = 0 : dialog "RegisterRawInputDevices failed" : end

	; WM_INPUT (0x00FF) を oncmd でフック
	oncmd gosub *on_wm_input, 0x00FF

	pos 10, 90
	mes "Event Log:"
	log_y = 110

*main_loop
	wait 1
	redraw 1
	goto *main_loop

; ---------------------------------------------------------
; WM_INPUT ハンドラ
;   wparam : 0=RIM_INPUT / 1=RIM_INPUTSINK
;   lparam : HRAWINPUT handle
; ---------------------------------------------------------
*on_wm_input
	; サイズを問い合わせ
	dim sz, 1
	sz(0) = 0
	GetRawInputData lparam, RID_INPUT, 0, sz, 24   ; sizeof(RAWINPUTHEADER) = 24
	if sz(0) <= 0 : return

	; バッファ確保してデータ取得
	sdim buf, sz(0) + 16
	GetRawInputData lparam, RID_INPUT, varptr(buf), sz, 24

	; RAWINPUTHEADER:
	;   0:  DWORD  Type         (0=mouse,1=kbd,2=hid)
	;   4:  DWORD  Size
	;   8:  HANDLE hDevice      (8 byte on x64)
	;   16: WPARAM wParam       (8 byte on x64)
	dw_type = lpeek(buf, 0)
	if dw_type != 1 : return              ; keyboard 以外は無視
	hdev_lo = lpeek(buf, 8)
	hdev_hi = lpeek(buf, 12)

	; RAWKEYBOARD (offset 24):
	;   24: USHORT MakeCode
	;   26: USHORT Flags
	;   28: USHORT Reserved
	;   30: USHORT VKey
	;   32: UINT   Message   = WM_KEYDOWN / WM_KEYUP / WM_SYSKEYDOWN / WM_SYSKEYUP
	make_code = wpeek(buf, 24)
	kb_flags  = wpeek(buf, 26)
	vkey      = wpeek(buf, 30)
	kb_msg    = lpeek(buf, 32)

	; キーダウンのみ表示
	if (kb_msg != 0x100) & (kb_msg != 0x104) : return

	redraw 0
	color 0, 0, 0
	pos 10, log_y
	ch = ""
	if (vkey >= 'A') & (vkey <= 'Z') : ch = strf(" '%c'", vkey)
	if (vkey >= '0') & (vkey <= '9') : ch = strf(" '%c'", vkey)
	if vkey == 0x0D : ch = " [ENTER]"
	mes strf("  [Device=%08X:%08X] VK=0x%02X%s  (make=0x%02X flags=0x%02X)",
	         hdev_hi, hdev_lo, vkey, ch, make_code, kb_flags)
	log_y += 18
	if log_y > 500 {
		color 255, 255, 255
		boxf 10, 110, 710, 515
		color 0, 0, 0
		log_y = 110
	}
	return