【问题标题】:Trying to use (System-Wide) Hotkeys in WPF/C#尝试在 WPF/C# 中使用(系统范围的)热键
【发布时间】:2012-01-04 05:44:09
【问题描述】:

我一直在尝试在我最新的 WPF/C# 项目中使用系统范围/全局热键。幸运的是,我在这里遇到了这门精彩的课程 - http://www.codeproject.com/Tips/274003/Global-Hotkeys-in-WPF

唯一的问题是,我无法让它工作。自上周以来,我一直在努力解决这个问题,奇怪的是,我没有遇到任何错误。这是我的代码,有什么想法吗?

HotKey hotkey = new HotKey((System.Windows.Interop.HwndSource)System.Windows.Interop.HwndSource.FromVisual(App.Current.MainWindow));
                //hotkey.Modifiers = list[i]._HotkeyA.Modifier; hotkey.Key = list[i]._HotkeyA._Key;
                hotkey.Modifiers = HotKey.ModifierKeys.Shift; hotkey.Key = Key.F2;
                hotkey.HotKeyPressed += new EventHandler<HotKeyEventArgs>(delegate(Object o, HotKeyEventArgs e)
                {
                    Console.WriteLine("Congratulations, Cap'n.");
                    System.Windows.Forms.MessageBox.Show("YAAY HOTKEY HAZ BEEN TEH PRESSEDS!");
                });
                hotkey.Enabled = true;

提前致谢!

【问题讨论】:

  • 我使用了命令和绑定方法,这里有一个例子stackoverflow.com/questions/2382916/…
  • 谢谢,但我的意思是系统范围的热键。
  • 您使用 System.Windows.Input.Key.F2 还是它的 WindowsForms“兄弟”?

标签: c# wpf


【解决方案1】:

以下实现使用 WPF ComponentDispatcher 类来调度 Windows 消息。

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;

[Flags]
public enum ModifierKeyCodes : uint
{
    Alt = 1,
    Control = 2,
    Shift = 4,
    Windows = 8
}

/// <summary>
/// Virtual Key Codes
/// </summary>
public enum VirtualKeyCodes : uint
{
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90
}

class KeyboardHook : IDisposable
{
[DllImport("user32.dll")]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);

[DllImport("user32.dll")]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, ModifierKeyCodes fdModifiers, VirtualKeyCodes vk);

#region Fields
WindowInteropHelper host;
bool IsDisposed = false;
int Identifier;

public Window Window { get; private set; }

public VirtualKeyCodes Key { get; private set; }

public ModifierKeyCodes Modifiers { get; private set; }
#endregion

public KeyboardHook(Window Window, VirtualKeyCodes Key, ModifierKeyCodes Modifiers)
{
    this.Key = Key;
    this.Modifiers = Modifiers;

    this.Window = Window;
    host = new WindowInteropHelper(Window);

    Identifier = Window.GetHashCode();

    RegisterHotKey(host.Handle, Identifier, Modifiers, Key);

    ComponentDispatcher.ThreadPreprocessMessage += ProcessMessage;
}

void ProcessMessage(ref MSG msg, ref bool handled)
{
    if ((msg.message == 786) && (msg.wParam.ToInt32() == Identifier) && (Triggered != null))
        Triggered();
}

public event Action Triggered;

public void Dispose()
{
    if (!IsDisposed)
    {
        ComponentDispatcher.ThreadPreprocessMessage -= ProcessMessage;

        UnregisterHotKey(host.Handle, Identifier);
        Window = null;
        host = null;
    }
    IsDisposed = true;
}
}

释放对象会取消注册热键。 您需要保留对 KeyboardHook 类的引用以防止它被注销。

例子:

// Registers a Hook to MyWindow - Ctrl+A and calls DoWork() when Triggered.
var KH = new KeyboardHook(MyWindow, VirtualKeyCodes.A, ModifierKeyCodes.Ctrl);
KH += () => DoWork();

// When you don't need the Hook
KH.Dispose();

【讨论】:

  • 不错!我有一段时间没有使用 C#,但这看起来很方便。
  • @un-lucky 不确定。完成。
【解决方案2】:

确保您对该 HotKey 有很强的引用。从您提供的链接中,该对象有一个终结器,它将 Enabled 设置为 false,这将取消注册热键。

【讨论】:

  • 请注意,如果这不是问题,请发布更完整的 sn-p 用法 - 即创建热键的位置等。
猜你喜欢
  • 2012-05-30
  • 2011-04-15
  • 1970-01-01
  • 2012-04-30
  • 1970-01-01
  • 2013-12-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多