Im building an app in c# using WPF and i need it to bind to some keys. Ive found some links but not work well with my setup. Anyone done this before?
also if i could bind to the windows key would be great.
Im building an app in c# using WPF and i need it to bind to some keys. Ive found some links but not work well with my setup. Anyone done this before?
also if i could bind to the windows key would be great.
I'm not sure about WPF, but this may help...I used this solution (modified to my needs of course) for a c# Windows forms application to assign a CTRL-KEY combination within Windows to bring up a c# form and it worked beautifully (even on Windows Vista). Hope it helps and good luck!
http://www.pinvoke.net/default.aspx/user32/RegisterHotKey.html
RegisterHotKey()
suggested by John could work - the only catch is that it requires an HWND (using PresentationSource.FromVisual()
, and casting the result to an HwndSource), however you'll also need to respond to the WM_HOTKEY
message - I'm not sure if there is a way to get access to the WndProc of a WPF window or not (which can be done for WinForms windows).
You might take a look at Scott Hanselman's BabySmash series and the BabySmash source. I don't know anything about WPF, but some of the blog posts in the series I linked discussed key bindings and limitations in WPF.
I'm not sure of what you mean by "global" here but here goes (I'm assuming you mean a command at the application level e.g. Save All that can be triggered from anywhere by Ctrl+Shift+S
You find the global UIElement of your choice e.g. the top level window which is the parent of all the controls where you need this binding. Due to "bubbling" of WPF events, events at child elements will bubble all the way up to the root of the control tree. Now first you need
For the Windows Key, you use the right Key enumerated member, Key.LWin or 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
}
A co-worker wrote a sample on how to create a low-level keyboard hook to be used WPF.
If you're going to mix Win32 and WPF, here's how I did it:
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());
}
}
}
You can get the virtual-key code for the hotkey you want to register here: http://msdn.microsoft.com/en-us/library/ms927178.aspx
There may be a better way, but this is what I've got so far.
Cheers!