2012-04-03 11 views
6

Mam combobox, który jest wypełniany przez wyliczenie Keys (WinForm).Dość kluczowe nazwy w C# (Formularze)

Problem polega na tym, że nazwy kluczy nie są zbyt jasne dla niedoświadczonych użytkowników. Na przykład przeciętny użytkownik może nie wiedzieć, co oznacza "OemPipe" lub "HanjaMode". Jak mogę rozwiązać ten problem i uzyskać lepsze nazwy kluczy?

Zastanawiam się nad stworzeniem słownika z kluczami i ich nazwami, ale samo zapełnianie słownika jest bardzo czasochłonne.

+0

To właśnie doucmentaion jest dla – Sandeep

+0

@JustinNiessner Keys jest wyliczeniem z formularzy Windows (System.Windows.Forms.Keys). – Tibi

+0

Będziesz musiał wymyślić opis dla każdej wartości, która jest czasochłonna. Nie ma znaczenia, jak je przechowujesz. –

Odpowiedz

7

Utwórz plik zasobów, który odwzorowuje nazwy klawiszy na łańcuch zrozumiały dla użytkownika. Jeśli plik zasobów nie ma wartości dla określonego klucza, po prostu idź z nazwą klucza (tak jak teraz), tak że musisz tylko zdefiniować te, które są trudne do zrozumienia, a ty nie Zrobić je wszystkie z góry.

Pozwala to również na lokalizację w różnych językach, jeśli chcesz.

EDYCJA: Dodano przykład kodu. Zakłada się, że masz plik zasobu o nazwie „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

Ogólnie jest to prawdopodobnie lepsze rozwiązanie niż trudne kodowanie wartości przyjaznych dla użytkownika, nawet jeśli nie trzeba go lokalizować. – jnylen

+0

To wydaje się najlepszym rozwiązaniem. – Tibi

0

Nie ma sposobu na samodzielne napisanie kodu. Oto podejście można użyć, który jest prawdopodobnie blisko minimalnym wysiłku potrzebnego, choć:

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(); 
    } 
} 

Nie jestem pewien, czy trzeba bitu & ~Keys.Modifiers czy nie - jeśli nie, prawdopodobnie będziesz chciał napisać więcej kodu do obsługi modyfikatorów - ale wcześniej robiłem podobne rzeczy.

1

Jeśli chcesz tylko dostarczyć opis niektórych klawiszy, można zapętlić System.Windows.Forms.Keys i dostarczamy metodę, która domyślnie nazwę klucza ENUM:

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 
    } 
} 
0

Można przypisać atrybuty do wyliczeń. To jest najlepszy sposób. W przeciwnym razie będziesz musiał utrzymywać równoległe słowniki lub rosnącą listę oświadczeń switch-case.

Oto jak można oznaczyć z ENUM:

public enum MyEnums 
{ 
    [Description("OEM Pipe")] 
    OemPipe, 

    [Description("Hanja Mode")] 
    HanjaMode 
} 

można pobrać atrybut Description poprzez metodę rozszerzenia:

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(); 
} 

Aby rzeczywiście odzyskać opis wyliczenia, byś go to nazwać droga;

var enumAsText = theEnum.ToEnumDescription(); 

Można też to zrobić:

MyEnums.OemPipe.ToEnumDescription(); 
+0

Używa istniejącego wyliczenia ('System.Windows.Forms.Keys') i dlatego nie może dodać atrybutów" Opis ". – jnylen

+0

LOL, którego początkowo nie podano ... – code4life

1

"OEM" oznacza Original Equipment Manufacturer. Innymi słowy, firma produkująca klawiatury. Te nazwy są specjalne, ponieważ na "zwykłej" klawiaturze nie ma dedykowanego klucza do generowania | lub włączania rodników Hanja po koreańsku (zgadnij). Uzyskanie | wymaga przytrzymania klawisza Shift w większości układów. Niektórzy producenci klawiatur mogą dodawać klucze do standardowego układu, który to robi.

Co powinno dać ci chwilę przerwy, klawisze te są mało prawdopodobne, aby były dostępne na klawiaturze użytkownika, więc przedstawienie ich jako możliwych skrótów klawiszowych jest nieprzydatne. Co ważniejsze, używanie ciągu, który wydobywasz z klawiszy, jest złym pomysłem. Daje ci to ból głowy, kiedy musisz zlokalizować swoją aplikację pewnego dnia, aby pozostałe 5-miliardy ludzi na tym świecie zaczęło płacić klientom.

+0

Prawda. Zawsze nienawidziłem lokalizacji, jest to jedna z najbardziej irytujących rzeczy w programowaniu ... – Tibi

3

Zakładam, że pozwalasz użytkownikowi przypisać klucze z poziomu aplikacji (takie jak klawisze skrótów lub kontrolki do gier). Niestety, nie ma łatwego sposobu na uzyskanie przyjaznych opisów kluczy (Microsoft nie udostępnia jednego lub podobnego API), więc będziesz musiał stworzyć własne mapowanie.

Jak pokazuje obecnie zaakceptowana odpowiedź, użycie pliku zasobów jest świetnym sposobem na zrobienie tego, aby umożliwić internacjonalizację aplikacji.

Dla porównania, tutaj jest pełna realizacja brute-force z wyliczeniem Keys pisałem jakiś czas temu: (przy wykorzystaniu pliku zasobów jest nadal zalecane, jednak)

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)); 
    } 
} 

można przekonwertować to do pliku zasobów uruchamiając następujący program, a następnie dodając output.resx do aplikacji jako zasób.

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)); 
     } 
    } 
} 

To da ci plik zasobów, który może być użyty w sposób wyjaśniony w zaakceptowanej odpowiedzi.