• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
格局
技术\业务\管理
博客园    首页    新随笔    联系   管理    订阅  订阅

C#的Hotkey简单封装

本来听说winapi里面的RegisterHotKey有时候不好使,于是打算用hook键盘消息来做hook key,结果发现hook那里处理消息那里还挺麻烦,也想会不会造成系统的额外开销比较大,所以最后用RegisterHotKey来封装了一下,测试没有问题,还是可以的。(winform)
下面的代码包括一个Textbox的处理,和一个封装了api的类。Textbox那里就是处理用户定义的热键的界面表示,比如用户按键的时候会出现"Ctrl+Alt+A"之类的,Api封装那里做了处理,只管Register好了,不用管UnRegister,当注册一个一样的Id的hotkey,会自动先UnRegister原来的,然后最后关闭窗口的时候,调用一下HotkeyHelper.Dispose()就可以了。还希望多加建议。here we go..

Textbox部分:(Key hotkeyVk = null;)
        private void txbHotKey_KeyDown(object sender, KeyEventArgs e)
        {
            txbHotKey.Text 
= string.Empty;

            
if (e.Control)
            {
                txbHotKey.Text 
+= "Ctrl+";
            }
            
if (e.Alt)
            {
                txbHotKey.Text 
+= "Alt+";
            }
            
if (e.Shift)
            {
                txbHotKey.Text 
+= "Shift+";
            }

            
if (e.KeyCode >= Keys.A && e.KeyCode <= Keys.Z)
            {
                
if (e.Modifiers != Keys.None)
                {
                    txbHotKey.Text 
+= e.KeyCode.ToString();
                    hotkeyVk 
= e.KeyCode;
                }
            }
            
else if (e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9)
            {
                
if (e.Modifiers != Keys.None)
                {
                    txbHotKey.Text 
+= e.KeyCode.ToString().Remove(0, 1);
                    hotkeyVk 
= e.KeyCode;
                }
            }
            
else if (e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9)
            {
                
if (e.Modifiers != Keys.None)
                {
                    txbHotKey.Text 
+= e.KeyCode.ToString().Replace("Pad", "");
                    hotkeyVk 
= e.KeyCode;
                }
            }
            
else if (e.KeyCode >= Keys.F1 && e.KeyCode <= Keys.F12)
            {
                txbHotKey.Text 
+= e.KeyCode.ToString();
                hotkeyVk 
= e.KeyCode;
            }

            e.SuppressKeyPress 
= false;
            e.Handled 
= true;
        }

        
private void txbHotKey_KeyPress(object sender, KeyPressEventArgs e)
        {
            e.Handled 
= true;
        }

        
private void txbHotKey_KeyUp(object sender, KeyEventArgs e)
        {
            CheckHotkey();
        }

        
void txbHotKey_LostFocus(object sender, EventArgs e)
        {
            CheckHotkey();
        }

        
private void CheckHotkey()
        {
            
if (txbHotKey.Text.EndsWith("+") || txbHotKey.Text == string.Empty)
            {
                txbHotKey.Text 
= "无";
            }
        }

        
private void btnHotKey_Click(object sender, EventArgs e)
        {
            
string hotkey = txbHotKey.Text.Replace("+", "");
            
if (hotkey != "无" && hotkey != string.Empty)
            {
                
uint modifies = 0;
                
if (hotkey.Contains("Ctrl"))
                {
                    modifies 
|= HotkeyHelper.MOD_CONTROL;
                    hotkey 
= hotkey.Replace("Ctrl", "");
                }
                
if (hotkey.Contains("Alt"))
                {
                    modifies 
|= HotkeyHelper.MOD_ALT;
                    hotkey 
= hotkey.Replace("Alt", "");
                }
                
if (hotkey.Contains("Shift"))
                {
                    modifies 
|= HotkeyHelper.MOD_SHIFT;
                    hotkey 
= hotkey.Replace("Shift", "");
                }
                GameProvider.HotkeyHelper.RegisterHotKey(
this.Handle, hotkeyId, modifies, (uint)hotkeyVk);
            }
        }

HotkeyHelper部分:
using System;
using System.Collections.Generic;
using System.Text;

using GFSucker.Game.Utility;

namespace GFSucker.Game.Provider
{
    
public class HotkeyHelper : IDisposable
    {
        
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;

        
private Dictionary<int, Hotkey> dicHotkeys;

        
public HotkeyHelper()
        {
            dicHotkeys 
= new Dictionary<int, Hotkey>();
        }

        
public bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk)
        {
            
if (dicHotkeys.ContainsKey(id))
            {
                
if (dicHotkeys[id].IsRegistered)
                {
                    UnregisterHotKey(dicHotkeys[id].HWnd, id);      
// unregister firstly
                    dicHotkeys[id].IsRegistered = false;
                }
                dicHotkeys[id].HWnd 
= hWnd;                         // set the new hwnd (normally should be the same)
            }
            
else
            {
                dicHotkeys.Add(id, 
new Hotkey(hWnd, false));
            }

            dicHotkeys[id].IsRegistered 
= WinApi.RegisterHotKey(hWnd, id, fsModifiers, vk);

            
return dicHotkeys[id].IsRegistered;
        }

        
private bool UnregisterHotKey(IntPtr hWnd, int id)
        {
            
return WinApi.UnregisterHotKey(hWnd, id);
        }

        
#region Hotkey Information
        
class Hotkey
        {
            
public Hotkey(IntPtr hWnd, bool isRegistered)
            {
                _HWnd 
= hWnd;
                _IsRegistered 
= isRegistered;
            }

            
private IntPtr _HWnd;

            
public IntPtr HWnd
            {
                
get { return _HWnd; }
                
set { _HWnd = value; }
            }

            
private bool _IsRegistered;

            
public bool IsRegistered
            {
                
get { return _IsRegistered; }
                
set { _IsRegistered = value; }
            }
        }
        
#endregion

        
#region IDisposable 成员

        
public void Dispose()
        {
            
foreach (int id in dicHotkeys.Keys)
            {
                
if (dicHotkeys[id].IsRegistered)
                {
                    UnregisterHotKey(dicHotkeys[id].HWnd, id);
                }
            }
        }

        
#endregion
    }
}

Winapi声明:
        [DllImport("user32.dll")]
        [
return: MarshalAs(UnmanagedType.Bool)]
        
public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);

        [DllImport(
"user32.dll")]
        [
return: MarshalAs(UnmanagedType.Bool)]
        
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);

Override winform窗体的WndProc:(就是接受到hotkey信息的时候,做你想做的东西)
        protected override void WndProc(ref Message m)
        {
            
base.WndProc(ref m);

            
if (m.Msg == HotkeyHelper.WM_HOTKEY)
            {
                MainForm mainform 
= this.Parent.Parent.Parent.Parent.Parent.Parent.Parent.Parent.Parent as MainForm;
                
if (mainform != null)
                {
                    
if (mainform.WindowState == FormWindowState.Minimized)
                    {
                        mainform.WindowState 
= FormWindowState.Normal;
                    }
                    mainform.Activate();
                }
            }
        }



因为直接从程序中copy出来的,代码没有很多注释,不过都是非常浅显易懂的东西,名字看上去还是一目了然的,另外说一句,我觉得如果重构得比较好的代码是不需要做过多的注释的,代码本身就是注释,注释用在解释一些比较混乱的行为意图。希望对大家有帮助咯。bye~
posted @ 2008-07-09 18:05  惠众益自  阅读(285)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3