There can be no Triumph without Loss,No Victory without Suffering,No Freedom without Sacrifice.
All you have to decide is what to do with the time that is given to you.
Get busy Living, or Get busy Dying?
  首页 | 留言给我 | 订阅 Rss | CLI | 黄白之恋 Posts:158   Hits: 5070810    Comments: 173    
 日历归档
<<  <  2024 - 04  >  >>
SuMoTuWeThFrSa
 123456
78910111213
14151617181920
21222324252627
282930
 About Me
 Name: ZhangSichu
 Sex: Male
 Age: 32
 Email: ZhangSichu@gmail.com
 MSN: ZhangSichu@hotmail.com
 Home: ZhangSichu.com
 WeiBo: weibo.com/zhangsichu
 个人推荐
 分类归档
  ·C++/C(5)  RSS
  ·软件工程(1)  RSS
  ·杂事/随感(26)  RSS
  ·.Net/Java(30)  RSS
  ·面向对象程序设计(5)  RSS
  ·汇编/破解(0)  RSS
  ·平面设计(3)  RSS
  ·SQL(5)  RSS
  ·COM/COM+(2)  RSS
  ·Web开发(81)  RSS
 My Friends
Back Forward Refresh Home 2024年4月24日 星期三 RSS CLI Mine Sweeper. In Javascript.

  .Net 下全局HotKey Register & Unregister
字体大小 [ ]

本文介绍了,在.Net下实现,用系统API注册系统HotKey的全过程。将系统的WM_HOTKEY Message包装成了一个.Net下的Event(用户定义的HotKeyPress Event)。同时简化了系统HotKey的注册过程。

HotKey的注册原理:

注册一个HotKey需要下面2个步骤:
1. [DllImport("kernel32")]
    internal static extern IntPtr GlobalAddAtom(string lpString
      );

  GlobalAddAtom是一个系统提供的API,在Kernel32.dll下,这个方法将注册一个字符串到系统的Global Atom Table中,并返回一个唯一的intPtr指示识别这个字符串。
2. [DllImport("user32")]
    internal static extern bool RegisterHotKey(IntPtr hWnd,
      int id,
      uint fsModifiers,
      uint vk
      );

  RegisterHotKey 是一个系统提供的API,在user32.dll下,这个方法将注册一个HotKey。注册HotKey时需要使用一个AtomID-----一个系统唯一的标识来注册这个HotKey,当HotKey按下时,系统会发出一个WM_HOTKEY的Message给注册这个HotKey的Application。当这个Application收到消息后作自己想要的操作。

HotKey的使用方法:
  本文已经包装了HotKey的WM_HOTKEY 系统Message为HotKeyPressed PrintWindowPressed PrintDesktopPressed 事件(用户定义的事件),注册HotKey时,使用类似this.HotKeys.Add(new HotKeyController.HotKey("Ctrl+O",Keys.O,HotKey.HotKeyModifiers.MOD_CONTROL));来注册这个HotKey。
  需要处理HotKey时使用private void MainForm_HotKeyPressed(object sender, HotKeyController.HotKeyPressedEventArgs e) 来处理HotKeyEvent。进行自己想做的操作。

部分核心代码:

1. 使用到的系统API
using System;
using System.Runtime.InteropServices;
namespace HotKeyController
{
  public class HotKeyUnmanagedMethods
  {
    public HotKeyUnmanagedMethods()
    {
    }

    ~ HotKeyUnmanagedMethods()
    {
    }

    internal static int WM_HOTKEY = 0x312;

    [DllImport("user32")]
    internal static extern bool RegisterHotKey(IntPtr hWnd,
      int id,
      uint fsModifiers,
      uint vk
      );

    [DllImport("user32")]
    internal static extern bool UnregisterHotKey(IntPtr hWnd,
      int id
      );

    [DllImport("kernel32")]
    internal static extern IntPtr GlobalAddAtom(string lpString
      );

    [DllImport("kernel32")]
    internal static extern IntPtr GlobalDeleteAtom(IntPtr nAtom
      );

    [DllImport("kernel32")]
    internal static extern uint GetTickCount();

  }
}

2.HotKey类 封装HotKey
using System;
using System.Windows.Forms;
namespace HotKeyController
{
  public class HotKey
  {
    #region Public Field

    #region KeyType
    [Flags()]
    public enum HotKeyModifiers
    {
      MOD_ALT = 0x1,
      MOD_CONTROL = 0x2,
      MOD_SHIFT = 0x4,
      MOD_WIN = 0x8,
    }
    #endregion

    public HotKey(string name,Keys keyCode,HotKeyModifiers modifiers)
    {
      this._name = name;
      this._keyCode = keyCode;
      this._modifiers = modifiers;
    }

    public HotKey()
    {
    }

    ~HotKey()
    {
    }

    //The hot key is or not valiable.
    public void Validate()
    {
      string message = "";
      if(this._name.Trim().Length == 0)
      {
        message = "A hotkey need a name.";
      }
      if(this._keyCode == Keys.Alt || this._keyCode == Keys.Control ||
        this._keyCode == Keys.Shift || this._keyCode == Keys.ShiftKey ||
        this._keyCode == Keys.ControlKey)
      {
        message = "The keycode cannot be set to a modifier key.";
      }
      if(message.Length > 0)
      {
        throw new HotKeyException(this,message);
      }
    }

    public string Name
    {
      get
      {
        return this._name;
      }
      set
      {
        this._name = value;
      }
    }
    public Keys KeyCode
    {
      get
      {
        return this._keyCode;
      }
      set
      {
        this._keyCode = value;
      }
    }
    public HotKeyModifiers Modifiers
    {
      get
      {
        return this._modifiers;
      }
      set
      {
        this._modifiers = value;
      }
    }
    #endregion

    #region Private Field
    private string _name;
    private string _atomName;
    private IntPtr _atomId;
    private Keys _keyCode;
    private HotKeyModifiers _modifiers;
    #endregion

    #region Internal Field

    //The Atom id will regist to the global system table.
    internal IntPtr AtomId
    {
      get
      {
        return this._atomId;
      }
      set
      {
        this._atomId = value;
      }
    }

    //The global atom name.
    internal string AtomName
    {
      get
      {
        return this._atomName;
      }
      set
      {
        this._atomName = value;
      }
    }
    #endregion
  }

}

3.HotKey Collection HotKey 的集合 存储管理 所有注册的HotKey
using System;
namespace HotKeyController
{
  public class HotKeyCollection:System.Collections.CollectionBase
  {
    #region Public Field

    //the hot key collections owner form.
    public HotKeyCollection(System.Windows.Forms.Form ownerForm)
    {
      this._ownerForm = ownerForm;
    }

    //Get a hot key.
    public HotKey this[int index]
    {
      get
      {
        return (HotKey)this.InnerList[index];
      }
    }

    //Add a hot key.
    public void Add(HotKey hotKey)
    {
      hotKey.Validate();
      this.AddHotKey(hotKey);
      this.InnerList.Add(hotKey);
    }

    //Remove a hot key.
    public void Remove(HotKey hotKey)
    {
      hotKey.Validate();
      this.RemoveHotKey(hotKey);
      this.InnerList.Remove(hotKey);
    }

    public void Remove(int index)
    {
      if(index>=this.InnerList.Count)
      {
        return;
      }
      else
      {
        this.RemoveHotKey((HotKey)this.InnerList[index]);
        this.InnerList.RemoveAt(index);
      }
    }

    public void RemoveAll()
    {
      while(this.InnerList.Count>0)
      {
        this.RemoveHotKey((HotKey)this.InnerList[0]);
        this.InnerList.RemoveAt(0);
      }
    }
    #endregion

    #region Private Field
    private System.Windows.Forms.Form _ownerForm;

    //Real add a hot key to system, use unmanagement methods.
    private void AddHotKey(HotKey hotKey)
    {
      string atomName;
      IntPtr atomId;
      bool registered;

      //get a atom name
      atomName = hotKey.Name + "_" + HotKeyUnmanagedMethods.GetTickCount().ToString();
      if(atomName.Length > 255)
      {
        atomName = atomName.Substring(0,255);
      }
      atomId = HotKeyUnmanagedMethods.GlobalAddAtom(atomName);
      
      //get a tom id
      if(atomId.Equals(IntPtr.Zero))
      {
        throw new HotKeyException(hotKey,"Failed to add a global atom for this HotKey");
      }
      else
      {
        //regist a hot key.
        registered = HotKeyUnmanagedMethods.RegisterHotKey(this._ownerForm.Handle,atomId.ToInt32(),System.Convert.ToUInt32(hotKey.Modifiers), System.Convert.ToUInt32(hotKey.KeyCode));
        if(!registered)
        {
          //unsuccessful.
          HotKeyUnmanagedMethods.GlobalDeleteAtom(atomId);
          throw new HotKeyException(hotKey,"Failed to register this HotKey");
        }
        else
        {
          //successful.
          hotKey.AtomName = atomName;
          hotKey.AtomId = atomId;
        }
      }
      
    }
    //Real remove a hot key, use unmanagement methods.
    private void RemoveHotKey(HotKey hotKey)
    {
      // remove the hot key:
      HotKeyUnmanagedMethods.UnregisterHotKey(this._ownerForm.Handle, hotKey.AtomId.ToInt32());
      // unregister the atom:
      HotKeyUnmanagedMethods.GlobalDeleteAtom(hotKey.AtomId);
    }
    #endregion

    #region Protected Method
    //Clean all hot keys.
    protected override void OnClear()
    {
      foreach(HotKey hotKey in this.InnerList)
      {
        this.RemoveHotKey(hotKey);
      }
      base.OnClear ();
    }

    protected override void OnInsert(int index, object value)
    {
      if(value.GetType().IsInstanceOfType(new HotKey()))
      {
        ((HotKey)value).Validate();
        this.AddHotKey((HotKey)value);
        base.OnInsert (index, value);
      }
      else
      {
        throw new InvalidCastException("The want to insert object is no a hotkey");
      }
    }

    protected override void OnRemove(int index, object value)
    {
      if(value.GetType().IsInstanceOfType(new HotKey()))
      {
        this.RemoveHotKey((HotKey)value);
        base.OnRemove(index, value);
      }
      else
      {
        throw new InvalidCastException("The want to remove object is no a hotkey");
      }      
    }

    protected override void OnSet(int index, object oldValue, object newValue)
    {
      HotKey hotKey;
      hotKey = new HotKey();

      if(oldValue.GetType().IsInstanceOfType(hotKey)&&newValue.GetType().IsInstanceOfType(newValue))
      {
        base.OnSet (index, ((HotKey)oldValue), ((HotKey)newValue));
      }
      else
      {
        throw new InvalidCastException("The want to set object is no a hotkey");
      }  
      
    }

    protected override void OnValidate(object value)
    {
      ((HotKey)value).Validate();
    }

    #endregion
  }
}
其中的 Private AddHotKey RemoveHotKey 调用了 系统的API 真正的注册一个HotKey 注销 一个HotKey。

4.HotKey Controller 重写窗体的WndProc方法 接收WM_HOTKEY Message 同时触发 HotKey Event 供Controller 的父类接收处理
using System;
namespace HotKeyController
{
  public delegate void HotKeyPressedEventHandler(object sender, HotKeyPressedEventArgs e);

  public class HotKeyController : System.Windows.Forms.Form
  {
    #region Public Field
    public HotKeyController()
    {
      this._hotKeys = new HotKeyCollection(this);
    }

    ~HotKeyController()
    {
      this._hotKeys.Clear();
    }
    public event HotKeyPressedEventHandler HotKeyPressed;
    public HotKeyCollection HotKeys
    {
      get
      {
        return this._hotKeys;
      }
    }
    #endregion

    #region Private Field
    private HotKeyCollection _hotKeys;
    protected override void WndProc(ref System.Windows.Forms.Message m)
    {
      base.WndProc (ref m);
      if (m.Msg == HotKeyUnmanagedMethods.WM_HOTKEY)
      {
        foreach (HotKey hotKey in this._hotKeys)
        {
          if (hotKey.AtomId.Equals(m.WParam))
          {
            HotKeyPressedEventArgs hotKeyArgs = new HotKeyPressedEventArgs(hotKey);
            if (this.HotKeyPressed != null)
            {
              this.HotKeyPressed(this, hotKeyArgs);
            }
          }
        }
      }
    }
    #endregion
  }
}

5.HotKeyController 父类窗体对HotKey 的处理
添加事件处理方法
this.HotKeyPressed +=new HotKeyPressedEventHandler(MainForm_HotKeyPressed);
从HotKeyPressedEventArgs中得到Press的HotKey
private void MainForm_HotKeyPressed(object sender, HotKeyController.HotKeyPressedEventArgs e)
    {
      if(e.PressedHotKey!= null)
      {
        MessageBox.Show("Hot key "+e.PressedHotKey.Name +" Pressed","A hot key pressed",MessageBoxButtons.OK,MessageBoxIcon.Information);
      }
    }

File: 本文实例代码
  Posted @ 1/26/2006 9:17:08 AM | Hits (78264) | Comment (0

  Post Comment
标题 *
作者 *
密码 记住我
评论 *
    


Stable in Firefox 1.5 2.0Stable in IE6 IE7Stable in MozillaStable in Netscape
ZhangSichu.com V0.1.7507
Powered By ZhangSichu
Copyright © ZhangSichu
Download ZhangSichu.com source code. Download source code