我怎么能注册一个全球性的热关键说CTRL+SHIFT+(母)使用WPF。净3.5?
题
我建立一个应用程序在C#使用WPF.我怎么可以结合到一些钥匙呢?
此外,我怎么可以绑定的 Windows键?
解决方案
我不知道你是什么意思通过的"全球"这里,但这里它会(我假设你指的是的一个命令,在程序一级,例如 保存所有 可以触发的任何地方的 Ctrl + 移位 + S.)
你找到全球 UIElement
你的选择,例如,顶级别窗口,它是母体的所有控制你在哪里需要这种结合。由于"泡泡"的WPF事件,事件在儿童元将泡沫的所有方式的根源的控制树。
现在,第一,你需要
- 绑定的关键组合的命令使用
InputBinding
像这样的 - 你可以随后转播命令你的处理程序(例如代码,被调通过
SaveAll
)通过CommandBinding
.
的 Windows 钥匙,你使用了正确的 关键 所列举的成员, 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.
}
其他提示
这是一个完整的工作方案,希望它能帮助...
使用:
_hotKey = new HotKey(Key.F9, KeyModifier.Shift | KeyModifier.Win, OnHotKeyHandler);
...
private void OnHotKeyHandler(HotKey hotKey)
{
SystemHelper.SetScreenSaverRunning();
}
级:
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
}
// ******************************************************************
}
如果你要混合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/en-us/library/ms927178.aspx
可能有一个更好的方式,但这是什么我有这么远。
干杯!
注册的操作系统级别的快捷方式是几乎没有一个良好的事情:用户不想让你惹他们的操作系统。
这就是说,有一个更简单和用户友好的方式这样做在WPF,如果你确定的热键工作内应用程序只(i。e只要你WPF应用程序具有重点):
在应用程序。停靠。cs:
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.
}
}
}
我已经找到它 fluxbytes.com.
虽然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"); } } } }
我不知道WPF,但这可能有帮助。我用中所描述的解决方案 RegisterHotKey(user32) (修改以我需要的课程)C#窗形式应用程序来分配CTRL-关键的组合内Windows带来了一个C#形成,它的工作精美的(即使在Windows Vista)。我希望它帮助和好运气!
我已经找到了 全球热键在WPF 项目codeproject.com 这不适合我的工作。这是相对较新,不需要一个参照系统。窗户。形式及工作的"全球"方面的反应来的热压甚至如果"您"应用不活动的窗口。
RegisterHotKey()
建议由约翰*可能的工作唯一的缺点是,它需要一个HWND(使用 PresentationSource.FromVisual()
, 和铸造的结果给一个HwndSource).
然而,还需要应对的 WM_HOTKEY
消息-我不确定如果有一种方法,以获得访问WndProc WPF窗口(其中可以适用于Windows的形式windows)。
狒狒的解决方案的工作最好的因为你可能有多个窗口。我做了调整,以便它使用PreviewKeyDownEvent而不是PreviewKeyUpEvent为了处理重复在按键。
我会建议反对操作系统级别的注册,除非你写的东西就像一个剪断工具或一个音记录应用程序,因为它会让你访问的功能时,窗户不是重点。
一个同事写了一样对如何创建一个低级别的键盘挂钩,被用于与WPF.
http://blogs.vertigo.com/personal/ralph/Blog/Lists/Posts/Post.aspx?ID=8