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

发布于 2024-10-07 20:19:15 字数 180 浏览 5 评论 0原文

我在 WPF 中开发了一个屏幕键盘。我需要夺取钥匙 新闻事件(通过键盘)以跟踪 Caps Lock、Shift 等等(无论它们是否被按下)。 请注意,当任何其他应用程序时,我的应用程序会失去焦点 (比如记事本)被打开。

谁能建议如何在 WPF 中实现这一目标? 简而言之,我的 WPF 应用程序甚至需要捕获按键事件 虽然它没有焦点。

I have developed an On Screen Keyboard in WPF. I need to capture the key
press event (via Key Board) in order to keep a track of Caps Lock, Shift
etc (whether they are pressed).
Please note that my application loses focus when any other application
(say notepad) is opened.

Could anyone suggest how to achieve this in WPF?
in short, my WPF application needs to capture the key press events even
though it does not have focus.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

墟烟 2024-10-14 20:19:15

如果您希望 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>

参考

If you want your WPF application to be able to detect and handle key presses even when it is not currently activated or focused on the screen you could implement what is known as global hot keys in Windows.

The following two methods can be added to a C# class to be able to register and unregister a global hot key:

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

Sample code

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>

Reference

左岸枫 2024-10-14 20:19:15

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

它与您的问题不完全相同,他试图在没有获得焦点的情况下捕捉事件,但这是一个很好的起点

This was helpful for me : Disable WPF Window Focus

Its not exactly the same as your problem, he is trying to catch an event without getting focus , but its a good starting point

水溶 2024-10-14 20:19:15

我使用了一个简单的代码:

在 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 的 keydown 例程的样子:

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

这是获取任何键的简单方法。我希望这有帮助。

I use a simple code behind:

In the xaml I use a KeyDown event called MyTestKey.

<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" >

This is what the keydown routine looks like where I check for the number 1:

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

This is an easy way to get to any key. I hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文