2009.01.31 C# 快捷键 与接收消息 ——My First 技术博文

这几天在继续做个Application,用到了 快捷键 ,或者说是 组合键。

费了一天时间来研究这个。在网上找了好多资料都没能成功,连《C#程序开发范例宝典》这本书的第七章第12节的功能快捷键范例都没用,给的源码无法正确应用,让我很失望。

虽然在网上找的那些资料没有能成功运行,但是给我了一些启发,从很多源码中,我找到了以下的结果:

       

        AddMessageFilter (IMessageFilter value)方法

用于添加消息筛选器以便在向目标传送 Windows 消息时监视这些消息。

参数:value IMessageFilter 接口的实现(就是对象)

警告:向应用程序的消息泵添加消息筛选器会降低性能。

 

既然接受消息的方法已经找到了,那么接下来就需要一个API来注册快捷键,这个函数为:

[DllImport("user32.dll")]

public static extern UInt32 RegisterHotKey(IntPtr hWnd, UInt32 id, UInt32 fsModifiers, Keys vk);

hWnd:用于接收消息的句柄,一般是this

id:被注册的快捷键的ID,可以设置个ID,但不能重复,推荐用System.Guid.NewGuid()方法获得一个不易被重复的ID.

fsModifiers:快捷键的修饰键(如:Ctrl,AltCtrl+Alt等等),可以使用下面的一些值:

        public const int MOD_ALT = 0x1;        //Alt键,值为1

        public const int MOD_CONTROL = 0x2;    //Ctrl键值为2,如果要用Ctrl+Alt,直接用3就可以了

        public const int MOD_SHIFT = 0x4;      //Shift键值为4

vk:快捷键,如:Keys.A 具体可以查看MSDNKeys枚举。

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

接下来还必须要添加一个反注册快捷键的方法:

[DllImport("user32.dll")]

public static extern UInt32 UnregisterHotKey(IntPtr hWnd, UInt32 id);

hWnd:注册快捷键的窗体句柄。

id:被注册的快捷键的id。(把之前注册快捷键的id放进去就可以了)

 

刚才用AddMessageFilter方法让消息发给自己的程序,在反注册全部的快捷键后,如果不想让消息再被窗体接收,就该调用 RemoveMessageFilter (IMessageFilter value)

参数:       value: IMessageFilter 接口的实现

因为添加消息筛选器会增大系统开销,所以当不再接收消息的时候就要RemoveMessageFilter()

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

除此以外,有一个接口:IMessageFilter”, 我在MSDN中查到:这个接口可以处理消息,这用于是定义消息筛选器的接口。该接口只提供了一个方法PreFilterMessage,作用:在调度消息之前将其筛选出来。

bool PreFilterMessage (ref Message m)

参数m是程序接收到的消息,消息的Msg 属性如果为0x312 就是快捷键的消息,然后获取消息的WParam 字段,把该字段转换为整型,与设置过的快捷键的id比较,如果有相等,那就可以确定按下了这个快捷键,然后就可以调用相应的方法来实现接下来自己的要做的事。

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

 

有了上面的核心解释,就可以了,接下来把完整的代码发出来,以供参考。(源码部分东西是基于网上的摘抄,由于网上的资源比较乱,也不知道原作者了,故在这感谢XXXXXX

为方便使用,代码中还添加了一些其他的东西以方便使用(也就是说不是必须的)

 

using System;

using System.Collections.Generic;

using System.Text;

using System.Windows.Forms;

using System.Runtime.InteropServices;

 

namespace Or

{

    public delegate void HotkeyEventHandler(int HotKeyID);    

    public class Hotkey : IMessageFilter       //继承这个接口,才能用AddMessageFilter接收消息

    {

        System.Collections.Hashtable keyIDs = new System.Collections.Hashtable();

        IntPtr hWnd;

        public event HotkeyEventHandler OnHotkey;  //方便对快捷键进行处理

        public const int MOD_ALT = 0x1;

        public const int MOD_CONTROL = 0x2;

        public const int MOD_SHIFT = 0x4;

        public const int MOD_WIN = 0x8;

        public const int WM_HOTKEY = 0x312;    //按下快捷键消息的ID

 

        [DllImport("user32.dll")]

        public static extern UInt32 RegisterHotKey(IntPtr hWnd, UInt32 id, UInt32 fsModifiers, Keys vk);

        [DllImport("user32.dll")]

        public static extern UInt32 UnregisterHotKey(IntPtr hWnd, UInt32 id);

 

        [DllImport("kernel32.dll")]

        public static extern UInt32 GlobalAddAtom(String lpString);

        [DllImport("kernel32.dll")]

        public static extern UInt32 GlobalDeleteAtom(UInt32 nAtom);

 

        public Hotkey(IntPtr hWnd)

        {

            this.hWnd = hWnd;

            Application.AddMessageFilter(this);    //这样this才会收到消息

        }

        public int RegisterHotkey(Keys Key, UInt32 KeyModifiers)

        {

            UInt32 hotkeyid = GlobalAddAtom(System.Guid.NewGuid().ToString());

            RegisterHotKey((IntPtr)hWnd, hotkeyid, KeyModifiers, Key);

            keyIDs.Add(hotkeyid, hotkeyid);

            return (int)hotkeyid;

        }

        public void UnregisterHotkeys()

        {

            Application.RemoveMessageFilter(this);

            foreach (UInt32 key in keyIDs.Values)

            {

                UnregisterHotKey(hWnd, key);

                GlobalDeleteAtom(key);

            }

        }

        /// <summary>

        /// 消息过滤器

        /// </summary>

        /// <param name="m">收到的消息</param>

        /// <returns>如果筛选消息并禁止消息被调度,则为true;如果允许消息继续到达下一个筛选器或控件,则为false</returns>

        public bool PreFilterMessage(ref Message m)

        {

            if (m.Msg == WM_HOTKEY)

            {

                if (OnHotkey != null)

                {

                    foreach (UInt32 key in keyIDs.Values)

                    {

                        if ((UInt32)m.WParam == key)

                        {

                            OnHotkey((int)m.WParam);

                            return true;

                        }

                    }

                }

            }

            return false;

        }

    }

}

 

使用方法:

1.首先在类级别的位置定义Hotkey的一个方法名:

        Hotkey hk;

2.在快捷键注册方法内实例化

        public void HotkeyReg()

        {

            hk = new Hotkey(this.Handle);

            hk.RegisterHotkey(……); //这里选择自己的快捷键设置,方法返回该快捷键的ID

            hk.OnHotkey += new HotkeyEventHandler(hk_OnHotkey);  //绑定方法

        }

 

        void hk_OnHotkey(int HotKeyID)

        {

            MessageBox.Show(HotKeyID.ToString());

            //在这里添加if语句,用来处理不同的快捷键ID

        }

 

    这是我第一篇技术博文,有问题请指出,有建议请提出,谢谢。正在学习中。。。

Help each other.

!Or

2009-1-31 2:05:56

 

你可能感兴趣的:(windows,String,C#,user,application,程序开发)