#c_sharp #wpf #windows #clickonce #keyboardhook
Имеется WPF-приложение (аудио-проигрыватель). Необходимо добавить возможность отлавливать нажатие определённых клавиш, даже когда приложение свёрнуто. Например, при нажатии Num4 - останавливать вопроизведение, при нажатии других клавиш (в зависимости от настроек - продолжать воспроизведение музыки и т.п.). Пробовал реализовать через функцию GetAsyncKeyState(int vkey) из user32.dll, но мне это не совсем подходит, вот пример кода: public static class KeyState { public static void Wait(Key key, Actionaction) { 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); } Проблема здесь в том, что мне не только нужно отловить нажатие клавиши, но и предотвратить "продвижение" нажатия клавиши далее. Т.е. нажатие клавиши должно перехватываться моим приложением и не попадать в другие (например, в текстовый редактор). Буду благодарен за помощь. Если кто-нибудь ещё и подскажет как это корректно реализовать для приложения, которое развертывается через ClickOnce, было бы вообще шикарно. Спасибо!
Ответы
Ответ 1
Начиная с Windows Vista можно использовать функцию RegisterHotKey. Она позволяет зарегистрировать глобальную горячую клавишу и указать окно, которое будет принимать сообщения. Чтобы обработать эти сообщения в WPF приложении, нужно зарегистрировать обработчик через HwndSource.AddHook. Пример как обработать событие горячей клавиши и вывести момент ее нажатия в 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"); } } }
Комментариев нет:
Отправить комментарий