繁体   English   中英

keypress事件处理程序,但在没有表单的Windows应用程序上

[英]keypress event handler but on a windows app with no forms

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

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

我认为我需要的是一个通用的按键监听器,可以在读卡器时查找。

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

我想我想要像KeyPressEventHandler这样的东西,但我似乎无法在我的应用程序中使用它。

我创建了以下Extention方法:

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()方法中引用它。 我没有看到按键方法。

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

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

说完所有这些之后,使用WH_KEYBOARD或WH_KEYBOARD_LL挂钩肯定可以实现所需的结果。 如果您决定走这条路线,我建议您使用交替的Left-Ctrl和Right-Control按键作为读取器的开始和停止标记(假设它能够这样做)。

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

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

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

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

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

经过深思熟虑后,我认为您可以直接访问HID设备并使用标准Win32 API执行键盘翻译。 在查看该路线时,我遇到了Raw Input API。 使用此功能,您应该能够为所有键盘设备注册原始输入,然后在输入时确定实际生成事件的设备。 消除了读者启动和停止哨兵的需要。

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

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

一个例子(我以为自.net框架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); 
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM