本来听说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~