Как написать локализованную экранную клавиатуру - PullRequest
5 голосов
/ 24 января 2011

Мне нужно написать экранную клавиатуру для программы нашей компании, которая в основном используется на промышленных ПК с сенсорным экраном.

Мы не можем использовать клавиатуру Windows по умолчанию, потому что нам не нужны все клавиши на клавиатуре. Поэтому меня попросили написать пользовательский на C #.

Я уже нашел этот блог в качестве ссылки, но я не уверен, как начать.

Я создал небольшой прототип GUI и назначил для каждого ключа скан-код, а затем преобразовал эти скан-коды в соответствующий символ. И отправить их в активный контроль. Но я не уверен, какие коды сканирования мне следует использовать.

Так что мой вопрос в том, является ли правильный способ написать OSK, подобный этому, и если да, то какие коды сканирования мне следует использовать? Любые ссылки?

Я также не уверен, как справиться с сдвигом состояний ...

Edit:

Хорошо, я немного больше исследовал и придумал оск, который читает текущую раскладку клавиатуры и даже обрабатывает простые состояния shift ( Shift и Alt Gr ). Я написал класс KeyButton, который наследуется от Button, у этого KeyButton есть свойство ScanCode типа byte, и если вы назначите ему действительный код сканирования, KeyButton вызовет связанные функции, чтобы получить правильный текст. Я использовал функции из блогов Майкла Каплана с некоторыми небольшими изменениями. В конце концов оказалось, что я просто должен был сделать то же, что и он.

Итак, ответ на мой вопрос: да, вы должны использовать сканкоды на своих кнопках, а затем получить виртуальную клавишу и юникод из раскладки клавиатуры. Используйте эти коды сканирования.

Теперь я получаю символы, единственное, что осталось, это отправить их.

Ответы [ 3 ]

1 голос
/ 26 января 2011

Я написал классы отображения, которые отображают код ключа на символ для приложения 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);
}
1 голос
/ 24 января 2011

Я думаю, что это довольно просто, просто сделайте серию кнопок и назначьте каждой кнопке букву, а внутри метода нажатия кнопок вы можете сделать простой.

SendKeys.Send("A"); 

Смена ключа в зависимости от кнопки и т. Д.

0 голосов
/ 09 апреля 2011

Вы можете проверить этих парней:

http://cnt.lakefolks.com/

Может быть, дешевле просто купить его, чем развивать, ты никогда не знаешь; -)

...