Il Framework .NET non fornisce metodi che consentono di
registrare HotKey a livello di sistema. In questo caso ci viene
in aiuto il Platform Invoke:
using System;using System.Runtime.InteropServices;using System.Collections.Generic;using System.Windows.Forms;namespace HotKey{ public class HotKeyHandler : NativeWindow, IDisposable { #region Platform Invoke [Flags] public enum Modifiers { NONE = 0, MOD_ALT = 0x01, MOD_CONTROL = 0x02, MOD_SHIFT = 0x04, MOD_WIN = 0x08 } private static readonly int WM_HOTKEY = 0x0312; [DllImport("user32.dll")] private static extern bool RegisterHotKey(IntPtr hWnd, int Id, int fsModifiers, int vlc); [DllImport("user32.dll")] private static extern bool UnregisterHotKey(IntPtr hWnd, int Id); #endregion private struct HotKeyInfo { public Keys Key; public Modifiers Modifier; public HotKeyInfo(Keys Key, Modifiers Modifier) { this.Key = Key; this.Modifier = Modifier; } public static bool operator==(HotKeyInfo HotKey1, HotKeyInfo HotKey2) { return ((HotKey1.Key == HotKey2.Key) && (HotKey1.Modifier == HotKey2.Modifier)); } public static bool operator !=(HotKeyInfo HotKey1, HotKeyInfo HotKey2) { return ((HotKey1.Key != HotKey2.Key) || (HotKey1.Modifier != HotKey2.Modifier)); } public override bool Equals(object obj) { if (obj == null || GetType() != obj.GetType()) return false; return this == (HotKeyInfo)obj; } public override int GetHashCode() { return base.GetHashCode(); } } private static int mLastID = 0; private Dictionary<int, HotKeyInfo> mHotKeys = null; public HotKeyHandler() { this.CreateHandle(new CreateParams()); mHotKeys = new Dictionary<int, HotKeyInfo>(); } public bool Register(Keys Key) { return this.Register(Key, Modifiers.NONE); } public bool Register(Keys Key, Modifiers Modifier) { mLastID++; //Registra la HotKey. if (RegisterHotKey(this.Handle, mLastID, (int)Modifier, (int)Key) == true) { //Se la registrazione ha avuto esito positivo, aggiunge la hotkey all'hashtable. //Questo serve per sapere quale hotkey è stata premuta, nel caso in cui ne //siano state registrate più di una. mHotKeys.Add(mLastID, new HotKeyInfo(Key, Modifier)); return true; } return false; } public void Unregister(Keys Key, Modifiers Modifier) { HotKeyInfo hotKey = new HotKeyInfo(Key, Modifier); if (mHotKeys.ContainsValue(hotKey)) { foreach (int ID in mHotKeys.Keys) { if (mHotKeys[ID] == hotKey) { UnregisterHotKey(this.Handle, ID); mHotKeys.Remove(ID); return; } } } } public void Unregister() { foreach (int ID in mHotKeys.Keys) UnregisterHotKey(this.Handle, ID); mHotKeys.Clear(); mLastID = 0; } #region Dispose private void FreeResources() { try { this.Unregister(); if (this.Handle != IntPtr.Zero) this.DestroyHandle(); } catch { } } ~HotKeyHandler() { this.FreeResources(); } public void Dispose() { this.FreeResources(); GC.SuppressFinalize(this); } #endregion public delegate void HotKeyPressedEventHandler(object sender, HotKeyPressedEventArgs e); //Evento che viene generato quando si preme una HotKey. public event HotKeyPressedEventHandler HotKeyPressed; protected override void WndProc(ref System.Windows.Forms.Message m) { if (m.Msg == HotKeyHandler.WM_HOTKEY) { //hID contiene l'ID della HotKey premuta. int hID = m.WParam.ToInt32(); if (mHotKeys.ContainsKey(hID)) { if (this.HotKeyPressed != null) this.HotKeyPressed(this, new HotKeyPressedEventArgs(mHotKeys[hID].Key, mHotKeys[hID].Modifier)); else base.WndProc(ref m); } else { base.WndProc(ref m); } } else { base.WndProc(ref m); } } } public class HotKeyPressedEventArgs : EventArgs { private Keys mKey; private HotKeyHandler.Modifiers mModifier; public HotKeyPressedEventArgs(Keys Key, HotKeyHandler.Modifiers Modifier) { mKey = Key; mModifier = Modifier; } public Keys Key { get { return mKey; } } public HotKeyHandler.Modifiers Modifier { get { return mModifier; } } }}
Dopo aver aggiunto questa classe al proprio progetto, per
utilizzarla è sufficiente scrivere, ad esempio:
using HotKey;//...HotKeyHandler HotKey = new HotKeyHandler();HotKey.Register(Keys.F12);HotKey.Register(Keys.Q, HotKeyHandler.Modifiers.MOD_ALT);HotKey.HotKeyPressed += new HotKeyHandler.HotKeyPressedEventHandler(HotKey_HotKeyPressed);private void HotKey_HotKeyPressed(object sender, HotKeyPressedEventArgs e){ if (e.Key == Keys.F12) { //... } else if (e.Key == Keys.Q && e.Modifier == HotKeyHandler.Modifiers.MOD_ALT) { //... }}
Infine, per una corretta esecuzione, è bene richiamare il
metodo Dispose dell'oggetto HotKeyHandler dopo aver terminato di lavorare con
esso (tipicamente in fase di chiusura dell'applicazione).
powered by IMHO 1.3