喫茶XRAYトップページ

[スレッド全体
]

[13009] Re:キー押下のエミュレート返信 削除
2019/7/29 (月) 20:33:10 Mr.XRAY
WM_KEYDOWN 等は lParam の指定がないと単にキーコードを送信するだけです.
キーイベントとするには lParam の値を設定します.
Shift キー等の組み合わせの時はその情報を lParam に格納しておきます.
WM_KEYDOWN 等メッセージを受信した時に Shift キー等を検出するコードを書くことがあります.
そのことを思い出してください.
送信には PostMessage を使用します.

以下の ZIP ファイルは昔テストしたコードを整備したものです.
Swiss Delphi Center に掲載されていたコードを利用しています.
Swiss Delphi Center です.懐かしいと思う方がいるかも.
今日現在も記事が存在することを確認しました.

http://mrxray.on.coocan.jp/Delphi/zip/QandA_20190728_Emulate_KeyEvent.zip
(EXE + ソースコード.説明なし)

某掲示板の場合は以下のようになります.

//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  Memo1.Lines.Text := '日本語 ABC テスト XYZ';
  Memo1.SelStart := 7;
end;

//=============================================================================
//  PostMessage でキー操作を実行
//  単なるキーコードのポストではない
//=============================================================================
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  PostKeyExHWND(Memo1.Handle, VK_RETURN, [], False);
  Memo1.SelStart := 7;
end;

//=============================================================================
//  PostMessage でキー操作を実行
//  単なるキーコードのポストではない
//=============================================================================
procedure TForm1.SpeedButton2Click(Sender: TObject);
begin
  PostKeyExHWND(Memo1.Handle, VK_LEFT, [ssShift], False);
end;

正直なところ,keybd_event 関数を使用した方が簡単で確実です.
と思います.個人的には.


[13010] Re2:キー押下のエミュレート返信 削除
2019/7/29 (月) 20:35:35 Mr.XRAY
▼ Mr.XRAYさん

>  送信には PostMessage を使用します.

今回提示した程度のコードであれば SendMessage でも問題が発生することはないと思います.


[13011] Re2:キー押下のエミュレート返信 削除
2019/7/30 (火) 07:49:30 Mr.XRAY
> 某掲示板の場合は以下のようになります.

このサンプル (ZIP 書庫内の 02_Emulate_KeyEvent) は自アプリの TMemo に対する操作です.
プロセス超えの通信では正常に機能しません.
つまり,他のアプリに対して WM_KEYDOWN, WM_KEYUP メッセージを使用しての
キー押下エミュレートはできません (コード内にもコメントがあります).
これが可能であれば,以下のような方法を使わなくても済みます.

[670] [ 06_メモ帳へのコマンド送信 ]
http://mrxray.on.coocan.jp/Delphi/plSamples/670_SendTextThreadAttach.htm#06

ということで,

> keybd_event 関数を使用した方が簡単で確実です.

ということでございます.
他のアプリの操作というのは難しいのです.

[ 他のアプリへ文字列送信と取得 ]
http://mrxray.on.coocan.jp/Delphi/plSamples/670_SendTextThreadAttach.htm#00

ということです.


[13012] Re3:キー押下のエミュレート返信 削除
2019/7/30 (火) 12:03:05 Mr.XRAY
> プロセス超えの通信では正常に機能しません.

キー操作の情報はキーバッファに格納されます.
このバッファはメモリです.
他のアプリ,つまり他のプロセスから見れば送信側のプロセスのメモリです.
したがって,他のアプリからはキー押下としての情報処理が正しくできないことがあります.
キーコードそのものは他のアプリでも取得できます.

このことから SendMessage ではキー押下としての処理ができないことがあります.

http://chokuto.ifdef.jp/urawaza/message/WM_KEYDOWN.html

に lParam の詳しい説明がありますが,この説明にしたがって lParam の値を設定すれば
キー押下としての情報がバッファに格納されるわけではありません.
PostKeyExHWND 関数のコードのように,意図的にバッファに情報を格納する必要があります.


[13013] Re4:キー押下のエミュレート返信 削除
2019/7/31 (水) 09:37:49 Mr.XRAY
>http://mrxray.on.coocan.jp/Delphi/zip/QandA_20190728_Emulate_KeyEvent.zip
>(EXE + ソースコード.説明なし)


ものはついてですので keybd_event 関数を使用したサンプルを追加しておきました.


//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  Memo1.Lines.Text := '日本語 ABC テスト XYZ';
  Memo1.SelStart := 7;
end;

//=============================================================================
//  keybd_event 関数を使用したキー操作のエミュレート
//  [Enter]
//=============================================================================
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  Memo1.SetFocus;

  keybd_event(VK_RETURN, 0, 0, 0);
  keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0);
end;

//=============================================================================
//  keybd_event 関数を使用したキー操作のエミュレート
//  [Shift] + [←]
//=============================================================================
procedure TForm1.SpeedButton2Click(Sender: TObject);
begin
  Memo1.SetFocus;

  keybd_event(VK_SHIFT, 0, 0, 0);
  keybd_event(VK_LEFT,  0, KEYEVENTF_EXTENDEDKEY, 0);
  keybd_event(VK_LEFT,  0, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);
  keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
end;


[13014] 他のアプリへのキー操作を送信返信 削除
2019/7/31 (水) 12:38:19 Mr.XRAY
受信側のアプリも自分で開発する場合であれば,
他のアプリにフォーカスを移動しないで,
他のアプリへキー操作を送信する方法が全くないわけではありません.

[650] [02_レコード型の場合]
http://mrxray.on.coocan.jp/Delphi/plSamples/650_SendText.htm#02

のサンプルの方法が使用できます.
送信側は例えば以下のようします.
テータを受け取ったアプリ側では,このデータを元に WM_KEYDOWN, WM_KEYUP メッセージを
目的のコントロールに PostMessage します.
これも UP した ZIP 書庫に追加しておきました.


type
  TKeyDataInfo = record
    Key  : Byte;
    shift: TShiftState
  end;

//=============================================================================
//  キー押下データの送信
//  [Enter]
//=============================================================================
procedure TSenderForm.Button1Click(Sender: TObject);
var
  LKeyData  : TKeyDataInfo;
  LCopyDS   : TCopyDataStruct;
  LhWindow  : HWND;
begin
  LKeyData.Key   := VK_RETURN;
  LKeyData.shift := [];

  //受取る側のウィンドウハンドル
  LhWindow := FindWindow('TReceivForm', nil);
  if LhWindow = 0 then exit;

  LCopyDS.dwData := 1234; //適当な値
  LCopyDS.cbData := SizeOf(LKeyData);
  LCopyDS.lpData := Addr(LKeyData);

  SendMessage(LhWindow, WM_COPYDATA, Handle, LPARAM(Addr(LCopyDS)));
end;

//=============================================================================
//  キー押下データの送信
//  [Shft] + [←]
//=============================================================================
procedure TSenderForm.Button2Click(Sender: TObject);
var
  LKeyData  : TKeyDataInfo;
  LCopyDS   : TCopyDataStruct;
  LhWindow  : HWND;
begin
  LKeyData.Key   := VK_LEFT;
  LKeyData.shift := [ssShift];

  //受取る側のウィンドウハンドル
  LhWindow := FindWindow('TReceivForm', nil);
  if LhWindow = 0 then exit;

  LCopyDS.dwData := 1234; //適当な値
  LCopyDS.cbData := SizeOf(LKeyData);
  LCopyDS.lpData := Addr(LKeyData);

  SendMessage(LhWindow, WM_COPYDATA, Handle, LPARAM(Addr(LCopyDS)));
end;


[▼次のスレッド]
INCM/CMT
Cyclamen v3.82