我在网上看过很多解决方案,但没有一个完全符合我的要求。我的应用程序在后台运行时,在给定进程(而不是我的控制台应用程序)中按下任何键的最佳/最简单方法是什么?我不需要修改器或任何东西。
答案 0 :(得分:4)
您正在寻找的是全局键盘钩子。您可以找到更多信息和示例on MSDN。
答案 1 :(得分:3)
如果您不是特别关心按最简单的方法按键的过程是调用GetAsyncKeyState。它相当有限,因为它没有挂钩键盘,需要你连续调用它。在我看来,最好的方法是挂钩键盘。
使用SetWindowsHookEx,您实际上可以明确指定与钩子过程相关联的线程的标识符,以便您可以为特定进程挂钩(请参阅 dwThreadId )。 / p>
这是一个你可以使用的课程(最初在Micrsoft博客上找到,但我现在似乎无法找到作者的名字!)
public delegate IntPtr KeyboardProcess(int nCode, IntPtr wParam, IntPtr lParam);
public sealed class KeyboardHook
{
public static event EventHandler<KeyPressedEventArgs> KeyPressed;
private const int WH_KEYBOARD = 13;
private const int WM_KEYDOWN = 0x0100;
private static KeyboardProcess keyboardProc = HookCallback;
private static IntPtr hookID = IntPtr.Zero;
public static void CreateHook()
{
hookID = SetHook(keyboardProc);
}
public static void DisposeHook()
{
UnhookWindowsHookEx(hookID);
}
private static IntPtr SetHook(KeyboardProcess keyboardProc)
{
using (Process currentProcess = Process.GetCurrentProcess())
using (ProcessModule currentProcessModule = currentProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD, keyboardProc, GetModuleHandle(currentProcessModule.ModuleName), 0);
}
}
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
if (KeyPressed != null)
KeyPressed(null, new KeyPressedEventArgs((Keys)vkCode));
}
return CallNextHookEx(hookID, nCode, wParam, lParam);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardProcess lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
}
public class KeyPressedEventArgs : EventArgs
{
public Keys KeyCode { get; set; }
public KeyPressedEventArgs(Keys Key)
{
KeyCode = Key;
}
}
通过控制台应用程序实施:
class Program
{
static void Main(string[] args)
{
KeyboardHook.CreateHook();
KeyboardHook.KeyPressed += KeyboardHook_KeyPressed;
Application.Run();
KeyboardHook.DisposeHook();
}
static void KeyboardHook_KeyPressed(object sender, KeyPressedEventArgs e)
{
Console.WriteLine(e.KeyCode.ToString());
}
}
答案 2 :(得分:2)
哦,所以你在老派游戏术语中寻找“Autofire”?
不是编写自己的键盘钩子应用程序(除非你是为了娱乐/它的快感/练习),你可能想要看看AutoIt或AutoHotkey,它们都非常适合键盘/鼠标自动化。
例如,请参阅此主题... http://www.autohotkey.com/board/topic/40598-autofire-keyboard/
答案 3 :(得分:0)
我找到了只为进程挂接的方法。 您可能需要它。
int ProcessId = GetProcessesByName("Your_app_here").FirstOrDefault().Id;
private IntPtr SetHook(KeyboardHookHandler proc)
{
return SetWindowsHookEx(13, proc, GetModuleHandle(Process.GetProcessById(ProcessId).MainModule.ModuleName), GetWindowThreadProcessId(GetModuleHandle(Process.GetProcessById(ProcessId).MainModule.ModuleName), out int MainThreadId));
}
请记住要导入这些方法。
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardHookHandler lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);