Как написать локализованную экранную клавиатуру
Я должен написать экранную клавиатуру для программы нашей компании, которая в основном используется на промышленных ПК с сенсорным экраном.
Мы не можем использовать клавиатуру Windows по умолчанию, потому что нам не нужны все клавиши на клавиатуре. Поэтому мне было предложено написать пользовательский в C#.
Я уже нашел этот блог в качестве ссылки, но я не уверен, как начать.
Я создал небольшой прототип GUI и назначил для каждого ключа скан-код, и перевел эти скан-коды на соответствующий символ. И отправить их в активный контроль. Но я не уверен, какие коды сканирования мне следует использовать.
Итак, мой вопрос, это правильный способ написать OSK, как это, и если да, какие коды сканирования я должен использовать? Есть ссылки?
Я также не уверен, как справиться со сменой состояний...
Редактировать:
Хорошо, я провел немного больше исследований и придумал оск, который читает текущую раскладку клавиатуры и даже обрабатывает состояния легкого переключения (Shift и Alt Gr). Я написал KeyButton
класс, который наследуется от Button
, этот KeyButton
имеет ScanCode
свойство типа byte, и если вы назначите ему действительный код сканирования, KeyButton
вызовет связанные функции, чтобы получить правильный текст. Я использовал функции из блогов Майкла Каплана с некоторыми небольшими изменениями. В итоге оказалось, что я просто должен был сделать то же, что и он.
Итак, ответ на мой вопрос: да, вы должны использовать сканкоды на своих кнопках, а затем получить виртуальную клавишу и юникод из раскладки клавиатуры. Используйте эти коды сканирования.
Теперь у меня есть персонажи, единственное, что осталось, это отправить их.
3 ответа
Я думаю, что это довольно просто, просто сделайте серию кнопок и назначьте каждой кнопке букву, а внутри метода нажатия кнопок вы можете сделать простой.
SendKeys.Send("A");
Смена ключа в зависимости от кнопки и т. Д.
Я написал классы отображения, которые отображают код ключа на символ для приложения 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);
}
Вы можете проверить этих парней:
Может быть, дешевле просто купить его, чем разрабатывать его, никогда не знаешь;-)