There is a WPF application (audio player). It is necessary to add the ability to catch the pressing of certain keys, even when the application is minimized. For example, when you press Num4 , to stop playback, when you press other keys (depending on the settings, to continue playing music, etc.). I tried to implement it through the GetAsyncKeyState(int vkey) function from user32.dll , but this does not quite suit me, here is a sample code:

 public static class KeyState { public static void Wait(Key key, Action<KeyStates> action) { var asyncOperation = AsyncOperationManager.CreateOperation(null); SendOrPostCallback callBack = state => action((KeyStates) state); ThreadPool.QueueUserWorkItem(state => { var vk = KeyInterop.VirtualKeyFromKey(key); var prev = ((GetAsyncKeyState(vk) & 0x8000) == 0x8000); if (prev) { asyncOperation.Post(callBack, KeyStates.Down); } while (true) { var res = ((GetAsyncKeyState(vk) & 0x8000) == 0x8000); if (res != prev && res) { asyncOperation.Post(callBack, KeyStates.Down); } prev = res; } }); } [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] private static extern short GetAsyncKeyState(int vkey); } 

The problem here is that I not only need to catch the keystroke, but also prevent the “advancement” of the keystroke further. Those. keystroke should be intercepted by my application and not fall into others (for example, in a text editor). I would be grateful for the help. If someone else tells you how to correctly implement this for an application that is deployed through ClickOnce , it would be great at all. Thank!

1 answer 1

Starting with Windows Vista, you can use the RegisterHotKey function. It allows you to register a global hot key and specify a window that will receive messages. To process these messages in a WPF application, you need to register a handler through HwndSource.AddHook .

An example of how to handle a hot key event and display the moment it was pressed in TextBlock:

 using System; using System.Collections.Generic; using System.Text; using System.Windows; using System.Windows.Controls; using System.Runtime.InteropServices; using System.Windows.Interop; namespace WpfHotkey { public partial class MainWindow : Window { [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); //необходимые константы public const int MOD_ALT = 0x1; public const int MOD_CONTROL = 0x2; public const int MOD_SHIFT = 0x4; public const int MOD_WIN = 0x8; public const int WM_HOTKEY = 0x312; //несколько примеров виртуальных кодов public const uint VK_F1 = 0x70; public const uint VK_F2 = 0x71; public const uint VK_UP = 0x26; public const uint VK_DOWN = 0x28; //обработчик сообщений для окна private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { if (msg == WM_HOTKEY) { textBlock1.Text += DateTime.Now.ToString() + " WM_HOTKEY message, ID: 0x" + wParam.ToString("X"); textBlock1.Text += Environment.NewLine; handled = true; } return IntPtr.Zero; } public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { WindowInteropHelper h = new WindowInteropHelper(this); HwndSource source = HwndSource.FromHwnd(h.Handle); source.AddHook(new HwndSourceHook(WndProc));//регистрируем обработчик сообщений bool res = RegisterHotKey(h.Handle, 1, 0, VK_F1);//регистрируем горячую клавишу if (res == false) MessageBox.Show("RegisterHotKey failed"); } } }