Lie*_*oen 6 c# culture infragistics localization user32
经过与Infragistics的长时间讨论后,看来带有SHIFT的ShortCuts在我的文化"nl-BE"中显示为MAJ.首先,文化"nl-BE"和AZERTY有点奇怪.如果想了解更多,请阅读http://en.wikipedia.org/wiki/AZERTY.重要的是:
其他键是相同的,即使传统上特殊键的名称用英语打印在它们上面.这是因为比利时主要是双语(法语 - 荷兰语)和官方三种语言(第三语言,德语,在东方语言中使用).
所以MAJ印刷为SHIFT.例如,在Office中,带有SHIFT的快捷方式显示为SHIFT.在Infragistics控件中,它们显示为MAJ.这让我们的客户感到沮丧.
因此,在与Infragistics讨论后,他们声称这是一个Windows Api调用,它返回MAJ而不是SHIFT.我从他们那里得到了一个展示行为的示例项目.所以现在我的问题是为什么Windows Api调用不会返回SHIFT,如果它是正常的,那么Office如何才能正确显示它?
获取密钥文本的代码是:
NativeWindowMethods.GetKeyNameText((int)scanCode, sb, 256);
Run Code Online (Sandbox Code Playgroud)
和
class NativeWindowMethods
{
#region MapVirtualKey
[DllImport("user32.dll")]
internal static extern int MapVirtualKey(uint uCode, uint uMapType);
#endregion //MapVirtualKey
#region GetKeyNameText
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern int GetKeyNameText(
int lParam,
[MarshalAs(UnmanagedType.LPWStr), Out]System.Text.StringBuilder str,
int size);
#endregion //GetKeyNameText
}
Run Code Online (Sandbox Code Playgroud)
如果是Shiftkey,则扫描码为2752512(2a),并返回MAJ.
那么,我的问题是什么?
为了完整性,我将粘贴Utilities类的完整代码.从Form下一次调用完成:
systemLocalizedString = Utilities.GetLocalizedShortcutString(shortcut);
使用快捷键= ShiftF12.调用后,systemLocalizedString等于"MAJ + F12".
更新:在Hans Passant的帮助下,我下载了Microsoft Keyboard Layout Creator并导出了我当前的键盘布局.在.klc文件中没有找到MAJ,只有Shift(例如2a Shift).那么为什么user32.dll会返回MAJ?甚至更奇怪的是,当我复制.klc文件并将其安装为新键盘时,突然user32.dll确实为新安装的键盘返回Shift(虽然它是一个精确的副本).
Utilities.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
class Utilities
{
#region GetLocalizedShortcutString
/// <summary>
/// Returns the localized string for the specified <b>Shortcut</b>
/// </summary>
/// <param name="shortcut">Shortcut to localize</param>
/// <param name="separator">Character used to separate multiple keys in the shortcut</param>
/// <returns>A string containing the localized description of the shortcut based on the currently mapped keyboard layout</returns>
public static string GetLocalizedShortcutString(Shortcut shortcut, char separator = '+')
{
if (shortcut == Shortcut.None)
return string.Empty;
return GetLocalizedKeyString((Keys)shortcut, separator);
}
#endregion //GetLocalizedShortcutString
#region GetLocalizedKeyString
/// <summary>
/// Returns the localized string for the specified <b>Keys</b>
/// </summary>
/// <param name="keys">Keys to localize</param>
/// <param name="separator">Character used to separate multiple keys</param>
/// <returns>A string containing the localized description of the keys based on the currently mapped keyboard layout</returns>
public static string GetLocalizedKeyString(Keys keys, char separator)
{
bool alt = ((long)keys & (long)Keys.Alt) != 0;
bool ctrl = ((long)keys & (long)Keys.Control) != 0;
bool shift = ((long)keys & (long)Keys.Shift) != 0;
// get the key involved
long value = (long)keys & 0xffff;
Keys key = (Keys)Enum.ToObject(typeof(Keys), value);
System.Text.StringBuilder sb = new System.Text.StringBuilder();
if (alt && key != Keys.Menu)
{
sb.Append(GetLocalizedKeyStringHelper(Keys.Menu));
sb.Append(separator);
}
if (ctrl && key != Keys.ControlKey)
{
sb.Append(GetLocalizedKeyStringHelper(Keys.ControlKey));
sb.Append(separator);
}
if (shift && key != Keys.ShiftKey)
{
sb.Append(GetLocalizedKeyStringHelper(Keys.ShiftKey));
sb.Append(separator);
}
sb.Append(GetLocalizedKeyStringHelper(key));
return sb.ToString();
}
#endregion //GetLocalizedKeyString
#region GetLocalizedKeyStringHelper
private static string GetLocalizedKeyStringHelper(Keys key)
{
string localizedKey = GetLocalizedKeyStringUnsafe(key);
if (localizedKey == null || localizedKey.Length == 0)
return key.ToString();
return localizedKey;
}
#endregion //GetLocalizedKeyStringHelper
#region GetLocalizedKeyStringUnsafe
private static string GetLocalizedKeyStringUnsafe(Keys key)
{
// strip any modifier keys
long keyCode = ((int)key) & 0xffff;
System.Text.StringBuilder sb = new System.Text.StringBuilder(256);
long scanCode = NativeWindowMethods.MapVirtualKey((uint)keyCode, (uint)0);
// shift the scancode to the high word
scanCode = (scanCode << 16);
if (keyCode == 45 ||
keyCode == 46 ||
keyCode == 144 ||
(33 <= keyCode && keyCode <= 40))
{
// add the extended key flag
scanCode |= 0x1000000;
}
NativeWindowMethods.GetKeyNameText((int)scanCode, sb, 256);
return sb.ToString();
}
#endregion //GetLocalizedKeyStringUnsafe
}
class NativeWindowMethods
{
#region MapVirtualKey
[DllImport("user32.dll")]
internal static extern int MapVirtualKey(uint uCode, uint uMapType);
#endregion //MapVirtualKey
#region GetKeyNameText
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern int GetKeyNameText(int lParam, [MarshalAs(UnmanagedType.LPWStr), Out]System.Text.StringBuilder str, int size);
#endregion //GetKeyNameText
}
}
Run Code Online (Sandbox Code Playgroud)
但即使我使用的是AZERTY,这也是学校用来学习如何输入的东西......
是的,这就是问题所在.获得AZERTY布局的唯一方法是在控制面板+语言+添加语言中选择标题为"français(Belgique)"的键盘布局.与"Nederlands(België)"布局相反,它有QWERTY安排.GetKeyNameText()winapi函数返回在键盘布局文件中编码的字符串.对于名为français的键盘布局,法语当然是法语,因此MAJ是预期的结果.Windows没有提供带有AZERTY排列的荷兰语的键盘布局.
一切都没有丢失,Windows用户经常要求自定义键盘布局.因此,Microsoft提供了一个工具来创建自己的Microsoft键盘布局创建器.它主要用于重新安排钥匙,需要一点额外的肘部油脂才能使它达到你想要的效果.该工具不允许您直接编辑密钥描述并默认使用英文名称.您将要从文件+加载现有键盘开始.然后File + Save Layout将布局保存到.klc文件.在文本编辑器中打开它,记事本很好,找到名为KEYNAME和KEYNAME_EXT的部分,并按照您希望的方式编辑键名.
重新启动该实用程序(不要跳过)并重新加载.klc文件.并使用Project + Build DLL构建安装程序包.