
После получения задачи использования в своём проекте экранной клавиатуры для сенсорного устройства я начал искать способы её реализации. Из возможных вариантов под Windows мне повстречались такие решения:
-
Встроенная клавиатура TabTip, osk.exe — не имеют возможностей гибкой кастомизации, появляются по произвольным координатам экрана и имеют только определенный размер.
-
Бесплатные решения — у таких подходов страдала реализация и компоненты выглядели даже похуже встроенной Windows клавиатуры.
-
Платные аналоги — действительно являются хорошей альтернативой со множеством необходимых настроек, но не было никакой бюджетной возможности покупать профессиональные решения.
В итоге своя клавиатура была создана с нуля — полностью на GDI+.
Эта статья — переработанная и дополненная версия моего материала, опубликованного в 2017 году на CodeProject.
Описание решения
В проекте реализовано два пользовательских элемента: самостоятельно отрисованная клавиатура-эмулятор и текстовое поле с этой всплывающей клавиатурой.
Приложенный пользовательский WinForms компонент может быть настроен под нужды интерфейса вашего приложения и позволяет манипулировать внешним видом/дизайном и поведением.
Настройка компонента
VirtualKeyboard — пользовательский WinForms-контрол создан, в основном с помощью программироваания GDI+. Этому элементу управления присуще следующие свойства:
-
FirstRowCustomButtons…FifthRowCustomButtons— списки клавиш соответствующего ряда. -
признак состояния клавиш клавиатуры: 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 + CSendKeys.Send("^%s"); // Ctrl + Alt + SSendKeys.Send("%{F4}"); // Alt + F4
Как работать с внешними приложениями
Когда пользователь кликает или нажимает пальцем другое окно или приложение (например, Notepad), то текущее окно с клавиатурой теряет активность. Поэтому можно предложить два решения:
-
при потере фокуса окна с клавиатурой использовать стили окна:
-
WS_EX_NOACTIVATE -
WS_EX_TOPMOST
-
-
при коммуникации со сторонними приложениями запускать клавиатуру в отдельном потоке:
ThreadPool.QueueUserWorkItem(KeyboardLoop);
Вывод
Несмотря на возраст технологии, реализованное решение можно использовать в нишевых или ограниченных системах:
-
киоски и терминалы
-
embedded-устройства
-
старые WinForms-приложения
Однако, если писать приложение сейчас, лучше использовать WPF, MAUI или web based приложение.
Исходный код
Весь проект выложен на GitHub по ссылке.
Там вы найдёте:
-
Полный код
VirtualKeyboard -
Демо-проект с примерами настройки
-
Готовые DLL для быстрого подключения
ссылка на оригинал статьи https://habr.com/ru/articles/1030360/