我可以使用PostMessage
api发送任何Windows应用程序键击。但我无法使用PostMessage
将关键笔划发送到游戏窗口。
任何人都知道使用直接输入功能从C#向游戏发送密钥。
答案 0 :(得分:6)
另一种方法是直接挂钩DirectInput API - Microsoft Research已经提供了一个库来执行此操作:http://research.microsoft.com/en-us/projects/detours/
一旦您加入API,您就可以随心所欲地做任何事情。但是,值得注意的是,在Windows的最新版本中,DirectInput for mouse&键盘输入只是Win32 Windows消息的包装。 DirectInput在后台生成一个线程,只是截获窗口消息,然后再将它们传递回应用程序。这是微软不再推荐使用DirectInput的原因之一 - 这意味着像PostMessage 这样的消息传递API应该正常工作。
答案 1 :(得分:4)
一种替代方法是使用键盘驱动程序(这不是SendInput())来模拟按键 - 以及事件鼠标按下,而不是挂钩到DirectX。
您可以使用Oblita's Interception keyboard driver(适用于Windows 2000 - Windows 7)和C# library Interception(包装键盘驱动程序以在C#中使用)。
有了它,你可以做很酷的事情,如:
input.MoveMouseTo(5, 5);
input.MoveMouseBy(25, 25);
input.SendLeftClick();
input.KeyDelay = 1; // See below for explanation; not necessary in non-game apps
input.SendKeys(Keys.Enter); // Presses the ENTER key down and then up (this constitutes a key press)
// Or you can do the same thing above using these two lines of code
input.SendKeys(Keys.Enter, KeyState.Down);
Thread.Sleep(1); // For use in games, be sure to sleep the thread so the game can capture all events. A lagging game cannot process input quickly, and you so you may have to adjust this to as much as 40 millisecond delay. Outside of a game, a delay of even 0 milliseconds can work (instant key presses).
input.SendKeys(Keys.Enter, KeyState.Up);
input.SendText("hello, I am typing!");
/* All these following characters / numbers / symbols work */
input.SendText("abcdefghijklmnopqrstuvwxyz");
input.SendText("1234567890");
input.SendText("!@#$%^&*()");
input.SendText("[]\\;',./");
input.SendText("{}|:\"<>?");
因为这些按键背后的机制是键盘驱动程序,所以它几乎不受限制。
答案 2 :(得分:1)
现在可以通过DirectInput API执行此操作。
归档相同效果的唯一方法是编写自己的DirectInput COM对象,它只包装普通的DirectInput对象。之后,您可以添加代码来模拟击键。诀窍是用您的版本替换Win32 dinput.dll。然后所有游戏都会在启动时加载你的DLL。
我担心你不能用托管语言做到这一点。你必须使用本机代码执行此操作,因为它需要相当多的低级hackery。
答案 3 :(得分:0)
您可以使用非托管SendInput函数。它将输入发布在低于DirectInput的级别。了解要发送的密钥代码非常重要。这些可能因游戏而异。如果Windows虚拟键码不适用于游戏,您可以尝试发送DIKEYBOARD常量(如DIKEYBOARD_A等),如果仍然无法继续尝试。例如,半条命或反恐精英期望ASCII代码作为密钥代码(我需要一段时间来解决这个问题)
答案 4 :(得分:0)
为没有探测器的朋友游戏(Nostale)工作:
另外here 虚拟密钥代码
的有用列表 [DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
private void button1_Click(object sender, EventArgs e)
{
const int WM_SYSKEYDOWN = 0x0104;
const int VK_SPACE = 0x20;
IntPtr WindowToFind = FindWindow(null, "WINDOW NAME");
PostMessage(WindowToFind, WM_SYSKEYDOWN, VK_SPACE, 0);
}