如何使用WPF和.NET 3.5注册一个全局热键以说CTRL + SHIFT +(LETTER)?
我在Cusing WPF中构建一个应用程序。如何绑定某些键?
另外,如何绑定Windows键?
解决方案
回答
我不确定WPF,但这可能会有所帮助。我使用了RegisterHotKey(user32)中描述的解决方案(根据我的需要进行了修改),用于CWindows Forms应用程序,以便在Windows中分配CTRL-KEY组合来生成Cform,并且效果很好(即使在Windows Vista中)。希望对我们有帮助,祝我们好运!
回答
John建议的RegisterHotKey()
可以起作用,唯一的问题是它需要HWND(使用PresentationSource.FromVisual()
,并将结果转换为HwndSource)。
但是,我们还需要响应" WM_HOTKEY"消息,我不确定是否可以通过某种方式访问WPF窗口的WndProc(这对于Windows Forms窗口是可行的)。
回答
我不确定我们在这里所说的"全局"是什么意思(但是我想假设我们是在应用程序级别指的是命令,例如,保存所有可以通过Ctrl + +从任何地方触发的命令) Shift+
S`。)
我们可以找到自己选择的全局" UIElement",例如,顶层窗口,该窗口是需要此绑定的所有控件的父级。由于WPF事件的"冒泡",子元素上的事件将一直冒泡直到控制树的根。
现在,首先我们需要
- 使用这样的" InputBinding"将键组合与命令绑定
- 然后可以通过CommandBinding将命令连接到处理程序(例如,由SaveAll调用的代码)。
对于Windows键,请使用正确的Key枚举成员Key.LWin或者Key.RWin。
public WindowMain() { InitializeComponent(); // Bind Key InputBinding ib = new InputBinding( MyAppCommands.SaveAll, new KeyGesture(Key.S, ModifierKeys.Shift | ModifierKeys.Control)); this.InputBindings.Add(ib); // Bind handler CommandBinding cb = new CommandBinding( MyAppCommands.SaveAll); cb.Executed += new ExecutedRoutedEventHandler( HandlerThatSavesEverthing ); this.CommandBindings.Add (cb ); } private void HandlerThatSavesEverthing (object obSender, ExecutedRoutedEventArgs e) { // Do the Save All thing here. }
回答
一位同事写了一个示例,说明如何创建与WPF一起使用的低级键盘挂钩。
http://blogs.vertigo.com/personal/ralph/Blog/Lists/Posts/Post.aspx?ID=8
回答
如果我们要混合使用Win32和WPF,请按以下步骤操作:
using System; using System.Runtime.InteropServices; using System.Windows.Interop; using System.Windows.Media; using System.Threading; using System.Windows; using System.Windows.Input; namespace GlobalKeyboardHook { public class KeyboardHandler : IDisposable { public const int WM_HOTKEY = 0x0312; public const int VIRTUALKEYCODE_FOR_CAPS_LOCK = 0x14; [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool UnregisterHotKey(IntPtr hWnd, int id); private readonly Window _mainWindow; WindowInteropHelper _host; public KeyboardHandler(Window mainWindow) { _mainWindow = mainWindow; _host = new WindowInteropHelper(_mainWindow); SetupHotKey(_host.Handle); ComponentDispatcher.ThreadPreprocessMessage += ComponentDispatcher_ThreadPreprocessMessage; } void ComponentDispatcher_ThreadPreprocessMessage(ref MSG msg, ref bool handled) { if (msg.message == WM_HOTKEY) { //Handle hot key kere } } private void SetupHotKey(IntPtr handle) { RegisterHotKey(handle, GetType().GetHashCode(), 0, VIRTUALKEYCODE_FOR_CAPS_LOCK); } public void Dispose() { UnregisterHotKey(_host.Handle, GetType().GetHashCode()); } } }
我们可以在此处获取要注册的热键的虚拟键代码:http://msdn.microsoft.com/zh-cn/library/ms927178.aspx
也许有更好的方法,但这是我到目前为止所掌握的。
干杯!
回答
尽管有时RegisterHotKey正是我们想要的,但在大多数情况下,我们可能不想使用系统范围的热键。我最终使用了如下代码:
using System.Windows; using System.Windows.Interop; namespace WpfApp { public partial class MainWindow : Window { const int WM_KEYUP = 0x0101; const int VK_RETURN = 0x0D; const int VK_LEFT = 0x25; public MainWindow() { this.InitializeComponent(); ComponentDispatcher.ThreadPreprocessMessage += ComponentDispatcher_ThreadPreprocessMessage; } void ComponentDispatcher_ThreadPreprocessMessage( ref MSG msg, ref bool handled) { if (msg.message == WM_KEYUP) { if ((int)msg.wParam == VK_RETURN) MessageBox.Show("RETURN was pressed"); if ((int)msg.wParam == VK_LEFT) MessageBox.Show("LEFT was pressed"); } } } }