如何编写本地化的屏幕键盘

发布于 2024-10-13 12:27:42 字数 872 浏览 7 评论 0原文

我必须为我们公司的程序编写一个屏幕键盘,该程序主要用于具有触摸功能的工业PC。

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

我已经找到此博客作为参考,但我不知道如何开始。

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

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

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

编辑:

好吧,我做了更多研究,并提出了一个读取当前键盘布局的 osk甚至可以处理简单的 shift 状态(ShiftAlt Gr)。我写了一个继承自Button的KeyButton类,这个KeyButton有一个byte类型的ScanCode属性,如果你为其指定有效的扫描码,KeyButton将调用相关函数来获取正确的文本。我使用了 Michael Kaplan 博客中的功能,并做了一些小改动。最后发现我只得像他一样做。

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

现在我得到了字符剩下的唯一一件事就是将这些发送出去。

I have to write an on screen keyboard for our company's program, which is mostly used on industry's PCs with touch capability.

We can't use the windows default keyboard because we don't need all keys on the keyboard. So I was asked to write a custom one in C#.

I already found this blog as reference, but I'm not sure how to start.

I created a small prototype GUI and assign for each key a scancode, and translate these scancodes to the related character. And send them to the active control. But I'm not sure what scancodes I should use.

So my question is, is that the correct way to write a OSK like this and if yes which scancodes should I use? Any links?

I'm also not sure how to handle the shift states...

Edit:

Okay I did a bit more research and came up with a osk which reads the current keyboard layout and even handles the easy shift states (Shift and Alt Gr). I wrote a KeyButton class which inherits from Button, this KeyButton has a ScanCode property of type byte and if you assign a valid scancode to it, the KeyButton will call the related functions to get the correct text. I used the functions from Michael Kaplan blogs with some small changes. In the end it turned out that I just had to do the same as he did.

So the answer to my question is: Yes, you have to use scancodes on your buttons and then get the virtualkey and the unicode from the keyboard layout. Use these scancodes.

Now I get the characters the only thing left is to send these around.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

舟遥客 2024-10-20 12:27:42

我认为这相当简单,只需制作一系列按钮并为每个按钮分配一个字母,然后在按钮内部的 Click 方法就可以做一个简单的。

SendKeys.Send("A"); 

根据按钮等更改键

I think this is fairly simple, just make a series of buttons and assign each button a letter, and inside the buttons Click method you can do a simple.

SendKeys.Send("A"); 

Changing key based on button etc

苍景流年 2024-10-20 12:27:42

我编写了映射类,将关键代码映射到 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);
}

I wrote mapping classes that map key code to character for WPF application.
May be this can help.

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);
}
独闯女儿国 2024-10-20 12:27:42

您可能想看看这些人:

http://cnt.lakefolks.com/

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

You might want to check out these guys:

http://cnt.lakefolks.com/

Might be cheaper just to buy it rather than develop it, ya never know ;-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文