我一直在尝试将按键发送到DirectX应用程序一会儿,并且一直在努力。我是C#的新手,所以有些更复杂的功能不胜枚举,但是我一直在尽力将其拼凑在一起。
SendInput是我似乎无法掌握的事情之一。
我尝试使用一些不同的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()
,但是由于某种原因,我遇到了同样的问题。它在游戏中到处都可以使用。
我使用的是VK代码,而不是DirectInput代码,我不确定这是否是问题所在,但是我担心如果我使用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);
}
我最终使用“ InputManager”SendInput
包装器使一切正常工作。
using InputManager
//......
Keyboard.KeyPress(Keys.YourSelectedKeyHere);
事实证明,我所要做的就是以管理员身份运行我的代码...
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句