Виртуальная экранная клавиатура, реализация через GDI+

Страницы:  1

Ответить
 

Professor Seleznov


pic
После получения задачи использования в своём проекте экранной клавиатуры для сенсорного устройства я начал искать способы её реализации. Из возможных вариантов под Windows мне повстречались такие решения:
  • Встроенная клавиатура TabTip, osk.exe - не имеют возможностей гибкой кастомизации, появляются по произвольным координатам экрана и имеют только определенный размер.
  • Бесплатные решения - у таких подходов страдала реализация и компоненты выглядели даже похуже встроенной Windows клавиатуры.
  • Платные аналоги - действительно являются хорошей альтернативой со множеством необходимых настроек, но не было никакой бюджетной возможности покупать профессиональные решения.
В итоге своя клавиатура была создана с нуля — полностью на GDI+.
Эта статья - переработанная и дополненная версия моего материала, опубликованного в 2017 году на CodeProject.
Архив оригинала.
Описание решения
В проекте реализовано  два пользовательских элемента: самостоятельно отрисованная клавиатура-эмулятор и текстовое поле с этой всплывающей клавиатурой.
Приложенный пользовательский WinForms компонент может быть настроен под нужды интерфейса вашего приложения и позволяет манипулировать внешним видом/дизайном и поведением.
Настройка компонента
VirtualKeyboard - пользовательский WinForms-контрол создан, в основном с помощью программироваания GDI+. Этому элементу управления присуще следующие свойства:
  • FirstRowCustomButtonsFifthRowCustomButtons - списки клавиш соответствующего ряда.
  • признак состояния клавиш клавиатуры: Shift, CapsLock, Alt ... (ShiftState, AltState …).
  • возможность скрыть/показать функциональные кнопки: Delete, Tab, Ctrl, кнопки со стрелками, цифровые кнопки (ShowDel, ShowTab … ).
  • визуальные настройки (цвет фона, шрифты).
  • показывать или нет только цифровой вариант (IsNumeric).
Каждая клавиша клавиатуры представлена классом-объектом VirtualKbButtonс отдельными свойствами:
  • верхний и нижний текст (TopText/BottomText).
  • шрифты для верхней и нижней части (TopFont/BottomFont).
  • признак, может ли кнопка отправлять команду (CanSendCommand).
  • тег и имя (Tag, ButtonName).
  • изображение (Picture).
Изменение  раскладки, работа с клавишами
По умолчанию создаётся стандартная английская раскладка, но её можно полностью заменить. Код для создания раскладки по-умолчанию расположен в классе KeyboardLayout.
Пользователь клавиатуры может работать или с отдельной  кнопкой, либо с рядом, содержащим список Listклавиш.
Пример добавления кнопки:
var btn = new VirtualKbButton();
btn.TopText = "www";
btn.Tag = "btn_Internet";
virtualKeyboard1.FifthRowCustomButtons.Add(btn);
Пример удаления клавиши:
buttons.Remove(buttons[buttons.Count - 1]);
Пример создания своего второго ряда клавиш:
var row = new ButtonsCollection
{
new VirtualKbButton("A", ""), new VirtualKbButton("B", ""),
new VirtualKbButton("C", ""), new VirtualKbButton("D", ""),
new VirtualKbButton("E", ""), new VirtualKbButton("F", "")
};
virtualKeyboard1.SecondRowCustomButtons = row;
Можно подгружать раскладки из внешних источников, например XML.
Пользователь может сам обрабатывать нажатие кнопки клавиатуры через событие ButtonClick. Например:
private void virtualKeyboard_KeyboardButtonPressed(string command, KeyboardButtonEventArgs e)
{
switch (command)
{
case "a":
Debug.WriteLine("Нажат символ 'a'");
break;
case "Backspace":
Debug.WriteLine("Нажат 'Back space'");
break;
default:
Debug.WriteLine($"Клавиша '{command}'");
break;
}
}
Тексты команд, которые посылают специальные кнопки (Tab, Enter, Backspace…)  находятся в классе KeyboardKeyConstants.
За счёт этого клавиатура легко адаптируется под любые задачи.
Как реализуются нажатия
С помощью метода SendKeys.Send каждая кнопка может симулировать нажатие клавиши.
Поддерживаются:
  • обычные символы:
SendKeys.Send("a"); //Нажат символ 'a'
SendKeys.Send("~"); // Нажат символ '~'
  • спецсимволы, которые нужно обернуть фигурными скобками:
SendKeys.Send("{%}"); // Нажат символ '%'
SendKeys.Send("{+}"); // Нажат символ '+'
  • специальные клавиши (ENTER, ESC)
SendKeys.Send("{ENTER}");
SendKeys.Send("{ESC}");
  • комбинации( "+" для Shift, "^" для Ctrl, "%" для Alt):
SendKeys.Send("^c");    // Ctrl + C
SendKeys.Send("^%s"); // Ctrl + Alt + S
SendKeys.Send("%{F4}"); // Alt + F4
Как работать с внешними приложениями
Когда пользователь кликает или нажимает пальцем другое окно или приложение (например, Notepad), то текущее окно с клавиатурой теряет активность. Поэтому можно предложить два решения:
  • при потере фокуса окна с клавиатурой использовать стили окна:
    • WS_EX_NOACTIVATE
    • WS_EX_TOPMOST
  • при коммуникации со сторонними приложениями запускать клавиатуру в отдельном потоке:
ThreadPool.QueueUserWorkItem(KeyboardLoop);
Вывод
Несмотря на возраст технологии, реализованное решение можно использовать в нишевых или ограниченных системах:
  • киоски и терминалы 
  • embedded-устройства
  • старые WinForms-приложения
Однако, если писать приложение сейчас, лучше использовать WPF, MAUI или web based приложение.
Исходный код
Весь проект выложен на GitHub по ссылке.
Там вы найдёте:
  • Полный код VirtualKeyboard
  • Демо-проект с примерами настройки
  • Готовые DLL для быстрого подключения
-Источник
 
Loading...
Error