Capturing Key Press Event in my WPF Application which do not have focus
Asked Answered
J

3

10

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.

Jamilla answered 16/12, 2010 at 18:58 Comment(1)
You have to use the Windows API to register a keyboard hook with Windows. blogs.msdn.microsoft.com/toub/2006/05/03/…Immodest
A
1

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

Alyosha answered 9/8, 2023 at 6:33 Comment(0)
H
0

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

Hadji answered 15/7, 2019 at 9:15 Comment(0)
S
-2

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.

Sexlimited answered 17/12, 2010 at 16:0 Comment(1)
it does not work when the application is not focus, it works only for the focus application. the wrong answer.Eyespot

© 2022 - 2024 — McMap. All rights reserved.