C# 我如何注册一个全局热键来表示CTRL+;班次+;(信件)使用WPF和.NET3.5?
我正在用WPF在C#中构建一个应用程序。我怎样才能绑定到一些钥匙上C# 我如何注册一个全局热键来表示CTRL+;班次+;(信件)使用WPF和.NET3.5?,c#,.net,wpf,windows,hotkeys,C#,.net,Wpf,Windows,Hotkeys,我正在用WPF在C#中构建一个应用程序。我怎样才能绑定到一些钥匙上 另外,如何绑定到?我不确定WPF,但这可能会有所帮助。我使用了中描述的解决方案(当然根据我的需要进行了修改),用于C#Windows窗体应用程序,在Windows中分配一个CTRL-KEY组合以显示C#窗体,它工作得很好(即使在Windows Vista上也是如此)。我希望这会有帮助,祝你好运 John建议的RegisterHotKey()可能有效-唯一的问题是它需要一个HWND(使用PresentationSource.Fro
另外,如何绑定到?我不确定WPF,但这可能会有所帮助。我使用了中描述的解决方案(当然根据我的需要进行了修改),用于C#Windows窗体应用程序,在Windows中分配一个CTRL-KEY组合以显示C#窗体,它工作得很好(即使在Windows Vista上也是如此)。我希望这会有帮助,祝你好运 John建议的RegisterHotKey()可能有效-唯一的问题是它需要一个HWND(使用
PresentationSource.FromVisual()
,并将结果强制转换为HwndSource)
但是,您还需要响应
WM_热键
消息-我不确定是否有办法访问WPF窗口的WndProc(这可以在Windows窗体窗口中完成)。我不确定您在这里所说的“全局”是什么意思,但它就在这里(我假设您指的是应用程序级别的命令,例如,保存所有可以通过Ctrl+Shift+S从任何位置触发的命令。)
您可以找到您选择的全局UIElement
,例如,顶层窗口,它是需要此绑定的所有控件的父级。由于WPF事件“冒泡”,子元素上的事件将一直冒泡到控件树的根
现在,首先你需要
InputBinding
命令绑定键组合CommandBinding
将命令连接到处理程序(例如,SaveAll
调用的代码)Key.LWin
或Key.RWin
public WindowMain()
{
InitializeComponent();
// Bind Key
var ib = new InputBinding(
MyAppCommands.SaveAll,
new KeyGesture(Key.S, ModifierKeys.Shift | ModifierKeys.Control));
this.InputBindings.Add(ib);
// Bind handler
var 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.
}
如果要混合使用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());
}
}
}
您可以在此处获取要注册的热键的虚拟密钥代码:
也许有更好的办法,但这就是我目前所知道的
干杯!尽管有时RegisterHotKey正是您想要的,但在大多数情况下,您可能不想使用系统范围的热键。我最终使用了如下代码:
使用System.Windows;
使用System.Windows.Interop;
名称空间WpfApp
{
公共部分类主窗口:窗口
{
常数int WM_KEYUP=0x0101;
const int VK_RETURN=0x0D;
const int VK_LEFT=0x25;
公共主窗口()
{
this.InitializeComponent();
ComponentDispatcher.ThreadPreprocessMessage+=
组件调度程序线程预处理消息;
}
无效组件Dispatcher\u线程预处理消息(
ref MSG MSG,ref bool(已处理)
{
如果(msg.message==WM\u KEYUP)
{
if((int)msg.wParam==VK_RETURN)
MessageBox.Show(“返回被按下”);
if((int)msg.wParam==VK_左)
MessageBox.Show(“按下左键”);
}
}
}
}
这是一个完整的工作解决方案,希望对您有所帮助
用法:
_hotKey = new HotKey(Key.F9, KeyModifier.Shift | KeyModifier.Win, OnHotKeyHandler);
类别:
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<int, HotKey> _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<HotKey> Action { get; private set; }
public int Id { get; set; }
// ******************************************************************
public HotKey(Key k, KeyModifier keyModifiers, Action<HotKey> 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<int, HotKey>();
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;
}
}
}
}
// ******************************************************************
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
// ******************************************************************
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be _disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be _disposed.
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if (!this._disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if (disposing)
{
// Dispose managed resources.
Unregister();
}
// Note disposing has been done.
_disposed = true;
}
}
}
// ******************************************************************
[Flags]
public enum KeyModifier
{
None = 0x0000,
Alt = 0x0001,
Ctrl = 0x0002,
NoRepeat = 0x4000,
Shift = 0x0004,
Win = 0x0008
}
// ******************************************************************
}
使用系统;
使用System.Collections.Generic;
使用系统诊断;
使用System.Linq;
使用System.Net.Mime;
使用System.Runtime.InteropServices;
使用系统文本;
使用System.Windows;
使用System.Windows.Input;
使用System.Windows.Interop;
命名空间非托管
{
公共类热键:IDisposable
{
专用静态字典_dictHotKeyToCalBackProc;
[DllImport(“user32.dll”)]
专用静态外部bool寄存器hotkey(IntPtr hWnd、int id、UInt32 fsModifiers、UInt32 vlc);
[DllImport(“user32.dll”)]
私有静态外部bool unregister热键(IntPtr hWnd,intid);
public const int WmHotKey=0x0312;
private bool_disposed=false;
公钥{get;private set;}
public KeyModifier KeyModifier{get;private set;}
公共操作操作{get;private set;}
公共int Id{get;set;}
// ******************************************************************
公用热键(键k、键修改器、键修改器、动作动作、布尔寄存器=true)
{
Key=k;
KeyModifiers=KeyModifiers;
行动=行动;
如果(注册)
{
寄存器();
}
}
// ******************************************************************
公共布尔寄存器()
{
int virtualKeyCode=KeyInterop.VirtualKeyFromKey(键);
Id=virtualKeyCode+((int)键修饰符*0x10000);
bool result=RegisterHotKey(IntPtr.Zero,Id,(UInt32)键修饰符,(UInt32)虚拟代码);
如果(_dictHotKeyToCalBackProc==null)
{
_dictHotKeyToCalBackProc=新字典();
ComponentDispatcher.ThreadFilterMessage+=新的ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage);
}
_dictHotKeyToCalBackProc.Add(Id,this);
Debug.Print(result.ToString()+”、“+Id+”、“+virtualKeyCode”);
返回结果;
}
// ******************************************************************
公共作废注销()
{
热键热键;
if(_dictHotKeyToCalBackProc.TryGetValue(Id,out热键))
{
取消注册热键(IntPtr.Zero,Id);
}
}
// ******************************************************************
私有静态无效组件DispatcherThreadFilterMessage(ref MSG MSG,ref bool handled)
{
如果(!已处理)
{
如果(msg.message==WmHotKey)
{
热键热键;
如果(_dictHotKeyToCalBackProc.TryGetValue((
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<int, HotKey> _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<HotKey> Action { get; private set; }
public int Id { get; set; }
// ******************************************************************
public HotKey(Key k, KeyModifier keyModifiers, Action<HotKey> 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<int, HotKey>();
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;
}
}
}
}
// ******************************************************************
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
// ******************************************************************
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be _disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be _disposed.
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if (!this._disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if (disposing)
{
// Dispose managed resources.
Unregister();
}
// Note disposing has been done.
_disposed = true;
}
}
}
// ******************************************************************
[Flags]
public enum KeyModifier
{
None = 0x0000,
Alt = 0x0001,
Ctrl = 0x0002,
NoRepeat = 0x4000,
Shift = 0x0004,
Win = 0x0008
}
// ******************************************************************
}
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
}
using System;
using System.Windows.Forms;
namespace GlobalHotkeyExampleForm
{
public partial class ExampleForm : Form
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
enum KeyModifier
{
None = 0,
Alt = 1,
Control = 2,
Shift = 4,
WinKey = 8
}
public ExampleForm()
{
InitializeComponent();
int id = 0; // The id of the hotkey.
RegisterHotKey(this.Handle, id, (int)KeyModifier.Shift, Keys.A.GetHashCode()); // Register Shift + A as global hotkey.
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0x0312)
{
/* Note that the three lines below are not needed if you only want to register one hotkey.
* The below lines are useful in case you want to register multiple keys, which you can use a switch with the id as argument, or if you want to know which key/modifier was pressed for some particular reason. */
Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF); // The key of the hotkey that was pressed.
KeyModifier modifier = (KeyModifier)((int)m.LParam & 0xFFFF); // The modifier of the hotkey that was pressed.
int id = m.WParam.ToInt32(); // The id of the hotkey that was pressed.
MessageBox.Show("Hotkey has been pressed!");
// do something
}
}
private void ExampleForm_FormClosing(object sender, FormClosingEventArgs e)
{
UnregisterHotKey(this.Handle, 0); // Unregister hotkey with id 0 before closing the form. You might want to call this more than once with different id values if you are planning to register more than one hotkey.
}
}
}
<KeyBinding Gesture="Ctrl+Alt+Add" Command="{Binding IncrementCommand}" />
<KeyBinding Gesture="Ctrl+Alt+Add" Command="{Binding IncrementCommand}"
HotkeyManager.RegisterGlobalHotkey="True" />