一、增加快捷键
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);
}
注意:快捷键能够被正常激活的条件是:这个窗体或者控件是焦点窗体或者控件
这里有个参考网址:/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