0

私は、さまざまなボットやその他の GUI 自動化プログラムのキーボード プレス イベントをシミュレートすることにしばしば苦労しました。

以下を使用して、キーダウンイベントをシミュレートできました。

INPUT[] kInput = new INPUT[1];
kInput[j].type = SendInputEventType.InputKeyboard;
kInput[j].mkhi.ki.wVk = 0;
kInput[j].mkhi.ki.wScan = (ushort) MapVirtualKey((uint) Keys.D5, 0);
kInput[j].mkhi.ki.dwFlags = KeyboardEventFlags.SCANCODE;
kInput[j].mkhi.ki.time = 0;
kInput[j].mkhi.ki.dwExtraInfo = IntPtr.Zero;
SendInput(1, kInput, Marshal.SizeOf(typeof(INPUT)));

また

INPUT[] kInput = new INPUT[1];
kInput[1].type = SendInputEventType.InputKeyboard;
kInput[1].mkhi.ki.wVk = '5';
kInput[1].mkhi.ki.wScan = 0;
kInput[1].mkhi.ki.dwFlags = 0;
kInput[1].mkhi.ki.time = 0;
kInput[1].mkhi.ki.dwExtraInfo = IntPtr.Zero;
SendInput(1, kInput, Marshal.SizeOf(typeof(INPUT)));

および以下を使用したキーアップ イベント:

kInput[1].type = SendInputEventType.InputKeyboard;
kInput[1].mkhi.ki.wVk = 0;
kInput[1].mkhi.ki.wScan = (ushort)MapVirtualKey((uint)Keys.D5, 0);
kInput[1].mkhi.ki.dwFlags = KeyboardEventFlags.KEYUP;
kInput[1].mkhi.ki.time = 0;
kInput[1].mkhi.ki.dwExtraInfo = IntPtr.Zero;
SendInput(1, kInput, Marshal.SizeOf(typeof(INPUT)));

また

kInput[1].type = SendInputEventType.InputKeyboard;
kInput[1].mkhi.ki.wVk = '5';
kInput[1].mkhi.ki.wScan = 0;
kInput[1].mkhi.ki.dwFlags = KeyboardEventFlags.KEYUP;
kInput[1].mkhi.ki.time = 0;
kInput[1].mkhi.ki.dwExtraInfo = IntPtr.Zero;
SendInput(1, kInput, Marshal.SizeOf(typeof(INPUT)));

そして、私の試みは2つを次のように組み合わせようとしています:

//key down
INPUT kInput = new INPUT[2];
kInput[0].type = SendInputEventType.InputKeyboard;
kInput[0].mkhi.ki.wVk = 0;
kInput[0].mkhi.ki.wScan = (ushort) MapVirtualKey((uint) Keys.D5, 0);
kInput[0].mkhi.ki.dwFlags = KeyboardEventFlags.SCANCODE;
kInput[0].mkhi.ki.time = 0;
kInput[0].mkhi.ki.dwExtraInfo = IntPtr.Zero;

//Key Up
kInput[1].type = SendInputEventType.InputKeyboard;
kInput[1].mkhi.ki.wVk = 0;
kInput[1].mkhi.ki.wScan = (ushort)MapVirtualKey((uint)Keys.D5, 0);
kInput[1].mkhi.ki.dwFlags = KeyboardEventFlags.KEYUP;
kInput[1].mkhi.ki.time = 0;
kInput[1].mkhi.ki.dwExtraInfo = IntPtr.Zero;

//sendinput
SendInput(1, kInput, Marshal.SizeOf(typeof(INPUT)));

さまざまな程度の成功を収めてきましたが、DirectX (またはその他の 3D) ゲームが物理キーボードを使用した人間とまったく同じように私の入力を見るキーホールド/プレスイベントを実際にエミュレートすることはできませんでした...

SendInput を使用して、DirectX ゲームで見られるキーのプレス/ホールド イベントをどのようにエミュレートしますか?

4

2 に答える 2

3

directX ゲームでキーボード イベントをシミュレートするには、キーボード ドライバーのラッパーが必要です。私は同じ問題を抱えていましたが、このメソッド (SendInput、SendKeys クラス) のどちらも役に立ちません。このラッパーを使用してみてください。私には成功しました。

于 2014-03-19T06:56:03.750 に答える
1

現在、これの多くは、実際には、「だまそう」としているゲーム/3D アプリケーションの詳細に依存していると思います。

私が取り組んでいた特定のゲームをだまそうとした最初の試みのいくつかの奇妙なケースでは、ゲームウィンドウ自体がフォーカスを取り戻している限り、スキルを切り替えるのに十分なキープレスとして単一の SCANCODE を受け入れるだけでした。(つまり、Web ブラウザを開いていると、アプリケーションがゲーム ウィンドウに切り替わり、SCANCODE イベントが発生します)。

ただし、奇妙な理由で、ウィンドウがフォーカスを取り戻した後、初めてこれを機能させることができましたが、その後、イベントを繰り返し発生させることができませんでした。

これには戸惑いましたが、最終的には、「キーストロークの繰り返しは、Windows や SendInput ではなく、キーボード コントローラーの機能です。SendInput() を繰り返し呼び出して、タイマーでエミュレートできます。」という投稿にたどり着き ました。

これにより、1 つのキーストロークまたは 2 つの入力 (1 つの拡張キーを押し下げ、もう 1 つのキーを押し上げる) だけを送信する代わりに、ハードウェア デバイスが行うかもしれない方法で入力のストリームを送信しようとしない理由がわかりました (これは私はしません)。実際にそうであるかどうかは確かですが、当時はすべて良い考えのように思えました)

最終的に、失敗がありました (主に X 量の単一の INPUT 1を送信しようとしました)、私が思いついたのはこれでした:

INPUT[] kInput = new INPUT[30];
for (int j = 0; j < kInput.Length - 1; j++)
{
    //activate skill
    //INPUT[] kInput = new INPUT[2];
    kInput[j].type = SendInputEventType.InputKeyboard;
    kInput[j].mkhi.ki.wVk = 0;
    kInput[j].mkhi.ki.wScan = (ushort) MapVirtualKey((uint) Keys.D5, 0);
    kInput[j].mkhi.ki.dwFlags = KeyboardEventFlags.SCANCODE;
    kInput[j].mkhi.ki.time = 0;
    kInput[j].mkhi.ki.dwExtraInfo = IntPtr.Zero;
}
kInput[kInput.Length - 1].type = SendInputEventType.InputKeyboard;
kInput[kInput.Length - 1].mkhi.ki.wVk = 0;
kInput[kInput.Length - 1].mkhi.ki.wScan = (ushort)MapVirtualKey((uint)Keys.D5, 0);
kInput[kInput.Length - 1].mkhi.ki.dwFlags = KeyboardEventFlags.KEYUP;
kInput[kInput.Length - 1].mkhi.ki.time = 0;
kInput[kInput.Length - 1].mkhi.ki.dwExtraInfo = IntPtr.Zero;
SendInput((uint)kInput.Length, kInput, Marshal.SizeOf(typeof(INPUT)));

そして、これは、私が現在「だまそうと」しているゲームでは十分に機能するようです。これは、人間がキーを保持する方法で SendInput を使用して保持されているキーをシミュレートできたのは初めてです。

ここで、私の例では、入力配列のサイズが 30 であることに注意してください。これは 30 ではありません。これは、30 が何らかの魔法の値であるためです。30 は、希望する結果を得るために選択しなければならなかった最初で唯一の数値であるためです。

このコードを使用して、長い間求められていたキーが押されているイベントをエミュレートすることができました。これが、この効果を達成しようとしている他の人に役立つことを願っています. これが他の人にも役立つことを願っています。そして、私よりも技術的に傾いている人々が、ハードウェアが入力ストリームでキー保持イベントを実際にシミュレートする方法と、入力を送信して同じことをより厳密に行う方法を説明できることを願っています。

于 2013-07-22T06:13:48.810 に答える