しばらくの間、キーの押下を DirectX アプリケーションに送信しようとしていて、打ち続けています。私は C# を初めて使用するので、より複雑な関数のいくつかは頭を悩ませますが、できる限りそれらをつなぎ合わせようとしています。
SendInput は、私が把握できないように見えるものの 1 つです。
以下を含むいくつかの異なる SendInput ラッパーを使用して、物事を簡素化しようとしました。
http://inputsimulator.codeplex.com/
http://www.codeproject.com/Articles/117657/InputManager-library-Track-user-input-and-simulate
インターセプターと呼ばれる別のもの
それらはすべて、ほとんどのアプリケーションにキープレスを送信しますが、アクティブなゲームウィンドウに送信することはまだできません.
SendKeys も試しました。
私は自分でキーボード フックを配置しようとしましたが、高度すぎて自分で理解できず、コードがエラーだらけになってしまいました。
ここにコードを投稿すると(単純なサーバーアプリ)、誰かがキーボードフックをどこにどのように配置するかを説明できるかもしれないと思っていました。
namespace ServerApp
{
public partial class Form1 : Form
{
private TcpListener tcpListener;
private Thread listenThread;
private int connectedClients = 0;
private delegate void WriteMessageDelegate(string msg);
public Form1()
{
InitializeComponent();
Server();
}
private void Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 8888);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
TcpClient client = this.tcpListener.AcceptTcpClient();
connectedClients++;
lblNumberOfConnections.Text = connectedClients.ToString();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
break;
}
if (bytesRead == 0)
{
connectedClients--;
lblNumberOfConnections.Text = connectedClients.ToString();
break;
}
ASCIIEncoding encoder = new ASCIIEncoding();
//Write message in RichTextBox
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
}
tcpClient.Close();
}
private void WriteMessage(string msg)
{
if (this.rtbServer.InvokeRequired)
{
WriteMessageDelegate d = new WriteMessageDelegate(WriteMessage);
this.rtbServer.Invoke(d, new object[] { msg });
}
else
{
this.rtbServer.AppendText(msg + Environment.NewLine);
// SEND KEYSTROKES TO ACTIVE WINDOW
if (msg.Equals("CTRL-T"))
{
// Keyboard.KeyDown(Keys.LControlKey);
// Keyboard.KeyPress(Keys.T); // I was using this for the InputManager Wrapper
// Keyboard.KeyUp(Keys.LControlKey);
}
あらゆる場所を検索した後、次のスニペットは、シミュレートされたキー ストロークを DirectX アプリケーションで動作させるための最良のチャンスのようですが、多数のエラーや使用できないコードなしでコードに実装することはできませんでした。
namespace DirectInput
{
class cDirectInput
{
[DllImport("user32.dll")]
static extern UInt32 SendInput(UInt32 nInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] INPUT[] pInputs, Int32 cbSize);
[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
public int dx;
public int dy;
public int mouseData;
public int dwFlags;
public int time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
public short wVk;
public short wScan;
public int dwFlags;
public int time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public int uMsg;
public short wParamL;
public short wParamH;
}
[StructLayout(LayoutKind.Explicit)]
struct INPUT
{
[FieldOffset(0)]
public int type;
[FieldOffset(4)]
public MOUSEINPUT mi;
[FieldOffset(4)]
public KEYBDINPUT ki;
[FieldOffset(4)]
public HARDWAREINPUT hi;
}
const int KEYEVENTF_EXTENDEDKEY = 0x0001;
const int KEYEVENTF_KEYUP = 0x0002;
const int KEYEVENTF_UNICODE = 0x0004;
const int KEYEVENTF_SCANCODE = 0x0008;
次のセクションでCTRL+T
コマンドを送信できると思いますが、100% 確実ではありません。
// SEND KEYSTROKES TO ACTIVE WINDOW
if (msg.Equals("CTRL-T"))
{
INPUT[] InputData = new INPUT[1];
InputData[0].type = 1;
InputData[0].ki.wScan = 0x1D;
InputData[0].ki.time = 0;
InputData[0].ki.dwExtraInfo = IntPtr.Zero;
InputData[0].type = 1;
InputData[0].ki.wScan = 0x14;
InputData[0].ki.time = 0;
InputData[0].ki.dwExtraInfo = IntPtr.Zero;
InputData[0].type = 1;
InputData[0].ki.wScan = 0x1D;
InputData[0].ki.dwFlags = 0x0002;
InputData[0].ki.time = 0;
InputData[0].ki.dwExtraInfo = IntPtr.Zero;
SendInput(1, InputData, Marshal.SizeOf(typeof(INPUT)));
}
ここで私が本当に苦労しているのは、既存のコードにキーボード フックを配置し、サーバーの残りの部分を適切に機能させる方法です。これらのキーストロークを機能させることは、私のプロジェクトの最後の部分であり、非常にイライラし始めているので、助けていただければ幸いです!
更新
今回は を使用して別の試みを行いましたkeybd_event()
が、何らかの理由で同じ問題が発生しました。ゲーム内を除いてどこでも機能します。
DirectInput コードではなく VK コードを使用しています。それが問題であるかどうかはわかりませんが、代わりに DI コードを使用すると、コードの別の部分を変更する必要があるのではないかと心配しています。私は知りません。
今回試したことの抜粋は次のとおりです。
[DllImport("user32.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
public const int KEYEVENTF_KEYUP = 0x0002;
public const int VK_LCONTROL = 0xA2;
public const int SEMICOLON = 0xBA;
public const int QUOTE = 0xDE;
public const int T = 0x54;
public const int H = 0x48;
public const int R = 0x52;
public const int Z = 0x5A;
public const int X = 0x58;
public const int NUM8 = 0x68;
public const int NUM2 = 0x62;
public const int NUM4 = 0x64;
public const int NUM6 = 0x66;
public const int NUM5 = 0x65;
public const int UP = 0x26;
public const int DOWN = 0x28;
public const int LEFT = 0x25;
public const int RIGHT = 0x27;
public const int RETURN = 0x0D;
// .....
if (msg.Equals("CTRL-T"))
{
keybd_event(VK_LCONTROL, 0, 0, 0);
keybd_event(T, 0, 0, 0);
keybd_event(T, 0, KEYEVENTF_KEYUP, 0);
keybd_event(VK_LCONTROL, 0, KEYEVENTF_KEYUP, 0);
}
コードに問題があるのか、それともまだ間違った方法を使用しているのかわかりません。
更新 2
今回は を使用して再試行しSendMessage
ましたが、 でエラーが発生しているため、ビルドできませんでしたhWnd
。「名前 hWnd は現在のコンテキストに存在しません」
[DllImport("user32.dll")]
public static extern IntPtr SetActiveWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, uint wParam, int lParam);
public const ushort WM_KEYDOWN = 0x0100;
public const ushort WM_KEYUP = 0x0101;
private void WriteMessage(string msg)
{
if (this.rtbServer.InvokeRequired)
{
WriteMessageDelegate d = new WriteMessageDelegate(WriteMessage);
this.rtbServer.Invoke(d, new object[] { msg });
}
else
{
this.rtbServer.AppendText(msg + Environment.NewLine);
// SEND KEYSTROKES TO ACTIVE WINDOW
if (msg.Equals("CTRL-T"))
{
SetActiveWindow(hWnd);
SendMessage(hWnd, WM_KEYDOWN, 0x1D, 0);
SendMessage(hWnd, WM_KEYDOWN, 0x14, 0);
SendMessage(hWnd, WM_KEYUP, 0x1D, 0);
SendMessage(hWnd, WM_KEYUP, 0x14, 0);
}