〜 インプット 〜
キーを自動的に送信2 (要USER32.DLL)

「キーボード内のどのキーが押されたか」は、stick命令やgetkey命令、onkey命令で取得出来ますが、
逆の「キーボード内のいずれかのキーを押す」命令はHSPの標準命令に用意されていませんので、
従来はコチラで紹介したAPIkeybd_event関数でキーを送信する方法が使われました。
ただ、この関数は少々古く、ウィンドウズ2000頃からはSendInput関数の利用が推奨されていますので、
当ページではSendInput関数を使ったサンプルを書いています。

SendInput関数は、動作イベントを複数個指定することができるので、
同時にキーを操作したり、マウスを一連の動作で制御する場合に役立つのではないでしょうか?
UINT SendInput {
DWORDnInputs,// イベント数
LPINPUTpInputs,// 入力イベントINPUT構造体の配列
intcbSize// 構造体サイズ
};
具体的な指定方法はサンプルを見ていただきたいのですが、 例えば1つのキーしか送信しない場合、SendInput関数の第1引数に指定するイベント数は。 第2引数のイベント配列の説明は後に回すとして、第3引数の構造体サイズは少し注意する必要があります。 キーボードからの入力の場合は上記KEYBDINPUT構造体(2+2+4+4+4)を使用するので、 INPUT構造体のサイズはタイプ値の4バイトと合わせて20バイトになるわけですが、 SendInput関数はキーボードからだけでなく、マウスやハードウェアからの入力にも使われる共用体で、 INPUT構造体の中で一番大きなMOUSEINPUT構造体28バイトを指定する必要があります。
Type INPUT {
DWORDtypes// 入力タイプ(ココでは KEYBDINPUT 構造体を指定)
union {
MOUSEINPUTmi,// INPUT_MOUSE(=0x00) の場合に使用
KEYBDINPUTki,// INPUT_KEYBOARD(=0x01) の場合に使用
HARDWAREINPUThi,// INPUT_HARDWARE(=0x02) の場合に使用
};
};
イベント配列であるSendInput関数の第2引数にはINPUT構造体を用いますが、 INPUT構造体のメンバ1は今回キーボードを使用と言うことで、INPUT_KEYBOARD(=0x01)を使用します。
定数コード内容
INPUT_MOUSE0x00マウスイベントを発生
INPUT_KEYBOARD0x01キーボードイベントを発生
INPUT_HARDWARE0x02ハードウェアイベントを発生
メンバ2はこれから説明するKEYBDINPUT構造体を選択します。
Type KEYBDINPUT {
WORDwVK,// 仮想キーコード
WORDwScan,// ハードウェアスキャンコード
DWORDdwFlags,// 関数のオプション
DWORDtime,// ミリ秒単位のタイムスタンプ
DWORDdwExtraInfo// 追加のキーストロークデータ
};
KEYBDINPUT構造体に指定するものはコチラで紹介したkeybd_event関数と似ており、 構造体のメンバ1である仮想キーには以下のコードを使用します。
定数コードキー内容
16進10進
VK_LBUTTON0x011マウス左ボタン
VK_RBUTTON0x022マウス右ボタン
VK_CANCEL0x033[Cancel]
VK_MBUTTON0x044マウス中央ボタン
VK_BACK0x088[Back space]
VK_TAB0x099[Tab]
VK_CLEAR0x0C12[Clear]
VK_RETURN0x0D13[Enter]
VK_SHIFT0x1016[Shift]
VK_CONTROL0x1117[Ctrl]
VK_MENU0x1218[Alt]
VK_PAUSE0x1319[Pause]
VK_CAPITAL0x1420[Caps Lock]
VK_KANA0x1521IMEカナモード
VK_KANJI0x1925IME漢字モード
VK_ESCAPE0x1B27[Esc]
VK_CONVERT0x1C28IME変換
VK_NONCONVERT0x1D29IME無変換
VK_MODECHANGE0x1F31IMEモード変更
VK_SPACE0x2032スペースキー
VK_PRIOR0x2133[Page Up]
VK_NEXT0x2234[Page Down]
VK_END0x2335[End]
VK_HOME0x2436[Home]
VK_LEFT0x2537[←]
VK_UP0x2638[↑]
VK_RIGHT0x2739[→]
VK_DOWN0x2840[↓]
VK_SELECT0x2941[Select]
VK_PRINT0x2A42[Print]
VK_EXECUTE0x2B43[Execute]
VK_SNAPSHOT0x2C44[Print Screen]
VK_INSERT0x2D45[Insert]
VK_DELETE0x2E46[Delete]
VK_HELP0x2F47[Help]
VK_00x3048[0]
VK_10x3149[1]
VK_20x3250[2]
VK_30x3351[3]
VK_40x3452[4]
VK_50x3553[5]
VK_60x3654[6]
VK_70x3755[7]
VK_80x3856[8]
VK_90x3957[9]
VK_A0x4165[A]
VK_B0x4266[B]
VK_C0x4367[C]
VK_D0x4468[D]
VK_E0x4569[E]
VK_F0x4670[F]
VK_G0x4771[G]
VK_H0x4872[H]
VK_I0x4973[I]
VK_J0x4A74[J]
VK_K0x4B75[K]
VK_L0x4C76[L]
VK_M0x4D77[M]
VK_N0x4E78[N]
VK_O0x4F79[O]
VK_P0x5080[P]
VK_Q0x5181[Q]
VK_R0x5282[R]
VK_S0x5383[S]
VK_T0x4584[T]
VK_U0x5585[U]
VK_V0x5686[V]
VK_W0x5787[W]
VK_X0x5888[X]
VK_Y0x5989[Y]
VK_Z0x5A90[Z]
VK_LWIN0x5B91左ウィンドウズ [ÿ]
VK_RWIN0x5C92右ウィンドウズ [ÿ]
VK_APPS0x5D93アプリケーション
VK_SLEEP0x5F95[Sleep]
VK_NUMPAD00x6096テンキー [0]
VK_NUMPAD10x6197テンキー [1]
VK_NUMPAD20x6298テンキー [2]
VK_NUMPAD30x6399テンキー [3]
VK_NUMPAD40x64100テンキー [4]
VK_NUMPAD50x65101テンキー [5]
VK_NUMPAD60x66102テンキー [6]
VK_NUMPAD70x67103テンキー [7]
VK_NUMPAD80x68104テンキー [8]
VK_NUMPAD90x69105テンキー [9]
VK_MULTIPLY0x6A106テンキー [*]
VK_ADD0x6B107テンキー [+]
VK_SEPARATOR0x6C108テンキー [Enter]
VK_SUBTRACT0x6D109テンキー [-]
VK_DECIMAL0x6E110テンキー [.]
VK_DIVIDE0x6F111テンキー [/]
VK_F10x70112[F1]
VK_F20x71113[F2]
VK_F30x72114[F3]
VK_F40x73115[F4]
VK_F50x74116[F5]
VK_F60x75117[F6]
VK_F70x76118[F7]
VK_F80x77119[F8]
VK_F90x78120[F9]
VK_F100x79121[F10]
VK_F110x7A122[F11]
VK_F120x7B123[F12]
VK_F130x7C124[F13]
VK_F140x7D125[F14]
VK_F150x7E126[F15]
VK_F160x7F127[F16]
VK_F170x80128[F17]
VK_F180x81129[F18]
VK_F190x82130[F19]
VK_F200x83131[F20]
VK_F210x84132[F21]
VK_F220x85133[F22]
VK_F230x86134[F23]
VK_F240x87135[F24]
VK_NUMLOCK0x90144[Num Lock]
VK_SCROLL0x91145[Scroll Lock]
定数コードキー内容
16進10進
VK_XBUTTON10x055マウスX1ボタン
VK_XBUTTON20x066マウスX2ボタン
VK_BROWSER_BACK0xA6166ブラウザー [戻る]
VK_BROWSER_FORWARD0xA7167ブラウザー [次へ]
VK_BROWSER_REFRESH0xA8168ブラウザー [更新]
VK_BROWSER_STOP0xA9169ブラウザー [中止]
VK_BROWSER_SEARCH0xAA170ブラウザー [検索]
VK_BROWSER_FAVORITES0xAB171ブラウザー [お気に入り]
VK_BROWSER_HOME0xAC172ブラウザー [ホーム]
VK_VOLUME_MUTE0xAD173ボリューム [ミュート]
VK_VOLUME_DOWN0xAE174ボリューム [ダウン]
VK_VOLUME_UP0xAF175ボリューム [アップ]
VK_MEDIA_NEXT_TRACK0xB0176メディア [次のトラック]
VK_MEDIA_PREV_TRACK0xB1177メディア [前のトラック]
VK_MEDIA_STOP0xB2178メディア [停止]
VK_MEDIA_PLAY_PAUSE0xB3179メディア [開始・停止]
VK_LAUNCH_MAIL0xB4180[メール開始]
VK_LAUNCH_MEDIA_SELECT0xB5181[メディア選択]
VK_LAUNCH_APP10xB6182[アプリケーション1起動]
VK_LAUNCH_APP20xB7183[アプリケーション2起動]
 ※上記一覧はウィンドウズ2000以降で有効
メンバ2は第1引数の仮想キーを元にしたハードウェアスキャンコードを指定します。 スキャンコードはAPIMapVirtualKey関数の第1引数に仮想キーコード、第2引数に指定で変換できます。
UINT MapVirtualKey {
DWORDcode,// 仮想キーコードまたはスキャンコード
DWORDtype// 実行したい変換の種類(仮想キーごとからスキャンコードへの変換は0)
};
コレら2つのメンバはいずれも2バイトなので、「wVK + (wScan << 16)」と1つにまとめてください。 メンバ3はキーストロークに加えるオプションを指定します。 尚、KEYEVENTF_KEYUP(=0x02)を指定しないときはキーの押し下げとなります。
定数コードキー内容
KEYEVENTF_EXTENDEDKEY0x01仮想キーを使わず拡張キーを使用
KEYEVENTF_KEYUP0x02キーの押し下げを解除
KEYEVENTF_SCANCODE0x04仮想キーは無視されハードウェアスキャンコード側を有効
KEYEVENTF_UNICODE0x08スキャンコードにUniCodeを使用
KEYBDINPUT構造体メンバ4はミリ秒単位のタイムスタンプを指定する要素となりますが、 どうやらこのメンバは無視されるとのことですので、としておきましょう。 メンバ5も、通常利用する分には使用しませんので、としておきましょう。 尚、下記サンプルではコチラの1キーずつ操作するやり方とは違って、 操作キーを配列変数に一括指定して一度に実行するやり方となっています。 先に押されたキーは押したままで最後のキーを押した後に、 一番先のキーから順に離していく形をとっているので、明示的に押したキーを離す処理は必要はありません。 モジュールに送るパラメータにオプション用パラメータは用意していないので、 オプションを設定する時は、キーコードに「上記のオプションコード値の1000倍」を加算してください。 例えば、シフトキーコードを解除する時は2000を足して2016を渡すということです。 また、HSP2側では配列変数の要素サイズ取得の為、 HSP3以降のlength命令に相当するコチラで紹介した命令を内部で使用しています。 命令の詳細はココでは紹介しないので、コチラを参照してください。

getdiminfo 変数, 次元
変数指定変数、指定次元のサイズがstatにセットされる。
次元1次元目を0として、取得する次元を0〜3のいずれかで指定する。

setkeys コード一覧
コード 制御する仮想キーコード一覧を格納した配列変数を指定する。
尚、内部でgetdiminfo命令を使用しているため、getdiminfo命令を先に定義すること。
キーストローク追加オプションを付加するには、キーコードに以下の値を加算する。
拡張キーを使用+1000
キー押し下げを解除+2000
スキャンコードを有効化+4000
UniCodeを使用+8000

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
	ll_libload user, "user32.dll"
	ll_getproc SendInput, "SendInput", user
	ll_getproc MapVirtualKey, "MapVirtualKeyA", user

#module
#deffunc getdiminfo val, int
	mref pval, 1024 : mref dnum, 1
	mref stt, 64
	stt = dnum + 2
	stt = pval.stt
	if (pval & $FFFF = 2) && (dnum = 0) : stt = stt * 4 
	return

#deffunc setkeys val
	mref code, 48
	getdiminfo code
	length = stat
	dim inputs, length * 7
	repeat length
		i = cnt * 7
		prm = code.cnt \ 1000, 0
		ll_callfunc prm, 3, MapVirtualKey@
		ll_ret i.1
		inputs.i = 0x01, (code.cnt \ 1000) + (i.1 << 16), code.cnt / 1000
	loop
	prm = length, 0, 28
	ll_getptr inputs : ll_ret prm.1
	ll_callfunc prm, 3, SendInput@
	repeat length
		i = cnt * 7 + 2
		inputs.i = 0x02
	loop
	ll_callfunc prm, 3, SendInput@
	return
#global

	exec "notepad"
	dim keys, 8
	keys = 'U', 'L', 'T', 'I', 'M', 'A', 'T', 'E'
	setkeys keys

setkeys コード一覧
コード 制御する仮想キーコード一覧を格納した配列変数を指定する。
キーストローク追加オプションを付加するには、キーコードに以下の値を加算する。
拡張キーを使用+1000
キー押し下げを解除+2000
スキャンコードを有効化+4000
UniCodeを使用+8000

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#uselib "user32.dll"
#func  global SendInput "SendInput" int, var, int
#cfunc global MapVirtualKey "MapVirtualKeyA" int, int

#module
#deffunc setkeys array code, local inputs
	dim inputs, length(code) * 7
	foreach code
		inputs(cnt * 7) = 0x01, (code.cnt \ 1000) + (MapVirtualKey(code.cnt \ 1000, 0) << 16), code.cnt / 1000
	loop
	SendInput length(code), inputs, 28
	foreach code : inputs(cnt * 7 + 2) = 0x02 : loop
	SendInput length(code), inputs, 28
	return
#global

	exec "notepad"
	keys = 16, 'U', 'L', 'T', 'I', 'M', 'A', 'T', 'E' // 16 = Shiftキーで以降の文字は大文字
	setkeys keys
	end