【问题标题】:How to write an localized on-screen-keyboard如何编写本地化的屏幕键盘
【发布时间】:2011-06-14 11:09:12
【问题描述】:

我要为我们公司的程序写一个屏幕键盘,这个程序主要用在工业上带有触摸功能的PC上。

我们不能使用 windows 默认键盘,因为我们不需要键盘上的所有键。所以我被要求用 C# 编写一个自定义的。

我已经找到this blog 作为参考,但我不知道如何开始。

我创建了一个小型原型 GUI,并为每个键分配了一个扫描码,并将这些扫描码转换为相关字符。并将它们发送到活动控件。但我不确定我应该使用什么扫描码。

所以我的问题是,这样编写 OSK 是否正确,如果是,我应该使用哪些扫描码?有链接吗?

我也不确定如何处理 shift 状态...

编辑:

好吧,我做了更多的研究,想出了一个 osk,它可以读取当前的键盘布局,甚至可以处理简单的 shift 状态(Shift 和 Alt gr)。我写了一个KeyButton 类,它继承自Button,这个KeyButton 有一个字节类型的ScanCode 属性,如果你给它分配一个有效的扫描码,KeyButton 将调用相关函数来获得正确的文本。我使用了 Michael Kaplan 博客中的函数并进行了一些小改动。最后结果证明我只需要和他一样。

所以我的问题的答案是:是的,您必须在按钮上使用扫描码,然后从键盘布局中获取虚拟键和 unicode。 Use these scancodes.

现在我得到了字符,唯一剩下的就是发送这些字符了。

【问题讨论】:

  • 这个 OSK 是用于一般用途还是专门用于给定软件? (即,您会将扫描代码提供给 Windows 事件总线还是将字符代码发送给 Winforms 应用程序?)差异很大。
  • 对于我们的软件,所以我想将字符代码发送到文本框。但我想使用键盘布局,就像 windows 中的默认 osk 一样。
  • 我不确定,如果有进展我会更新帖子。

标签: c# windows keyboard screen localized


【解决方案1】:

我觉得这个比较简单,就是做一系列的按钮,给每个按钮分配一个字母,在按钮的Click方法里面就可以做一个简单的了。

SendKeys.Send("A"); 

根据按钮等更改键

【讨论】:

  • 是的,但我想使用 windows 的键盘布局。
【解决方案2】:

我为 WPF 应用程序编写了将关键代码映射到字符的映射类。 这可能会有所帮助。

public class KeyMapper
{
    /// <summary>
    /// Map key code to character.
    /// If key code cannot be mapped returns empty char.
    /// </summary>
    public static char MapKey(Key key, bool shiftPressed, string culture)
    {
        CheckCulture(culture);
        int englishVirtuaCode = KeyInterop.VirtualKeyFromKey(key);
        return EnglishVirtualCodeToChar(englishVirtuaCode, shiftPressed, culture);
    }

    private static void CheckCulture(string culture)
    {
        InputLanguage language = InputLanguage.FromCulture(new CultureInfo(culture));
        if (language == null)
            throw new ArgumentException(string.Format("culture {0} does not exist.", culture));
    }

    private static char EnglishVirtualCodeToChar(int enlishVirtualCode, bool shiftPressed, string culture)
    {
        var scanCode = KeyMappingWinApi.MapVirtualKeyEx((uint)enlishVirtualCode, 0, EnglishCultureHandle);
        var vitualKeyCode = KeyMappingWinApi.MapVirtualKeyEx(scanCode, 1, GetCultureHandle(culture));
        byte[] keyStates = GetKeyStates(vitualKeyCode, shiftPressed);
        const int keyInformationSize = 5;
        var stringBuilder = new StringBuilder(keyInformationSize);
        KeyMappingWinApi.ToUnicodeEx(vitualKeyCode, scanCode, keyStates, stringBuilder, stringBuilder.Capacity, 0, GetCultureHandle(culture));
        if (stringBuilder.Length == 0)
            return ' ';
        return stringBuilder[0];
    }

    private static IntPtr EnglishCultureHandle
    {
        get { return GetCultureHandle("en-US"); }
    }

    private static IntPtr GetCultureHandle(string culture)
    {
        return InputLanguage.FromCulture(new CultureInfo(culture)).Handle;
    }

    /// <summary>
    /// Gets key states for ToUnicodeEx function
    /// </summary>
    private static byte[] GetKeyStates(uint keyCode, bool shiftPressed)
    {
        const byte keyPressFlag = 0x80;
        const byte shifPosition = 16; // position of Shift key in keys array
        var keyStatses = new byte[256];
        keyStatses[keyCode] = keyPressFlag;
        keyStatses[shifPosition] = shiftPressed ? keyPressFlag : (byte)0;
        return keyStatses;
    }
}

public class KeyMappingWinApi
{
    [DllImport("user32.dll")]
    public static extern uint MapVirtualKeyEx(uint uCode, uint uMapType, IntPtr dwhkl);

    [DllImport("user32.dll")]
    public 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")]
    public static extern short VkKeyScanEx(char ch, IntPtr dwhkl);
}

【讨论】:

    【解决方案3】:

    你可能想看看这些人:

    http://cnt.lakefolks.com/

    购买它而不是开发它可能更便宜,你永远不知道;-)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-29
      • 1970-01-01
      • 1970-01-01
      • 2019-01-10
      • 1970-01-01
      • 1970-01-01
      • 2015-07-16
      相关资源
      最近更新 更多