仮想キーコードの送信方法


mk  2019-07-29 06:13:06  No: 49838

お世話になります。標記の件について質問させてください。
  現在、自分のプログラムで、仮想キーの送信を行いたいと思い、試しにTMemoに
エンターキーやShift+左キーを送信するプログラムを以下のように書きま
した。ですが、エンターキーは送信されません。また、左キーはShiftキー
が押されない状態のまま(範囲選択がなされず)、単にカーソルが左に1個
ずれるだけになってしまいます。どのようにすれば、意図どおりに動くで
しょうか。

※キー送信の合間に別の処理を挟みたいので、PostMessageの使用は考えて
  おりません。(処理の順番が狂ってしまうため)
  また、アプリケーションは必ずしもアクティブな状態になっているわけ
  ではありませんので、Keybd_eventの使用は考えておりません。

※WM_KeyDownの代わりにWM_IME_CHARを使うようなことを書いているサイト
  もありましたが、現状ではよく理解できておりません。

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  SendMessage(Memo1.Handle, WM_KeyDown, VK_Return,  0);
  SendMessage(Memo1.Handle, WM_KeyUp,   VK_Return,  0);
end;

procedure TForm1.SpeedButton2Click(Sender: TObject);
begin
  SendMessage(Memo1.Handle, WM_KEYDOWN, VK_Shift, 0);
  SendMessage(Memo1.Handle, WM_KeyDown, VK_LEFT,  0);
  SendMessage(Memo1.Handle, WM_KeyUp,   VK_LEFT,  0);
  SendMessage(Memo1.Handle, WM_KEYUP,   VK_Shift, 0);
end;


通りすがり  2019-07-29 06:52:15  No: 49839

LParamちゃんと入れないとだめとかですかね?

WM_KEYDOWN message - Windows applications | Microsoft Docs
https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-keydown

WM_KEYUP message - Windows applications | Microsoft Docs
https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-keyup

とりあえずMemo1のWndProc乗っ取って、普通にキーボードから入力したときにWM_KEYDOWN/WM_KEYUP/WM_CHARがどういう感じに来てるか、確認してみてはどうでしょう?


Mr.XRAY  2019-08-01 01:54:09  No: 49840

Keybd_event 関数は物理的なキー操作をエミュレートします.一方,

PostMessage(Memo1.Handle, WM_KEYDOWN, VK_Shift, 0); 
PostMessage(Memo1.Handle, WM_KeyDown, VK_LEFT,  0); 

というコードは単に,指定したウィンドウにキーコードを送信しているだけです.
つまり,

>エンターキーは送信されません。

ということはありません.
Enter キーの操作としては動作しませんが,VK_RETURN というコードは
間違いなく送信されています.よく確認してください.
「送信」と「機能の実行」とは全く意味が違います.

[Shift] + [←] というキー操作を送信したいのであれば.
WM_KEYDOWN, WM_KEYUP の lParam 引数の値を設定することはもちろんですが,
[←] キーを押下した時に [Shift] キーも押下しているというという情報を
キーバッファに書き込みます.
自分でコーディングしなくても Torry's DelphiCenter にコードがあります.
昔のコードですが十分使えます.

[...simulate the pressing of keyboard keys?]
https://www.swissdelphicenter.ch/en/showcode.php?id=220

そのコードにある PostKeyExHWND という関数を使用すると,例えば以下のように書けます.
(動作確認は Windows 7 U64(SP1) + Delphi xE5(UP2) Pro VCL-32)

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  PostKeyExHWND(Memo1.Handle, VK_RETURN, [], False);
end;

procedure TForm1.SpeedButton2Click(Sender: TObject);
begin
  PostKeyExHWND(Memo1.Handle, VK_LEFT, [ssShift], False);
end;

※ 一般的に,[Shift] キー等が押下されているかは TKeyboardState あるいは 
※ GetKeyState 関数等でキーバッファの情報を調べます.
※ WM_KEYDOWN, WM_KEYUP を SendMessage で送信すると不具合が発生することがあります.


Mr.XRAY  2019-08-01 16:55:11  No: 49841

>ということはありません. 

ただし,受信できるのは送信先のコントロールの OnKeyDown, OnKeyUP 等のイベント
処理内です.
WM_KEYDOWN, WM_KEYUP メッセージとしては受信できません.

WM_KEYDOWN, WM_KEYUP はメッセージキューにポストされたメッセーを検出します.
メッセージキューにポストするには PostMessage を使用します.
SendMessage で送信した場合は,メッセージキューにはポストされません.


Mr.XRAY  2021-08-17 19:02:20  No: 149815

最近,ある経過で以下のようなユニットを作成しました.
手前みそではありますが紹介させていただきます.コードが参考になれば.
Windows API の keybd_event または SendInput 関数を使用しています.

[ 07_ショートカットキー送信操作用ユニット ]
http://mrxray.on.coocan.jp/Delphi/plSamples/508_SendCmdPrompt.htm#07

2 年前にレスしたように,たとえ自アプリであっても,
キー操作に WM_KEYDOWN, WM_KEYUP を使用するのは面倒です.

> PostMessageの使用は考えて
>  おりません。(処理の順番が狂ってしまうため) 

キー操作には PostMessage を使用します.キー操作はメッセージキューを使用するので.
自アプリ (正確には自スレッド) が対象でしたら,
メッセージキューの処理に Application.ProcessMessages が使用できます.
他のアプリへのキー送信では Sleep 等を使用します.


Mr.XRAY  2021-08-17 19:08:57  No: 149816

ごめんなさい.ソースコードは以下でした.

[ 08_ショートカットキー送信操作用ユニットのソースコード ]
http://mrxray.on.coocan.jp/Delphi/plSamples/508_SendCmdPrompt.htm#08


Mr.XRAY  2021-08-22 17:04:31  No: 149819

SendMessage と PostMessage については以下の記事と記事中のリンクを参考にしてくだい.
サンプルを大幅に追加しました ( ZIP 書庫には添付していません ).

[508] [ 12_キーバッファ ( メッセージキュー ) の処理 ]   
http://mrxray.on.coocan.jp/Delphi/plSamples/508_SendCmdPrompt.htm#12


※返信する前に利用規約をご確認ください。








  このエントリーをはてなブックマークに追加