不确定我对标题的解释是否足够好,但我想让一个人按下任何键,然后我可以存储该键码以供以后使用,但更重要的是我希望直观地显示他们选择的键。有点像你在游戏中得到的键盘设置类型的东西。
我想知道是否有任何公共课程或可以减轻为每个键编码的麻烦的东西。
有一个专门为此目的设计的本机 Win32 控件,称为热键控件。您可能已经看到它在 Windows shell 和其他应用程序中的使用。那将是我建议您使用的那个,而不是尝试自己重新发明轮子。
不幸的是,WinForms 没有为这个控件提供包装。这意味着您要么必须自己编写它,要么满足于其他人实现类似类型的控件。
编辑:或者使用这个快速组合的 .NET 包装器用于热键控件。整个公共接口是KeyData
属性,它的工作方式与类的类似名称的属性一样KeyEventArgs
。该Text
属性(通过继承 from 提供Control
)不做任何事情,但可以重载以返回所选热键的漂亮打印版本。此外,本机控件的HKM_SETRULES消息的功能未实现;如果您需要该功能,您需要自己添加代码。
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
internal static class NativeMethods
{
internal const string HOTKEY_CLASS = "msctls_hotkey32";
internal const int CS_GLOBALCLASS = 0x4000;
internal const int WS_CHILD = 0x40000000;
internal const int WS_VISIBLE = 0x10000000;
internal const int WS_TABSTOP = 0x00010000;
internal const int WS_EX_NOPARENTNOTIFY = 0x00000004;
internal const int WS_EX_CLIENTEDGE = 0x00000200;
internal const int WS_EX_LEFT = 0x00000000;
internal const int WS_EX_LTRREADING = 0x00000000;
internal const int WS_EX_RIGHTSCROLLBAR = 0x00000000;
internal const int WS_EX_RIGHT = 0x00001000;
internal const int WS_EX_RTLREADING = 0x00002000;
internal const int WS_EX_LEFTSCROLLBAR = 0x00004000;
internal const int HOTKEYF_SHIFT = 0x01;
internal const int HOTKEYF_CONTROL = 0x02;
internal const int HOTKEYF_ALT = 0x04;
internal const int HOTKEYF_EXT = 0x08;
internal const int WM_USER = 0x0400;
internal const int HKM_SETHOTKEY = (WM_USER + 1);
internal const int HKM_GETHOTKEY = (WM_USER + 2);
internal const int HKM_SETRULES = (WM_USER + 3);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern IntPtr SendMessage(IntPtr hWnd,
int msg,
IntPtr wParam,
IntPtr lParam);
}
class HotKey : Control
{
public HotKey()
{
base.SetStyle(ControlStyles.UserPaint
| ControlStyles.StandardClick
| ControlStyles.StandardDoubleClick
| ControlStyles.UseTextForAccessibility, false);
base.SetStyle(ControlStyles.FixedHeight, true);
}
public Keys KeyData
{
get
{
IntPtr retVal = NativeMethods.SendMessage(Handle,
NativeMethods.HKM_GETHOTKEY,
IntPtr.Zero,
IntPtr.Zero);
Keys keyCode = (Keys)(retVal.ToInt32() & 0xFF);
int modifierFlags = (retVal.ToInt32() >> 8);
Keys modifiers = Keys.None;
if ((modifierFlags & NativeMethods.HOTKEYF_ALT) == NativeMethods.HOTKEYF_ALT)
modifiers |= Keys.Alt;
if ((modifierFlags & NativeMethods.HOTKEYF_CONTROL) == NativeMethods.HOTKEYF_CONTROL)
modifiers |= Keys.Control;
if ((modifierFlags & NativeMethods.HOTKEYF_SHIFT) == NativeMethods.HOTKEYF_SHIFT)
modifiers |= Keys.Shift;
return (keyCode | modifiers);
}
set
{
Keys keyCode = (value & (~Keys.Alt & ~Keys.Control & ~Keys.Shift));
int modifierFlags = 0;
if ((value & Keys.Alt) == Keys.Alt)
modifierFlags |= NativeMethods.HOTKEYF_ALT;
if ((value & Keys.Control) == Keys.Control)
modifierFlags |= NativeMethods.HOTKEYF_CONTROL;
if ((value & Keys.Shift) == Keys.Shift)
modifierFlags |= NativeMethods.HOTKEYF_SHIFT;
NativeMethods.SendMessage(Handle,
NativeMethods.HKM_SETHOTKEY,
(IntPtr)((modifierFlags << 8) | ((int)keyCode & 0xffff)),
IntPtr.Zero);
}
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ClassName = NativeMethods.HOTKEY_CLASS;
cp.ClassStyle = NativeMethods.CS_GLOBALCLASS;
cp.Style = NativeMethods.WS_CHILD | NativeMethods.WS_VISIBLE | NativeMethods.WS_TABSTOP;
cp.ExStyle = NativeMethods.WS_EX_NOPARENTNOTIFY | NativeMethods.WS_EX_CLIENTEDGE;
if (RightToLeft == RightToLeft.No ||
(RightToLeft == RightToLeft.Inherit && Parent.RightToLeft == RightToLeft.No))
{
cp.ExStyle |= NativeMethods.WS_EX_LEFT
| NativeMethods.WS_EX_LTRREADING
| NativeMethods.WS_EX_RIGHTSCROLLBAR;
}
else
{
cp.ExStyle |= NativeMethods.WS_EX_RIGHT
| NativeMethods.WS_EX_RTLREADING
| NativeMethods.WS_EX_LEFTSCROLLBAR;
}
return cp;
}
}
}
它提到了这个Control.KeyDown
事件。
private Keys _lastKeyPressed;
public Form1()
{
InitializeComponent();
this.KeyDown += Form1_KeyDown;
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
// Do something with event keycode
_lastKeyPressed = e.KeyCode;
}
您还可以在他们释放密钥时收听Control.KeyUp
事件。