Around and About .NET World

Il blog di Marco Minerva
posts - 1671, comments - 2232, trackbacks - 2135

My Links

News

Contattami su Live Messenger:


MCTS: Windows, Web, Distributed Applications & SQL Server

MCPD: Enterprise Applications

Tag Cloud

Archives

Post Categories

Links

Gestire le HotKey con C#

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(thisnew 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

Print | posted on Sunday, July 2, 2006 4:30 PM | Filed Under [ C# ]

Feedback

Gravatar

# re: Gestire le HotKey con C#

Bel codice, complimenti ! Hai aggiunto un pezzo mancante al framework ...
9/28/2006 11:10 AM | Stefano
Gravatar

# re: Gestire le HotKey con C#

Grazie! Sono contento di averti aiutato!
9/28/2006 11:19 AM | Marco Minerva
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET