【问题标题】:C# keystroke interceptor when minimized最小化时的 C# 击键拦截器
【发布时间】:2014-04-25 07:18:24
【问题描述】:

好的,所以我正在尝试编写一个程序来跟踪我在玩游戏时的击键,以便我以后可以分析数据以帮助我改进我的游戏。我一直在尝试做的是使用 user32.dll 的 RegisterHotKey 实现一个全局热键挂钩。但这会完全捕获击键,并且游戏不再接收击键。我不知道从这里去哪里,任何指针都将不胜感激。以下是一些附加信息:

  • 我正在使用 C#
  • .NET 4
  • 使用 Visual Studio 2010
  • 我并没有试图做任何违法的事情,或者违反游戏服务条款

【问题讨论】:

标签: c# .net winforms keyboard-events keystroke


【解决方案1】:

这取自 Stephan Toubs 2006 年的博客:

http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx

using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;

class InterceptKeys
{
   private const int WH_KEYBOARD_LL = 13;
   private const int WM_KEYDOWN = 0x0100;
   private static LowLevelKeyboardProc _proc = HookCallback;
   private static IntPtr _hookID = IntPtr.Zero;

   public static void Main()
   {
       _hookID = SetHook(_proc);
       Application.Run();
       UnhookWindowsHookEx(_hookID);
   }

   private static IntPtr SetHook(LowLevelKeyboardProc proc)
   {
       using (Process curProcess = Process.GetCurrentProcess())
       using (ProcessModule curModule = curProcess.MainModule)
       {
        return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
            GetModuleHandle(curModule.ModuleName), 0);
       }
    }

    private delegate IntPtr LowLevelKeyboardProc(
    int nCode, IntPtr wParam, IntPtr lParam);

    private static IntPtr HookCallback(
    int nCode, IntPtr wParam, IntPtr lParam)
   {
       if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
       {
           int vkCode = Marshal.ReadInt32(lParam);
           Console.WriteLine((Keys)vkCode);
       }

       return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

   [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   private static extern IntPtr SetWindowsHookEx(int idHook,
   LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

   [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   [return: MarshalAs(UnmanagedType.Bool)]
   private static extern bool  UnhookWindowsHookEx(IntPtr hhk);

   [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);
}

【讨论】:

  • 使用我的谷歌技能,我自己确实遇到了这个问题,但从未想过尝试它,因为我认为它与我已经尝试过的更相似,而不是实际。我会看一下并试一试!我会告诉你进展如何
  • 非常适合我。我最近也出于类似的原因摆弄了键盘钩子,并得到了一个外观相似的示例,其中指出您必须拥有一个 Windows 窗体才能接收这些击键,但事实证明,这个示例表明您确实可以将其编译为控制台应用程序,您只需添加对System.Windows.FormsApplication.Run(); 的引用即可启动消息循环。所以不需要明确的形式。
  • 好的,所以我必须遗憾地承认,因为我唯一的编程教育形式是自学的,所以我从第一眼开始就对此知之甚少...。我点击了链接,并做到了正如它所说,我有两个问题......如果我将它作为一个控制台应用程序(就像它在网站上所说的那样)它有大量的编译错误。如果我将其作为 WinForm 执行,则在添加“使用系统”后进行编译;到顶部,但它什么都不做(我知道它可能不会,直到我添加其他东西。我只是不知道其他东西需要什么......任何提示?再次感谢!:)
  • @Michael 对于这些错误,最好在那里开始一个新问题,因为我能够复制粘贴代码添加一个引用并完成(虽然使用 vs 2012),但也许这些错误微不足道,可以在 cmets 中解决?你真的需要让它成为一个控制台应用程序,你后来添加了对System.Windows.Forms 的引用(只是引用不要使它成为一个Windows窗体项目)?
  • @Michael 应该像switch outputtype in project's properties to Windows Application, add a form to the project 一样简单,并将该表单作为Application.Run(new YourFormName()) 的参数运行,或者您作为Windows 窗体应用程序启动一个新项目并添加相同的代码并包含表格变成Application.Run()
猜你喜欢
  • 1970-01-01
  • 2010-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-22
  • 2014-03-10
相关资源
最近更新 更多