在WPF中如何注册热键(转)

 

WPF注册热键大荟萃

 

源码下载:http://www.cnblogs.com/dabaopku/archive/2010/02/22/1671267.html

 

研究了一晚上,终于搞定了啦~~~~~

 

首先完整复制下面的第一篇文章中的代码

 

  

然后以下代码是

  

private void Register(object sender, RoutedEventArgs e)
 {
IntPtr handle=new WindowInteropHelper(this).Handle;
int id = 1000;
bool r=HotKey.RegisterHotKey(handle, id,(uint)HotKey.KeyFlags.MOD_CONTROL, (uint)System.Windows.Forms.Keys.F12);
 MessageBox.Show(r.ToString()+" "+handle.ToString()+" ");
HotKey.InstallHotKeyHook(this);
}

 

其中Id随意取值,好像都没有问题

  

一直受第三篇文章干扰(说实在的,确实让人恼火,它的RegisterHotkey(Keys Key, KeyFlags keyflags)

 


明明是Key在前 keyflags在后,可是带入APi的

 

结底还是自己不够细心,足足浪费了半小时,郁闷!)

RegisterHotKey后却是反过来的,结果我也跟着他的弄反了control和F12,归根

 

  

然后反注册就很简单了,唉,累死了~~

 

 

 

在WPF中如何注册热键

来源:http://www.cnblogs.com/zengezenge/archive/2009/07/09/1519582.html

不说废话,直接看代码吧,其关键就是 System.Windows.Interop.HwndSource类。

第一步:注册热键,需要使用API函数,具体的参照网上的其它文章。唯一需要注意的是需要使用KeyInterop.VirtualKeyFromKey函数将

WPF的Key枚举转化为API函数可以使用的VirtualKeyCode :


     /// <summary>
        
/// 注册热键处理函数
        
/// </summary>
        
/// <param name="hWnd">用于处理热键消息的窗体句柄</param>
        
/// <param name="id">热键的编号</param>
        
/// <param name="controlKey">控制键</param>
        
/// <param name="virtualKey">热键的虚键编码</param>
        
/// <returns>
        
///     <c>true</c>:注册成功<br/>
        
///     <c>false</c>:注册失败
        
/// </returns>
        
/// <remarks></remarks>
        
/// <history>
        
/// [ZengE]               2009-7-8 22:28    创建
        
/// </history>
        [System.Runtime.InteropServices.DllImport("user32")]
        
public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint controlKey, uint virtualKey);

        
/// <summary>
        
/// 注销指定的热键
        
/// </summary>
        
/// <param name="hWnd">用于处理热键消息的窗体句柄</param>
        
/// <param name="id">要注销的热键编号</param>
        
/// <returns>
        
///     <c>true</c>:注销成功<br/>
        
///     <c>false</c>:注销失败
        
/// </returns>
        
/// <remarks></remarks>
        
/// <history>
        
/// [ZengE]               2009-7-8 22:30    创建
        
/// </history>
        [System.Runtime.InteropServices.DllImport("user32")]
        
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);

 第二步:注册热键处理函数,主要的难点就在这里,在.NET的WinForm程序中一般使用重写Form的WinProc方法或者注册IMessageFilter来实现的,

但是在WPF中以上两种方式都无法获得热键消息的处理机会,除非是在WPF程序中隐藏一个常规的Form(最开始就是这么弄得,后来觉得实在是太丑陋了)


 1        /// <summary>
 2        /// 安装热键处理挂钩
 3        /// </summary>
 4        /// <param name="window">The window.</param>
 5        /// <returns>
 6        ///     <c>true</c>:安装成功<br/>
 7        ///     <c>false</c>:安装失败
 8        /// </returns>
 9        /// <value>消息源</value>
10        /// <remarks></remarks>
11        /// <history>
12        /// [ZengE]               2009-7-8 23:57    创建
13        /// </history> 

14        public static bool InstallHotKeyHook( Window window )
15        {
16            //判断组件是否有效
17            if ( null == window )
18            {
19                //如果无效,则直接返回
20                return false;
21            }

22
23            //获得窗体的句柄
24            System.Windows.Interop.WindowInteropHelper helper = new System.Windows.Interop.WindowInteropHelper( window );
25
26            //判断窗体句柄是否有效
27            if ( IntPtr.Zero == helper.Handle )
28            {
29                //如果句柄无效,则直接返回
30                return false;
31            }

32
33            //获得消息源
34            System.Windows.Interop.HwndSource source = System.Windows.Interop.HwndSource.FromHwnd( helper.Handle );
35
36            //判断消息源是否有效
37            if ( null == source )
38            {
39                //如果消息源无效,则直接返回
40                return false;
41            }

42
43            //挂接事件
44            source.AddHook( HotKeyHook );
45
46            //返回安装成功
47            return true;
48        }

49
50        /// <summary>
51        /// 热键处理过程
52        /// </summary>
53        /// <param name="hwnd">触发消息的窗口句柄</param>
54        /// <param name="msg">要被处理的消息编号</param>
55        /// <param name="wParam">消息参数</param>
56        /// <param name="lParam">消息参数</param>
57        /// <param name="handled">消息是否被处理</param>
58        /// <returns></returns>
59        /// <remarks></remarks>
60        /// <history>
61        /// [ZengE]               2009-7-8 23:54    创建
62        /// </history> 

63        private static IntPtr HotKeyHook( IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled )
64        {
65            //判断是否为热键消息
66            if ( msg == WM_HOTKEY )
67            {
68
69            }

70
71            //返回
72            return IntPtr.Zero;
73        }

74
75        /// <summary>
76        /// 热键消息编号
77        /// </summary> 

78        private const int WM_HOTKEY = 0x0312;

 

 以上代码在Windows2008下测试通过。

 

 

 

 

 

 在c#中使用全局快捷键

 

 

来源:http://hi.baidu.com/55csharp/blog/item/de6fef88efcebdbb0e24442f.html

由于.net并没有提供快捷键的库,所以要使用该功能得通过api实现。

在winapi中,注册和注销全局快捷键分别是通过RegisterHotKey和UnregisterHotKey函数实现。在c#中直接使用该api显得不够简洁,这里我提供了一个友好点的封装。

代码如下:

    static class Hotkey
    {
        系统api#region 系统api
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool RegisterHotKey(IntPtr hWnd, int id, HotkeyModifiers fsModifiers, Keys vk);

        [DllImport("user32.dll")]
        static extern bool UnregisterHotKey(IntPtr hWnd, int id);
        #endregion

        /**//// <summary> 
        /// 注册快捷键 
        /// </summary> 
        /// <param name="hWnd">持有快捷键窗口的句柄</param> 
        /// <param name="fsModifiers">组合键</param> 
        /// <param name="vk">快捷键的虚拟键码</param> 
        /// <param name="callBack">回调函数</param> 
        public static void Regist(IntPtr hWnd, HotkeyModifiers fsModifiers, Keys vk, HotKeyCallBackHanlder callBack)
        {
            int id = keyid++;
            if (!RegisterHotKey(hWnd, id, fsModifiers, vk))
                throw new Exception("regist hotkey fail.");
            keymap[id] = callBack;
        }

        /**//// <summary> 
        /// 注销快捷键 
        /// </summary> 
        /// <param name="hWnd">持有快捷键窗口的句柄</param> 
        /// <param name="callBack">回调函数</param> 
        public static void UnRegist(IntPtr hWnd, HotKeyCallBackHanlder callBack)
        {
            foreach (KeyValuePair<int, HotKeyCallBackHanlder> var in keymap)
            {
                if (var.Value == callBack)
                    UnregisterHotKey(hWnd, var.Key);
            }
        }

        /**//// <summary> 
        /// 快捷键消息处理 
        /// </summary> 
        public static void ProcessHotKey(System.Windows.Forms.Message m)
        {
            if (m.Msg == WM_HOTKEY)
            {
                int id = m.WParam.ToInt32();
                HotKeyCallBackHanlder callback;
                if (keymap.TryGetValue(id, out callback))
                {
                    callback();
                }
            }
        }

        const int WM_HOTKEY = 0x312;
        static int keyid = 10;
        static Dictionary<int, HotKeyCallBackHanlder> keymap = new Dictionary<int, HotKeyCallBackHanlder>();

        public delegate void HotKeyCallBackHanlder();
    }

    enum HotkeyModifiers
    {
        MOD_ALT = 0x1,
        MOD_CONTROL = 0x2,
        MOD_SHIFT = 0x4,
        MOD_WIN = 0x8
    }

 

这里通过Hotkey类实现功能的封装,使用非常简单。下面为参考测试代码。

 

        void Test()
        {
            MessageBox.Show("Test");
        }

        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            Hotkey.ProcessHotKey(m);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Hotkey.UnRegist(this.Handle, Test);
        }

当程序form1启动时,注册了两个快捷键Alt+T和Ctrl+Shift+K,单击button1的时候会注销快捷键Alt+T。代码比较简单,这里就不多介绍了。

注:快捷键是通过消息触发的,因此要重载WndProc函数,在里面添加对快捷键回调消息的处理方法Hotkey.ProcessHotKey(m)。

 

 

 

C# 设置全局热键

来源:http://www.cnblogs.com/lhking/archive/2009/03/16/1413245.html


using System;
using
 System.Collections.Generic;
using
 System.ComponentModel;
using
 System.Data;
using
 System.Drawing;
using
 System.Text;
using
 System.Windows.Forms;
using
 System.Runtime.InteropServices;
using
 System.Collections;

namespace
 HotKey1
{
    
public partial class
 Form1 : Form
    {
        
public
 Form1()
        {
            InitializeComponent();
        }
        
public delegate void HotkeyEventHandler(int
 HotKeyID);
        
private int
 Hotkey1;
        
public class
 Hotkey : System.Windows.Forms.IMessageFilter
        {
            Hashtable keyIDs 
= new
 Hashtable();
            IntPtr hWnd;

            
public event
 HotkeyEventHandler OnHotkey;

            
public enum
 KeyFlags
            {
                MOD_ALT 
= 0x1
,
                MOD_CONTROL 
= 0x2
,
                MOD_SHIFT 
= 0x4
,
                MOD_WIN 
= 0x8

            }
            [DllImport(
"user32.dll")]
            
public static extern
 UInt32 RegisterHotKey(IntPtr hWnd, UInt32 id, UInt32 fsModifiers, UInt32 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
);
            }

            
public int
 RegisterHotkey(Keys Key, KeyFlags keyflags)
            {
                UInt32 hotkeyid 
=
 GlobalAddAtom(System.Guid.NewGuid().ToString());
                RegisterHotKey((IntPtr)hWnd, hotkeyid, (UInt32)keyflags, (UInt32)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);
                }
            }

            
public bool PreFilterMessage(ref
 System.Windows.Forms.Message m)
            {
                
if (m.Msg == 0x312
)
                {
                    
if (OnHotkey != null
)
                    {
                        
foreach (UInt32 key in
 keyIDs.Values)
                        {
                            
if ((UInt32)m.WParam ==
 key)
                            {
                                OnHotkey((
int
)m.WParam);
                                
return true
;
                            }
                        }
                    }
                }
                
return false
;
            }
        }

        
public void OnHotkey(int HotkeyID) //Ctrl+F2隐藏窗体,再按显示窗体。

        {
            
if (HotkeyID ==
 Hotkey1)
            {
                
if (this.Visible == true
)
                    
this.Visible = false
;
                
else

                    
this.Visible = true;
            }
            
else

            {
                
this.Visible = false;
            }
        }

        
private void Form1_Load(object
 sender, EventArgs e)
        {
            Hotkey hotkey;
            hotkey 
= new Hotkey(this
.Handle);
            Hotkey1 
= hotkey.RegisterHotkey(System.Windows.Forms.Keys.F2, Hotkey.KeyFlags.MOD_CONTROL);   //定义快键(Ctrl + F2)

            hotkey.OnHotkey += new HotkeyEventHandler(OnHotkey);
        }
    }
}

 

 

 

 

 


posted on 2010-02-21 23:40  大宝pku  阅读(5450)  评论(0编辑  收藏  举报

导航