我有一个由Keys
枚举(winforms)填充的组合框。
问题是对于没有经验的用户来说,关键名称不是很清楚。例如,普通用户可能不知道“OemPipe”或“HanjaMode”的含义。那么,我该如何解决这个问题,并有一些更好的密钥名称?
我正在考虑用密钥及其名称制作字典,但是自己填写字典非常耗时。
答案 0 :(得分:7)
创建一个资源文件,将密钥名称映射到用户可理解的字符串。如果资源文件没有特定键的值,那么只需使用键名(正如您现在所做的那样),这样您只需要定义难以理解的键,而不是必须事先做好。
如果您愿意,这也允许您本地化为不同的语言。
编辑:添加了代码示例。假设您有一个名为“KeyNames.resx”的资源文件
foreach (var key in Enum.GetValues(typeof(Keys)))
{
var keyName = KeyNames.ResourceManager.GetString(key.ToString());
if (keyName == null)
keyName = key.ToString();
comboBox1.Items.Add(keyName);
}
答案 1 :(得分:3)
我假设您允许用户从您的应用程序中分配键(例如快捷键或游戏控件)。不幸的是,没有简单的方法来获得密钥的友好描述(Microsoft不提供一个或等效的API),因此您需要自己创建映射。
正如当前接受的答案所示,使用资源文件是一种很好的方法,可以实现应用程序的国际化。
作为参考,这里是我前一段时间写的关键枚举的完整暴力实现:(但仍建议使用资源文件)
public static string GetDescription(Keys key)
{
switch (key)
{
//letters
case Keys.A: case Keys.B: case Keys.C: case Keys.D: case Keys.E: case Keys.F:
case Keys.G: case Keys.H: case Keys.I: case Keys.J: case Keys.K: case Keys.L:
case Keys.M: case Keys.N: case Keys.O: case Keys.P: case Keys.Q: case Keys.R:
case Keys.S: case Keys.T: case Keys.U: case Keys.V: case Keys.W: case Keys.X:
case Keys.Y: case Keys.Z:
return Enum.GetName(typeof(Keys), key);
//digits
case Keys.D0:
return "0";
case Keys.NumPad0:
return "Number Pad 0";
case Keys.D1:
return "1";
case Keys.NumPad1:
return "Number Pad 1";
case Keys.D2:
return "2";
case Keys.NumPad2:
return "Number Pad 2";
case Keys.D3:
return "3";
case Keys.NumPad3:
return "Number Pad 3";
case Keys.D4:
return "4";
case Keys.NumPad4:
return "Number Pad 4";
case Keys.D5:
return "5";
case Keys.NumPad5:
return "Number Pad 5";
case Keys.D6:
return "6";
case Keys.NumPad6:
return "Number Pad 6";
case Keys.D7:
return "7";
case Keys.NumPad7:
return "Number Pad 7";
case Keys.D8:
return "8";
case Keys.NumPad8:
return "Number Pad 8";
case Keys.D9:
return "9";
case Keys.NumPad9:
return "Number Pad 9";
//punctuation
case Keys.Add:
return "Number Pad +";
case Keys.Subtract:
return "Number Pad -";
case Keys.Divide:
return "Number Pad /";
case Keys.Multiply:
return "Number Pad *";
case Keys.Space:
return "Spacebar";
case Keys.Decimal:
return "Number Pad .";
//function
case Keys.F1: case Keys.F2: case Keys.F3: case Keys.F4: case Keys.F5:
case Keys.F6: case Keys.F7: case Keys.F8: case Keys.F9: case Keys.F10:
case Keys.F11: case Keys.F12: case Keys.F13: case Keys.F14: case Keys.F15:
case Keys.F16: case Keys.F17: case Keys.F18: case Keys.F19: case Keys.F20:
case Keys.F21: case Keys.F22: case Keys.F23: case Keys.F24:
return Enum.GetName(typeof(Keys), key);
//navigation
case Keys.Up:
return "Up Arrow";
case Keys.Down:
return "Down Arrow";
case Keys.Left:
return "Left Arrow";
case Keys.Right:
return "Right Arrow";
case Keys.Prior:
return "Page Up";
case Keys.Next:
return "Page Down";
case Keys.Home:
return "Home";
case Keys.End:
return "End";
//control keys
case Keys.Back:
return "Backspace";
case Keys.Tab:
return "Tab";
case Keys.Escape:
return "Escape";
case Keys.Enter:
return "Enter";
case Keys.Shift: case Keys.ShiftKey:
return "Shift";
case Keys.LShiftKey:
return "Shift (Left)";
case Keys.RShiftKey:
return "Shift (Right)";
case Keys.Control: case Keys.ControlKey:
return "Control";
case Keys.LControlKey:
return "Control (Left)";
case Keys.RControlKey:
return "Control (Right)";
case Keys.Menu: case Keys.Alt:
return "Alt";
case Keys.LMenu:
return "Alt (Left)";
case Keys.RMenu:
return "Alt (Right)";
case Keys.Pause:
return "Pause";
case Keys.CapsLock:
return "Caps Lock";
case Keys.NumLock:
return "Num Lock";
case Keys.Scroll:
return "Scroll Lock";
case Keys.PrintScreen:
return "Print Screen";
case Keys.Insert:
return "Insert";
case Keys.Delete:
return "Delete";
case Keys.Help:
return "Help";
case Keys.LWin:
return "Windows (Left)";
case Keys.RWin:
return "Windows (Right)";
case Keys.Apps:
return "Context Menu";
//browser keys
case Keys.BrowserBack:
return "Browser Back";
case Keys.BrowserFavorites:
return "Browser Favorites";
case Keys.BrowserForward:
return "Browser Forward";
case Keys.BrowserHome:
return "Browser Home";
case Keys.BrowserRefresh:
return "Browser Refresh";
case Keys.BrowserSearch:
return "Browser Search";
case Keys.BrowserStop:
return "Browser Stop";
//media keys
case Keys.VolumeDown:
return "Volume Down";
case Keys.VolumeMute:
return "Volume Mute";
case Keys.VolumeUp:
return "Volume Up";
case Keys.MediaNextTrack:
return "Next Track";
case Keys.Play:
case Keys.MediaPlayPause:
return "Play";
case Keys.MediaPreviousTrack:
return "Previous Track";
case Keys.MediaStop:
return "Stop";
case Keys.SelectMedia:
return "Select Media";
//IME keys
case Keys.HanjaMode: case Keys.JunjaMode: case Keys.HangulMode:
case Keys.FinalMode: //duplicate values: Hanguel, Kana, Kanji
case Keys.IMEAccept: case Keys.IMEConvert: //duplicate: IMEAceept
case Keys.IMEModeChange: case Keys.IMENonconvert:
return null;
//special keys
case Keys.LaunchMail:
return "Launch Mail";
case Keys.LaunchApplication1:
return "Launch Favorite Application 1";
case Keys.LaunchApplication2:
return "Launch Favorite Application 2";
case Keys.Zoom:
return "Zoom";
//oem keys
case Keys.OemSemicolon: //oem1
return ";";
case Keys.OemQuestion: //oem2
return "?";
case Keys.Oemtilde: //oem3
return "~";
case Keys.OemOpenBrackets: //oem4
return "[";
case Keys.OemPipe: //oem5
return "|";
case Keys.OemCloseBrackets: //oem6
return "]";
case Keys.OemQuotes: //oem7
return "'";
case Keys.OemBackslash: //oem102
return "/";
case Keys.Oemplus:
return "+";
case Keys.OemMinus:
return "-";
case Keys.Oemcomma:
return ",";
case Keys.OemPeriod:
return ".";
//unsupported oem keys
case Keys.Oem8:
case Keys.OemClear:
return null;
//unsupported other keys
case Keys.None: case Keys.LButton: case Keys.RButton: case Keys.MButton:
case Keys.XButton1: case Keys.XButton2: case Keys.Clear: case Keys.Sleep:
case Keys.Cancel: case Keys.LineFeed: case Keys.Select: case Keys.Print:
case Keys.Execute: case Keys.Separator: case Keys.ProcessKey: case Keys.Packet:
case Keys.Attn: case Keys.Crsel: case Keys.Exsel: case Keys.EraseEof:
case Keys.NoName: case Keys.Pa1: case Keys.KeyCode: case Keys.Modifiers:
return null;
default:
throw new NotSupportedException(Enum.GetName(typeof(Keys), key));
}
}
您可以通过运行以下程序将此转换为资源文件,然后将output.resx作为资源添加到您的应用程序中。
static void Main(string[] args)
{
using(ResXResourceWriter writer = new ResXResourceWriter("output.resx"))
{
//since there are duplicate values, we need to clumsily look at each name, then parse
foreach (string name in Enum.GetNames(typeof(Keys)))
{
object value = Enum.Parse(typeof(Keys), name);
string description = GetDescription((Keys)value);
if (description != null)
writer.AddResource(new ResXDataNode(name, description));
}
}
}
这将为您提供一个资源文件,可以在接受的答案中以解释的方式使用。
答案 2 :(得分:1)
如果您只想提供某些键的描述,可以循环System.Windows.Forms.Keys
并提供一个默认为Key枚举名称的方法:
private void Form1_Load(object sender, EventArgs e)
{
foreach (System.Windows.Forms.Keys key in Enum.GetValues(typeof(System.Windows.Forms.Keys)))
{
comboBoxKeys.Items.Add(new { Value = key, Description = GetDescription(key) });
}
comboBoxKeys.DisplayMember = "Description";
}
private string GetDescription(System.Windows.Forms.Keys key)
{
switch(key)
{
case Keys.OemPipe:
return "Better oem pipe description";
case Keys.HanjaMode:
return "Ninja mode";
default:
return key.ToString(); // default name
}
}
答案 3 :(得分:1)
“Oem”指原始设备制造商。换句话说,那种制造键盘的公司。这些名称很特别,因为在“常规”键盘上,没有专用键可以生成|
或打开韩语中的汉字激进(猜测)。获得|
需要在大多数布局上按住Shift键。某些键盘制造商可能会为执行此操作的标准布局添加键。
哪个应该给你一些暂停,这些键不太可能在用户的键盘上可用,因此将它们作为可能的快捷键击提供是没有用的。更重要的是,使用你从Keys中获得的字符串本身就是一个坏主意。当你需要在某一天本地化你的应用程序时,它会让你头疼,所以这个世界上其他五十亿人成为付费用户。
答案 4 :(得分:0)
没有办法自己编写代码。这是一种你可以使用的方法,可能接近于所需的最小努力,但是:
string GetBaseKeyDescription(Keys k) {
switch (k & ~Keys.Modifiers) {
case Keys.OemPipe:
return "Pipe |";
case Keys.OemPeriod:
return "Dot .";
case Keys.HanjaMode:
return "(Description of HanjaMode key)";
default:
return k.ToString();
}
}
我不确定你是否需要& ~Keys.Modifiers
位 - 如果你这样做,你可能想要编写更多代码来处理修饰符 - 但我之前做过类似的事情。
答案 5 :(得分:0)
您可以为枚举指定属性。这是最好的方法。否则,您最终将不得不维护并行字典或不断增加的switch-case
语句列表。
以下是标记枚举的方法:
public enum MyEnums
{
[Description("OEM Pipe")]
OemPipe,
[Description("Hanja Mode")]
HanjaMode
}
您可以通过扩展方法检索Description
属性:
public static string ToEnumDescription(this Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute),
false);
if (attributes != null &&
attributes.Length > 0)
return attributes[0].Description;
else
return value.ToString();
}
要实际检索枚举描述,您可以这样调用它;
var enumAsText = theEnum.ToEnumDescription();
你也可以这样做:
MyEnums.OemPipe.ToEnumDescription();