diff --git a/src/Main/Base/Project/Src/Commands/MenuItemBuilders.cs b/src/Main/Base/Project/Src/Commands/MenuItemBuilders.cs index 84623a1227..cc88bc0693 100644 --- a/src/Main/Base/Project/Src/Commands/MenuItemBuilders.cs +++ b/src/Main/Base/Project/Src/Commands/MenuItemBuilders.cs @@ -442,7 +442,7 @@ namespace ICSharpCode.SharpDevelop.Commands SD.Workbench.MainWindow.InputBindings.Add( new System.Windows.Input.InputBinding(item.Command, kg) ); - item.InputGestureText = kg.GetDisplayStringForCulture(Thread.CurrentThread.CurrentUICulture); + item.InputGestureText = MenuService.GetDisplayStringForShortcut(kg); } list.Add(item); diff --git a/src/Main/ICSharpCode.Core.Presentation/Menu/MenuCheckBox.cs b/src/Main/ICSharpCode.Core.Presentation/Menu/MenuCheckBox.cs index 765f68cc94..dba8643bfd 100644 --- a/src/Main/ICSharpCode.Core.Presentation/Menu/MenuCheckBox.cs +++ b/src/Main/ICSharpCode.Core.Presentation/Menu/MenuCheckBox.cs @@ -34,7 +34,7 @@ namespace ICSharpCode.Core.Presentation if (!string.IsNullOrEmpty(codon.Properties["shortcut"])) { KeyGesture kg = MenuService.ParseShortcut(codon.Properties["shortcut"]); MenuCommand.AddGestureToInputBindingOwner(inputBindingOwner, kg, this.Command, null); - this.InputGestureText = kg.GetDisplayStringForCulture(Thread.CurrentThread.CurrentUICulture); + this.InputGestureText = MenuService.GetDisplayStringForShortcut(kg); } } diff --git a/src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs b/src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs index b46f010e2d..f9d25c446d 100644 --- a/src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs +++ b/src/Main/ICSharpCode.Core.Presentation/Menu/MenuCommand.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.Core.Presentation if (!string.IsNullOrEmpty(codon.Properties["shortcut"])) { KeyGesture kg = MenuService.ParseShortcut(codon.Properties["shortcut"]); AddGestureToInputBindingOwner(inputBindingOwner, kg, this.Command, GetFeatureName()); - this.InputGestureText = kg.GetDisplayStringForCulture(Thread.CurrentThread.CurrentUICulture); + this.InputGestureText = MenuService.GetDisplayStringForShortcut(kg); } } diff --git a/src/Main/ICSharpCode.Core.Presentation/Menu/MenuService.cs b/src/Main/ICSharpCode.Core.Presentation/Menu/MenuService.cs index 6c89195d45..5eab73752a 100644 --- a/src/Main/ICSharpCode.Core.Presentation/Menu/MenuService.cs +++ b/src/Main/ICSharpCode.Core.Presentation/Menu/MenuService.cs @@ -4,7 +4,11 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Globalization; using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; @@ -240,5 +244,79 @@ namespace ICSharpCode.Core.Presentation { return (KeyGesture)new KeyGestureConverter().ConvertFromInvariantString(text.Replace('|', '+')); } + + public static string GetDisplayStringForShortcut(KeyGesture kg) + { + string old = kg.GetDisplayStringForCulture(Thread.CurrentThread.CurrentUICulture); + string text = KeyCodeConversion.KeyToUnicode(kg.Key.ToKeys()); + if (text != null) { + if ((kg.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt) + text = "Alt+" + text; + if ((kg.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift) + text = "Shift+" + text; + if ((kg.Modifiers & ModifierKeys.Control) == ModifierKeys.Control) + text = "Ctrl+" + text; + if ((kg.Modifiers & ModifierKeys.Windows) == ModifierKeys.Windows) + text = "Win+" + text; + return text; + } + return old; + } + } + + static class KeyCodeConversion + { + [DllImport("user32.dll")] + static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte [] + lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff, + int cchBuff, uint wFlags, IntPtr dwhkl); + + [DllImport("user32.dll")] + static extern bool GetKeyboardState(byte[] pbKeyState); + + [DllImport("user32.dll")] + static extern uint MapVirtualKeyEx(uint uCode, uint uMapType, IntPtr dwhkl); + + [DllImport("user32.dll")] + static extern IntPtr GetKeyboardLayout(uint idThread); + + /// Only works with Windows.Forms.Keys. The WPF Key enum seems to be horribly distorted! + public static string KeyToUnicode(WinForms.Keys key) + { + StringBuilder sb = new StringBuilder(255); + byte[] keyState = new byte[255]; + IntPtr hkl = GetKeyboardLayout(0); + + if (!GetKeyboardState(keyState)) return null; + + uint scanCode = MapVirtualKeyEx((uint)key, 0, hkl); + if (scanCode < 1) return null; + + ClearKeyboardBuffer(hkl); + int len = ToUnicodeEx((uint)key, scanCode, keyState, sb, sb.Capacity, 0, hkl); + if (len > 0) + return sb.ToString(0, len).ToUpper(); + + ClearKeyboardBuffer(hkl); + return null; + } + + static void ClearKeyboardBuffer(IntPtr hkl) + { + StringBuilder sb = new StringBuilder(10); + uint key = (uint)WinForms.Keys.Space; + int rc; + do { + rc = ToUnicodeEx(key, MapVirtualKeyEx(key, 0, hkl), new byte[255], sb, sb.Capacity, 0, hkl); + } while(rc < 0); + } + + public static WinForms.Keys ToKeys(this Key key) + { + WinForms.Keys result; + if (Enum.TryParse(key.ToString(), out result)) + return result; + return WinForms.Keys.None; + } } } diff --git a/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs b/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs index 6dde062a06..d770adea41 100644 --- a/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs +++ b/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs @@ -42,7 +42,7 @@ namespace ICSharpCode.Core.Presentation if (!string.IsNullOrEmpty(codon.Properties["shortcut"])) { KeyGesture kg = MenuService.ParseShortcut(codon.Properties["shortcut"]); MenuCommand.AddGestureToInputBindingOwner(inputBindingOwner, kg, this.Command, GetFeatureName()); - this.inputGestureText = kg.GetDisplayStringForCulture(Thread.CurrentThread.CurrentUICulture); + this.inputGestureText = MenuService.GetDisplayStringForShortcut(kg); } UpdateText();