在我的WPF应用程序中捕获没有焦点的按键事件

10
我在WPF中开发了一个屏幕键盘。我需要捕获按键事件(通过键盘)以便跟踪大写锁定、Shift等是否被按下。 请注意,当打开其他应用程序(比如记事本)时,我的应用程序会失去焦点。
有人能否建议如何在WPF中实现这一点? 简而言之,我的WPF应用程序需要捕获按键事件,即使它没有焦点。

3
您需要使用Windows API在Windows中注册键盘钩子。 https://blogs.msdn.microsoft.com/toub/2006/05/03/low-level-keyboard-hook-in-c/ - Logan Fields
3个回答

1

如果您希望您的WPF应用程序能够在当前未被激活或焦点在屏幕上时检测和处理按键操作,您可以在Windows中实现所谓的全局热键。

以下两种方法可以添加到一个C#类中,以便注册和注销全局热键:

[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
 
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

示例代码
using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
 
namespace Mm.Wpf.GlobalHotKeys
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        [DllImport("user32.dll")]
        private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
 
        [DllImport("user32.dll")]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
 
        private const int HOTKEY_ID = 9000;
 
        //Modifiers:
        private const uint MOD_NONE = 0x0000; //(none)
        private const uint MOD_ALT = 0x0001; //ALT
        private const uint MOD_CONTROL = 0x0002; //CTRL
        private const uint MOD_SHIFT = 0x0004; //SHIFT
        private const uint MOD_WIN = 0x0008; //WINDOWS
        //CAPS LOCK:
        private const uint VK_CAPITAL = 0x14;
 
        public MainWindow()
        {
            InitializeComponent();
        }
 
        private IntPtr _windowHandle;
        private HwndSource _source;
        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);
 
            _windowHandle = new WindowInteropHelper(this).Handle;
            _source = HwndSource.FromHwnd(_windowHandle);
            _source.AddHook(HwndHook);
 
            RegisterHotKey(_windowHandle, HOTKEY_ID, MOD_CONTROL, VK_CAPITAL); //CTRL + CAPS_LOCK
        }
 
        private IntPtr HwndHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            const int WM_HOTKEY = 0x0312;
            switch (msg)
            {
                case WM_HOTKEY:
                    switch (wParam.ToInt32())
                    {
                        case HOTKEY_ID:
                            int vkey = (((int)lParam >> 16) & 0xFFFF);
                            if (vkey == VK_CAPITAL)
                            {
                                tblock.Text += "CapsLock was pressed" + Environment.NewLine;
                            }
                            handled = true;
                            break;
                    }
                    break;
            }
            return IntPtr.Zero;
        }
 
        protected override void OnClosed(EventArgs e)
        {
            _source.RemoveHook(HwndHook);
            UnregisterHotKey(_windowHandle, HOTKEY_ID);
            base.OnClosed(e);
        }
    }
}
<Window x:Class="Mm.Wpf.GlobalHotKeys.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBlock x:Name="tblock"></TextBlock>
    </Grid>
</Window>

参考资料


0

这对我很有帮助:禁用WPF窗口焦点

虽然不完全符合你的问题,但这是一个很好的起点。他试图在不获取焦点的情况下捕获事件。


-2
我使用一个简单的代码后台:
在XAML中,我使用了一个名为MyTestKey的KeyDown事件。
<Window x:Class="MyApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        KeyDown="myTestKey" >

这是键盘按下事件的代码,我在其中检查数字1:

private void myTestKey(object sender, KeyEventArgs e)
{
            if ((e.Key == Key.D1) || (e.Key == Key.NumPad1))
            {
                //do some stuff here
                return;
            }
}

这是一个轻松的方法,可以快速找到任何键。希望这有所帮助。


11
只有当应用程序处于焦点状态时,它才能正常工作,它只对焦点应用程序起作用。这是错误答案。 - Darius Miliauskas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接