Windows 中的 C# RawInputDevice:如何禁用除我之外的所有应用程序的消息?

问题描述 投票:0回答:3

我有一个注册的 RawInputDevice。

// sample
private void SplashLoad(object sender, EventArgs e)
        {
            var rid = new RawInputDevice[1];
            rid[0].UsagePage = HidUsagePage.GENERIC;
            rid[0].Usage = HidUsage.Keyboard;
            rid[0].Flags = RawInputDeviceFlags.INPUTSINK;
            rid[0].Target = Handle;
            if (!Win32.RegisterRawInputDevices(rid, (uint)rid.Length, (uint)Marshal.SizeOf(rid[0])))
            {
                throw new ApplicationException("Не удалось зарегистрировать устройство.");
            }
            inputBuffer = "";
            this.terminateFlag = false;
            t = new Thread(MainThread);
            t.Start(this);
        }
// another cs file goes there
    internal enum RawInputDeviceFlags
        {
            /// <summary>No flags.</summary>
            NONE = 0,
            /// <summary>If set, this removes the top level collection from the inclusion list. This tells the operating system to stop reading from a device which matches the top level collection.</summary>
            REMOVE = 0x00000001,
            /// <summary>If set, this specifies the top level collections to exclude when reading a complete usage page. This flag only affects a TLC whose usage page is already specified with PageOnly.</summary>
            EXCLUDE = 0x00000010,
            /// <summary>If set, this specifies all devices whose top level collection is from the specified UsagePage. Note that Usage must be zero. To exclude a particular top level collection, use Exclude.</summary>
            PAGEONLY = 0x00000020,
            /// <summary>If set, this prevents any devices specified by UsagePage or Usage from generating legacy messages. This is only for the mouse and keyboard.</summary>
            NOLEGACY = 0x00000030,
            /// <summary>If set, this enables the caller to receive the input even when the caller is not in the foreground. Note that WindowHandle must be specified.</summary>
            INPUTSINK = 0x00000100,
            /// <summary>If set, the mouse button click does not activate the other window.</summary>
            CAPTUREMOUSE = 0x00000200,
            /// <summary>If set, the application-defined keyboard device hotkeys are not handled. However, the system hotkeys; for example, ALT+TAB and CTRL+ALT+DEL, are still handled. By default, all keyboard hotkeys are handled. NoHotKeys can be specified even if NoLegacy is not specified and WindowHandle is NULL.</summary>
            NOHOTKEYS = 0x00000200,
            /// <summary>If set, application keys are handled.  NoLegacy must be specified.  Keyboard only.</summary>
            APPKEYS = 0x00000400,
            /// If set, this enables the caller to receive input in the background only if the foreground application
            /// does not process it. In other words, if the foreground application is not registered for raw input,
            /// then the background application that is registered will receive the input.
            /// </summary>
            EXINPUTSINK = 0x00001000,
            DEVNOTIFY = 0x00002000
        }

        public enum HidUsagePage : ushort
        {
            /// <summary>Unknown usage page.</summary>
            UNDEFINED = 0x00,
            /// <summary>Generic desktop controls.</summary>
            GENERIC = 0x01,
            /// <summary>Simulation controls.</summary>
            SIMULATION = 0x02,
            /// <summary>Virtual reality controls.</summary>
            VR = 0x03,
            /// <summary>Sports controls.</summary>
            SPORT = 0x04,
            /// <summary>Games controls.</summary>
            GAME = 0x05,
            /// <summary>Keyboard controls.</summary>
            KEYBOARD = 0x07,
        }

        public enum HidUsage : ushort
        {
            /// <summary>Unknown usage.</summary>
            Undefined = 0x00,
            /// <summary>Pointer</summary>
            Pointer = 0x01,
            /// <summary>Mouse</summary>
            Mouse = 0x02,
            /// <summary>Joystick</summary>
            Joystick = 0x04,
            /// <summary>Game Pad</summary>
            Gamepad = 0x05,
            /// <summary>Keyboard</summary>
            Keyboard = 0x06,
            /// <summary>Keypad</summary>
            Keypad = 0x07,
            /// <summary>Muilt-axis Controller</summary>
            SystemControl = 0x80,
            /// <summary>Tablet PC controls</summary>
            Tablet = 0x80,
            /// <summary>Consumer</summary>
            Consumer = 0x0C,
        }

该设备——读卡器,是系统中模拟键盘的HID。一切正常,但我有问题:来自设备的消息不仅适用于我的应用程序(在后台、托盘中工作),而且也适用于活动窗口应用程序。我如何禁用它并设置仅适用于我的应用程序的消息?

c# winapi raw-input
3个回答
2
投票

好吧,我花了很多时间来解决这个问题,这里是结果和说明: Keyboard message path in Windows

  1. 我无法使用原始输入,因为在此级别上消息已到达将该设备注册为我的输入数据的所有应用程序。
  2. 我无法使用低级键盘挂钩,因为 WinAPI 不提供有关挂钩中设备的信息。是的,这令人难以置信,但该 API 的设计太糟糕了。
  3. 唯一的方法(我确信)是使用内核模块。如果您需要解决该问题,您可以自己编写或使用这个 C++ 上的。它工作完美,非常好的英语入门并解决了我的问题。是的,它不是 C#,但对我来说不是问题。如果您在 C# 上需要它,请尝试在可管理的 C++ 中使用此代码。

1
投票

原始输入不支持您的要求。允许多个应用程序注册同一设备,没有获得独占访问权限的选项。您必须使用

SetWindowsHookEx()
拦截并丢弃
WM_INPUT
消息以及
WM_KEY...
相关消息(假设其他应用程序不使用
RIDEV_NOLEGACY
标志),这些消息不是针对您的窗口的。


0
投票

您无法禁用其他应用程序注册原始输入(不使用挂钩等)。

但是您可以使用

NOLEGACY
标志阻止在前台窗口生成正常的键盘消息。

rid[0].Flags = RawInputDeviceFlags.INPUTSINK | RawInputDeviceFlags.NOLEGACY;
© www.soinside.com 2019 - 2024. All rights reserved.