質問
2010年12月16日木曜日 0:35
いつもお世話になります。
64ビットWindows 上で、たとえば、HOME と SHIFT;END を他のプログラムへ送って行全体を選択状態にしたいのですが、SHIFT キーが無視されてしまいます。
ターゲットプログラムはメモ帳など、外部プログラムです。
VK_HOME
VK_SHIFT
VK_END
と順に送り出してやると、32ビットプログラムでは正常に HOME, SHIFT;END の動作が実行されます。
(実際にはこの後、逆の順で KEY_UP を送ります。)
ところが 64bit Windows上で、実際に受け取るメッセージを確認すると次のようになっています。
WM_KEYDOWN VK_HOME
WM_KEYUP VK_HOME
WM_KEYDOWN VK_SHIFT
WM_KEYUP VK_SHIFT
WM_KEYDOWN_VK_END
WM_KEYDOWN VK_SHIFT
WM_KEYUP VK_END
WM_KEYUP VK_SHIFT
どうやら VK_END を送ると自動的に VK_SHIFT の DOWN/UP が前後に付加されるようです。
これを無視して SHIFT;VK_END を送り出したいのですが、何か解決策は無いでしょうか?
すべての返信 (6)
2010年12月17日金曜日 1:57 ✅回答済み | 1 票
Visual Studio 2010 で作った 32bit アプリを Windows 7 x64 の上で試しているので動きは違ってしまうかもしれませんが、私が試したコードです。
(そこらにあったやつを再利用したので、構造体への設定値についてはあまり吟味していません。)
INPUT input[4];
input[0].type = INPUT_KEYBOARD;
input[0].ki.wScan = MapVirtualKey(VK_SHIFT, 0);
input[0].ki.time = 0;
input[0].ki.dwExtraInfo = GetMessageExtraInfo();
input[0].ki.wVk = VK_SHIFT;
input[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
input[1].type = INPUT_KEYBOARD;
input[1].ki.wScan = MapVirtualKey(VK_END, 0);
input[1].ki.time = 0;
input[1].ki.dwExtraInfo = GetMessageExtraInfo();
input[1].ki.wVk = VK_END;
input[1].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
input[2].type = INPUT_KEYBOARD;
input[2].ki.wScan = MapVirtualKey(VK_END, 0);
input[2].ki.time = 0;
input[2].ki.dwExtraInfo = GetMessageExtraInfo();
input[2].ki.wVk = VK_END;
input[2].ki.dwFlags = KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP;
input[3].type = INPUT_KEYBOARD;
input[3].ki.wScan = MapVirtualKey(VK_SHIFT, 0);
input[3].ki.time = 0;
input[3].ki.dwExtraInfo = GetMessageExtraInfo();
input[3].ki.wVk = VK_SHIFT;
input[3].ki.dwFlags = KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP;
SendInput(4, input, sizeof(INPUT));
2010年12月16日木曜日 3:47
手元に x64 版がないので試せないのですが、そもそも、キー操作をどのような手段で送られていますか?
何かのクラスライブラリを使われていると最終的にどうやっているかは不明かもしれませんが、キー操作ではキー操作を1つづつ送信するため、割り込みや分割がありうるという問題がある旧式の keybd_event と、操作を一括して送信する SendInput の2つが有名どころです。
2010年12月16日木曜日 6:06
スレッドのタイトルに SendInput とあるので、手元の Windows 7 x64 でやってみました。
特に問題なく SHIFT;END を送れているように思います。
・INPUT を 4 個の配列で準備
・INPUT[0] = VK_SHIFT, KEYDOWN (dwFlags=0)
・INPUT[1] = VK_END, KEYDOWN
・INPUT[2] = VK_END, KEYUP
・INPUT[3] = VK_SHIFT, KEYUP
・SendInput で 4 つをいっぺんに送信
64bit アプリでも 32bit アプリ (WOW64) でも同じ動きになりました。(メモ帳で 1 行が選択された状態になりました。)
2010年12月17日金曜日 0:57
ありがとうございます。
送信元は VC 6 で作成した 32 bit プログラムです。
元が32bit だからなのかも知れません。
手順は SendInput でまとめて同じ様に送っています。
2010年12月17日金曜日 1:28
一度 HOME のみを送信し、次に SHIFT;END を送信しています。
SHIFT;END の送信部分を抜き出すと次のようになっています。
INPUT inp[30]; ' 多めに取っているだけ
memset( &inp,0,sizeof inp );
UINT n = 0;
inp[n].type = INPUT_KEYBOARD;
inp[n].ki.wVk = VK_SHIFT;
inp[n].ki.wScan = MapVirtualKey( VK_SHIFT, 0 );
n;;;
inp[n].type = INPUT_KEYBOARD;
inp[n].ki.wVk = VK_END;
inp[n].ki.wScan = MapVirtualKey( VK_END, 0 );
n;;;
inp[n].type = INPUT_KEYBOARD;
inp[n].ki.wVk = VK_END;
inp[n].ki.wScan = MapVirtualKey( VK_END, 0 );
inp[n].ki.dwFlags = KEYEVENTF_KEYUP;
n;;;
inp[n].type = INPUT_KEYBOARD;
inp[n].ki.wVk = VK_SHIFT;
inp[n].ki.wScan = MapVirtualKey( VK_SHIFT, 0 );
inp[n].ki.dwFlags = KEYEVENTF_KEYUP;
n;;;
n -= SendInput(n,&inp[0],sizeof (INPUT));
2010年12月17日金曜日 3:19
ありがとうございます。
ExtraInfo を追加したところ 64bit の 2008Server R2 でメモ帳への出力を確認できました。
ExtraInfo の内容自体が不明なのと、32bit-Windows と 64bit-Windows の動作に違いがあるのがわかりませんが、これでチェックしてみて、動作すれば良しとします。
お世話になりました m(_ _)m