Глобальные горячие клавиши в WPF, работающие из любого окна

Я должен использовать горячие клавиши, которые будут работать из каждого окна и кафедры. В winforms я использовал:

RegisterHotKey(this.Handle, 9000, 0x0002, (int)Keys.F10);

и

UnregisterHotKey(this.Handle, 9000);

и

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);
    switch (m.Msg)
    {
        case 0x312:
        switch (m.WParam.ToInt32())
        {
            case 9000:
            //function to do
            break;
        }
        break;
    }
}

В моем приложении WPF я попытался сделать:

AddHandler(Keyboard.KeyDownEvent, (KeyEventHandler)HandleKeyDownEvent);

и

private void HandleKeyDownEvent(object sender, KeyEventArgs e)
{
    if (e.Key == Key.F11 && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
    {
        //function to do
    }
}    

Но это работает только тогда, когда мое приложение активно и находится сверху, но не работает, когда приложение свернуто (например). Есть ли способ сделать это?


person cadi2108    schedule 07.07.2012    source источник
comment
Что означает 9000?   -  person Starwave    schedule 14.01.2020
comment
Я понял это из комментариев в этом примере: ourcodeworld.com/articles/read/573/   -  person Starwave    schedule 14.01.2020


Ответы (1)


Вы можете использовать тот же подход, что и в WinForms, с некоторой адаптацией:

  • используйте WindowInteropHelper для получения HWND (вместо свойства Handle формы)
  • использовать HwndSource для обработки оконных сообщений (вместо переопределения WndProc формы)
  • не используйте перечисление Key из WPF - это не те значения, которые вам нужны

Полный код:

[DllImport("User32.dll")]
private static extern bool RegisterHotKey(
    [In] IntPtr hWnd,
    [In] int id,
    [In] uint fsModifiers,
    [In] uint vk);

[DllImport("User32.dll")]
private static extern bool UnregisterHotKey(
    [In] IntPtr hWnd,
    [In] int id);

private HwndSource _source;
private const int HOTKEY_ID = 9000;

protected override void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);
    var helper = new WindowInteropHelper(this);
    _source = HwndSource.FromHwnd(helper.Handle);
    _source.AddHook(HwndHook);
    RegisterHotKey();
}

protected override void OnClosed(EventArgs e)
{
    _source.RemoveHook(HwndHook);
    _source = null;
    UnregisterHotKey();
    base.OnClosed(e);
}

private void RegisterHotKey()
{
    var helper = new WindowInteropHelper(this);
    const uint VK_F10 = 0x79;
    const uint MOD_CTRL = 0x0002;
    if(!RegisterHotKey(helper.Handle, HOTKEY_ID, MOD_CTRL, VK_F10))
    {
        // handle error
    }
}

private void UnregisterHotKey()
{
    var helper = new WindowInteropHelper(this);
    UnregisterHotKey(helper.Handle, HOTKEY_ID);
}

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:
                    OnHotKeyPressed();
                    handled = true;
                    break;
            }
            break;
    }
    return IntPtr.Zero;
}

private void OnHotKeyPressed()
{
    // do stuff
}
person max    schedule 07.07.2012
comment
Вы можете использовать KeyInterop для ключей WPF, чтобы получить правильный виртуальный ключ: stackoverflow.com/questions/1153009/ . - person Josh; 22.10.2020