.net中关于增加快捷键(热键)的方法,及UserControl中类似form的Active和Deactive事件

来源:互联网 发布:单片机电压测量电路 编辑:程序博客网 时间:2024/06/18 08:29

一、增加快捷键

1、使用windows api,主要的api及解释如下:

RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
UnregisterHotKey(IntPtr hWnd, int id);


其中关于id中在msdn中的描述如下:

An application must specify an id value in the range 0x0000 through 0xBFFF. 
A shared DLL must specify a value in the range 0xC000 through 0xFFFF (the range returned by the GlobalAddAtom function). 
To avoid conflicts with hot-key identifiers defined by other shared DLLs, 
a DLL should use the GlobalAddAtom function to obtain the hot-key identifier.


完整的代码段:

public partial class frmKeybordShortcuts : Form
    {
        int _myFindHotKeyId = 100;
        int _mySaveHotKeyId = 200;
        public frmKeybordShortcuts()
        {
            InitializeComponent();


            this.Load += frmKeybordShortcuts_Load;
            this.FormClosed += frmKeybordShortcuts_FormClosed;
        }


        /// <summary>
        /// 在这里进行快捷键注册工作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void frmKeybordShortcuts_Load(object sender, EventArgs e)
        {
            KeybordShortcutsWapper.RegisterHotKey(this, Keys.Control | Keys.F, this._myFindHotKeyId);
            KeybordShortcutsWapper.RegisterHotKey(this, Keys.Control | Keys.S, this._mySaveHotKeyId);
        }


        /// <summary>
        /// 在这里释放快捷键
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void frmKeybordShortcuts_FormClosed(object sender, FormClosedEventArgs e)
        {
            KeybordShortcutsWapper.UnregisterHotKey(this,this._myFindHotKeyId);
            KeybordShortcutsWapper.UnregisterHotKey(this, this._mySaveHotKeyId);
        }


        /// <summary>
        /// 这里的进行快捷键分派的处理方法
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == KeybordShortcutsWapper.WM_HOTKEY
                && m.HWnd == this.Handle)
            {
                if (m.WParam.ToInt32() == this._myFindHotKeyId) //根据注册时候不同id 对应的不同的快捷键进行快捷键分派
                {
                    MessageBox.Show("Control+F is pressed");
                }
                else if (m.WParam.ToInt32() == this._mySaveHotKeyId)
                {
                    MessageBox.Show("Control + S is pressed");
                }
            }


            base.WndProc(ref m);
        }


    }


    /// <summary>
    /// windows api 的一个包装器
    /// </summary>
    public class KeybordShortcutsWapper
    {
        private static int MOD_ALT = 0x1;
        private static int MOD_CONTROL = 0x2;
        private static int MOD_SHIFT = 0x4;
        private static int MOD_WIN = 0x8;
        public static int WM_HOTKEY = 0x312;


        /// <summary>
        /// Define a system-wide hot key.
        /// </summary>
        /// <param name="hWnd">
        /// A handle to the window that will receive WM_HOTKEY messages generated by the
        /// hot key. If this parameter is NULL, WM_HOTKEY messages are posted to the 
        /// message queue of the calling thread and must be processed in the message loop.
        /// </param>
        /// <param name="id">
        /// The identifier of the hot key. If the hWnd parameter is NULL, then the hot 
        /// key is associated with the current thread rather than with a particular 
        /// window. If a hot key already exists with the same hWnd and id parameters, 
        /// see Remarks for the action taken.
        /// </param>
        /// <param name="fsModifiers">
        /// The keys that must be pressed in combination with the key specified by the 
        /// uVirtKey parameter in order to generate the WM_HOTKEY message. The fsModifiers
        /// parameter can be a combination of the following values.
        /// MOD_ALT     0x0001
        /// MOD_CONTROL 0x0002
        /// MOD_SHIFT   0x0004
        /// MOD_WIN     0x0008
        /// </param>
        /// <param name="vk">The virtual-key code of the hot key.</param>
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool RegisterHotKey(IntPtr hWnd, int id,
            uint fsModifiers, uint vk);




        /// <summary>
        /// Frees a hot key previously registered by the calling thread. 
        /// </summary>
        /// <param name="hWnd">
        /// A handle to the window associated with the hot key to be freed. This parameter
        /// should be NULL if the hot key is not associated with a window.
        /// </param>
        /// <param name="id">
        /// The identifier of the hot key to be freed. 
        /// </param>
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);


        public static void RegisterHotKey(Form f, Keys key,int keyId)
        {
            int modifiers = 0;


            if ((key & Keys.Control) == Keys.Control)
                modifiers = modifiers | MOD_CONTROL;


            if ((key & Keys.Shift) == Keys.Shift)
                modifiers = modifiers | MOD_SHIFT;


            Keys k = 
                key 
                & ~Keys.Control //~符号表示按位取反,也会用在析构函数前对析构函数进行标识
                & ~Keys.Shift;


            RegisterHotKey(f.Handle, keyId, (uint)modifiers, (uint)k);            
        }


        public static void UnregisterHotKey(Form f,int keyId)
        {
            try
            {
                UnregisterHotKey(f.Handle, keyId);                
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
        }


2、重写ProcessCmdKey方法:

无论在窗体还是UserControl中都可以对ProcessCmdKey进行重写以达到自己想要的快捷键;

具体代码如下:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{

            var key = keyData & Keys.KeyCode;
            var modeifierKey = keyData & Keys.Modifiers;

if(modeifierKey  == Keys.Control && key==Keys.F)

{

MessageBox("Control+F is pressed");

return true;

}

//if ((keyData & Keys.Control) == Keys.Control

//&&(keyData & Keys.F) == Keys.F)

//{

//MessageBox.Show("Control + F is pressed");

//return true;

//}



return base.ProcessCmdKey(ref msg, keyData);
}

注意:快捷键能够被正常激活的条件是:这个窗体或者控件是焦点窗体或者控件

这里有个参考网址:http://www.codeguru.com/csharp/.net/net_general/keyboard/article.php/c4639/Building-Keyboard-Accelerators-into-NET-Windows-Forms-Applications.htm

综上所述:

设置快捷键时,要看快捷键是应用程序级的,还是系统级,如果是系统级的则用api方法,否则尽量使用重写方法实现;

再有,需要注意使用api注册快捷键(热键)时,可能会和系统中已经存在的其他应用的快捷键冲突,从而导致快捷键设置不起作用;

在重写ProcessCmdKey方法时,如果子容器和父容器(比如一个user control和一个form)中定义的快捷键相同(冲突),那么

当子容器中获得焦点后,父容器的快捷键将会被子容器的淹没;

==============================================================================================================

关于UserControl中类似Form的Active和Deactive事件:

分别是:Enter,Leave


0 0
原创粉丝点击