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