5

我有一个绑定到读卡器(磁条)的应用程序。当我有一个输出我的数据的表单或在我可以将数据输出到控制台的控制台应用程序中时,我能够捕获卡上的数据。

但是在我正在开发的应用程序上,它有一个 Program 类作为它的启动,并且只是以这种方式启动程序。

我认为我需要的是一个通用的按键监听器,用于在读卡器被刷卡时寻找。

Windows 窗体应用程序前 控制台应用程序前 KeyPressEventHandler 委托

我想我想要 KeyPressEventHandler 之类的东西,但我似乎无法让它在我的应用程序中工作。

我创建了以下扩展方法:

public static class Utilities
{
    private static KeyPressEventHandler handler = KeyPressed;

    public static void KeyPressed(Object sender, KeyPressEventArgs e)
    {
        while (true)
        {
            dataReceived.Append(e.KeyChar);
        }
    }

    public static KeyPressEventHandler getKeyPressHandler()
    {
        return handler;
    }
}

但我不确定如何在我的Main()方法中引用它。我没有看到按键方法。

4

2 回答 2

2

根据 CLR 和 Windows 的版本,使用 Windows Hooks 会遇到一些特定问题。

  1. WH_KEYBOARD/WH_KEYBOARD_LL 键盘挂钩需要消息循环才能正确操作。在生成对挂钩委托的调用之前,键盘事件被发布到安装线程的消息队列中。
  2. Windows Vista 和更高版本将不允许来自较低权限进程的挂钩查看较高权限进程中的活动。因此,您可能会或可能不会收到键盘事件,具体取决于当前具有输入焦点的进程。
  3. 一旦你钩住了键盘事件,你将需要读卡器生成一个启动和停止标记,以指示你应该捕获剩余的输入。这是否可以实现将取决于配置读卡器的能力。

说了这么多,当然可以使用 WH_KEYBOARD 或 WH_KEYBOARD_LL 挂钩来实现所需的结果。如果你决定走那条路,我建议你交替使用 Left-Ctrl 和 Right-Control 按键作为来自读者的开始和停止哨兵(假设它能够这样做)。

此外,如果您最终使用了 Windows 挂钩,则需要从后台线程而不是应用程序的主线程安装挂钩,因为您需要在一定时间内处理键盘事件。如果您花费的时间超过 Windows 允许的时间,则挂钩将被忽略。

作为 Windows Hooks 的替代方案,您可以使用 DirectInput。老实说,我从未尝试过这种方法,但这个概念似乎是合理的,并且消除了 Windows Hooks 的一些不确定性。

我假设由于您要求全局键盘事件,因此您的读卡器是某种 USB HID 设备。您可以通过运行 DxDiag 来验证您的读卡器是否显示为 DirectInput 设备。如果可以访问该设备,它应该出现在“输入”选项卡上。似乎有各种可用的 DirectX 托管程序集。

如果您不限于所拥有的读卡器类型,那么使用基于串行的读卡器可能会更好。有了它,您将无法完成设备输出的其他应用程序。

我意识到我实际上并没有回答你的问题,所以请随意投反对票或忽略这个答案。希望这确实为您提供了一些有关您可能面临的问题的信息。

经过进一步思考,我认为您可以直接访问 HID 设备并使用标准 Win32 API 执行键盘翻译。沿着这条路线查看时,我遇到了原始输入API。使用它,您应该能够注册所有键盘设备的原始输入,然后在输入时确定实际生成事件的设备。消除了阅读器对启动和停止哨兵的需要。

更好的是,API 发送消息来区分窗口是前景窗口和不是前景窗口时生成的输入。使用此 API,您仍然需要在后台线程上创建窗口和消息循环,但它应该比 Windows Hook 方法更简洁。

有关在 C# 中读取原始输入的示例应用程序,请参阅使用 C# 中的原始输入处理 CodeProject 上的多个键盘。

于 2013-10-11T05:44:49.270 回答
1

一个例子(以为我从.net framework 1.1开始就没有更新代码)在按下任何键时都有一个事件:

public class Hook
{

    [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
    private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
    [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
    private static extern bool UnhookWindowsHookEx(int idHook);
    [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
    private static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
    [DllImport("kernel32.dll")]
    public static extern int GetCurrentThreadId();

    public static event Action Event = null;
    private const int WH_KEYBOARD = 2;
    private delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);
    static int _hookKeyboard = 0;
    private static HookProc _hookKeyboardProc;

    public static bool Install() 
    {
        _hookKeyboardProc = new HookProc(KeyboardHook);
        _hookKeyboard = SetWindowsHookEx(WH_KEYBOARD, _hookKeyboardProc, IntPtr.Zero, GetCurrentThreadId());
        return _hookKeyboard != 0;
    }

    public static bool Uninstall()
    {
        // uninstall keyboard hook
        if(!UnhookWindowsHookEx(_hookKeyboard))
            return false;
        _hookMouseProc = null;
        return true;
    }

    private static int KeyboardHook(int nCode, IntPtr wParam, IntPtr lParam)
    {
        // if any message - fire event
        if(nCode >= 0 && Event != null) 
            Event();
        return CallNextHookEx(_hookKeyboard, nCode, wParam, lParam); 
    }
}
于 2013-10-08T13:30:25.593 回答