お世話になります。標記の件について質問させてください。
現在、自分のプログラムで、仮想キーの送信を行いたいと思い、試しに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;
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がどういう感じに来てるか、確認してみてはどうでしょう?
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 で送信すると不具合が発生することがあります.
>ということはありません.
ただし,受信できるのは送信先のコントロールの OnKeyDown, OnKeyUP 等のイベント
処理内です.
WM_KEYDOWN, WM_KEYUP メッセージとしては受信できません.
WM_KEYDOWN, WM_KEYUP はメッセージキューにポストされたメッセーを検出します.
メッセージキューにポストするには PostMessage を使用します.
SendMessage で送信した場合は,メッセージキューにはポストされません.
最近,ある経過で以下のようなユニットを作成しました.
手前みそではありますが紹介させていただきます.コードが参考になれば.
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 等を使用します.
ごめんなさい.ソースコードは以下でした.
[ 08_ショートカットキー送信操作用ユニットのソースコード ]
http://mrxray.on.coocan.jp/Delphi/plSamples/508_SendCmdPrompt.htm#08
SendMessage と PostMessage については以下の記事と記事中のリンクを参考にしてくだい.
サンプルを大幅に追加しました ( ZIP 書庫には添付していません ).
[508] [ 12_キーバッファ ( メッセージキュー ) の処理 ]
http://mrxray.on.coocan.jp/Delphi/plSamples/508_SendCmdPrompt.htm#12
ツイート | ![]() |