如何在WPF和.NET 3.5中注册全局热键以使用CTRL+SHIFT+(LETTER)?

15 浏览
0 Comments

如何在WPF和.NET 3.5中注册全局热键以使用CTRL+SHIFT+(LETTER)?

我正在使用WPF和C#构建一个应用程序。如何绑定到一些按键?另外,如何绑定到Windows键

0
0 Comments

问题的原因是作者想要在WPF和.NET 3.5中注册一个全局热键,使用Ctrl + Shift + (字母)触发。解决方法是通过以下步骤实现:

1. 绑定所选UI元素(例如顶级窗口)与命令,使用InputBinding。

2. 将命令与处理程序绑定,使用CommandBinding。

以下是示例代码:

public WindowMain()
{
   InitializeComponent();
   // 绑定热键
   var ib = new InputBinding(
       MyAppCommands.SaveAll,
       new KeyGesture(Key.S, ModifierKeys.Shift | ModifierKeys.Control));
   this.InputBindings.Add(ib);
   // 绑定处理程序
   var cb = new CommandBinding( MyAppCommands.SaveAll);
   cb.Executed += new ExecutedRoutedEventHandler( HandlerThatSavesEverthing );
   this.CommandBindings.Add (cb );
}
private void HandlerThatSavesEverthing (object obSender, ExecutedRoutedEventArgs e)
{
  // 在这里执行保存所有操作
}

需要注意的是,这种方法并不是真正的全局热键,只有当应用程序处于焦点状态时才起作用。如果打开了新窗口并在那里按下热键,它不起作用。此外,如果应用程序失去焦点,也无法触发热键。

0
0 Comments

问题的出现原因:用户想要在WPF和.NET 3.5中注册一个全局快捷键,但不清楚如何实现。

解决方法:提供了一个完整的工作解决方案,包括一个HotKey类和示例用法。用户可以使用该类来注册全局快捷键,并定义相应的操作。

具体代码如下:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Mime;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
namespace UnManaged
{
    public class HotKey : IDisposable
    {
        private static Dictionary _dictHotKeyToCalBackProc;
        [DllImport("user32.dll")]
        private static extern bool RegisterHotKey(IntPtr hWnd, int id, UInt32 fsModifiers, UInt32 vlc);
        [DllImport("user32.dll")]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
        public const int WmHotKey = 0x0312;
        private bool _disposed = false;
        public Key Key { get; private set; }
        public KeyModifier KeyModifiers { get; private set; }
        public Action Action { get; private set; }
        public int Id { get; set; }
        
        public HotKey(Key k, KeyModifier keyModifiers, Action action, bool register = true)
        {
            Key = k;
            KeyModifiers = keyModifiers;
            Action = action;
            if (register)
            {
                Register();
            }
        }
        
        public bool Register()
        {
            int virtualKeyCode = KeyInterop.VirtualKeyFromKey(Key);
            Id = virtualKeyCode + ((int)KeyModifiers * 0x10000);
            bool result = RegisterHotKey(IntPtr.Zero, Id, (UInt32)KeyModifiers, (UInt32)virtualKeyCode);
            if (_dictHotKeyToCalBackProc == null)
            {
                _dictHotKeyToCalBackProc = new Dictionary();
                ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage);
            }
            _dictHotKeyToCalBackProc.Add(Id, this);
            Debug.Print(result.ToString() + ", " + Id + ", " + virtualKeyCode);
            return result;
        }
        
        public void Unregister()
        {
            HotKey hotKey;
            if (_dictHotKeyToCalBackProc.TryGetValue(Id, out hotKey))
            {
                UnregisterHotKey(IntPtr.Zero, Id);
            }
        }
        
        private static void ComponentDispatcherThreadFilterMessage(ref MSG msg, ref bool handled)
        {
            if (!handled)
            {
                if (msg.message == WmHotKey)
                {
                    HotKey hotKey;
                    if (_dictHotKeyToCalBackProc.TryGetValue((int)msg.wParam, out hotKey))
                    {
                        if (hotKey.Action != null)
                        {
                            hotKey.Action.Invoke(hotKey);
                        }
                        handled = true;
                    }
                }
            }
        }
        
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        
        protected virtual void Dispose(bool disposing)
        {
            if (!this._disposed)
            {
                if (disposing)
                {
                    Unregister();
                }
                _disposed = true;
            }
        }
    }
    
    [Flags]
    public enum KeyModifier
    {
        None = 0x0000,
        Alt = 0x0001,
        Ctrl = 0x0002,
        NoRepeat = 0x4000,
        Shift = 0x0004,
        Win = 0x0008
    }
}

使用示例:

_hotKey = new HotKey(Key.F9, KeyModifier.Shift | KeyModifier.Win, OnHotKeyHandler);
private void OnHotKeyHandler(HotKey hotKey)
{
    SystemHelper.SetScreenSaverRunning();
}

这个解决方案提供了一个HotKey类,用户可以使用该类来注册全局快捷键,并定义相应的操作。用户可以根据自己的需求修改和扩展该类。

0
0 Comments

问题的出现原因:

- 注册全局热键可以干扰用户的操作系统,用户不希望应用程序干扰他们的操作系统。

解决方法:

- 在App.xaml.cs文件中,重写OnStartup方法,并通过EventManager.RegisterClassHandler方法注册一个PreviewKeyUpEvent事件处理程序。

- 在OnWindowKeyUp方法中,可以使用e.Key和Keyboard.Modifiers来处理按键事件。

- 这种方法只在应用程序中有效,并且在应用程序关闭时会自动移除注册。

代码示例:

protected override void OnStartup(StartupEventArgs e)
{
   EventManager.RegisterClassHandler(typeof(Window), Window.PreviewKeyUpEvent, new KeyEventHandler(OnWindowKeyUp));
}
private void OnWindowKeyUp(object source, KeyEventArgs e)
{
   //Do whatever you like with e.Key and Keyboard.Modifiers
}

以上方法简单易行,并且提供了用户友好的方式来注册热键。同时,还指出了注册操作系统级别快捷键的不好之处。

0