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