Как заставить управление вводами WPF показывать виртуальную клавиатуру, когда она попадает в сенсорный экран
Для нашего приложения WPF, когда он работает на сенсорном экране (Surface Pro.etc), элемент управления TextBox
/PasswordBox
не может отображать виртуальную клавиатуру, когда они сосредоточиться.
Любой хороший способ реализовать эту функцию в WPF?
Обновлено:
то, чего мы хотим достичь, наконец-то выглядит следующим образом:
Если пользователь запускает приложение на ПК, нам не нужна эта функция, а это означает, что у пользователя есть физическая клавиатура, мы ничего не делаем, как обычное приложение WPF, запущенное на ПК.
Если пользователь работает на Surface Pro, когда он нажимает кнопку TextBox
, встроенная виртуальная клавиатура может отображаться и которая должна быть удобной для пользователя, например, клавиатура никогда не будет закрываться элемент ввода.
Обновлено 2:
Итак, WPF не может легко установить какое-либо свойство для реализации этой функции? На мой взгляд, эта функция должна быть встроена в WPF, я не понимаю, почему я не могу найти простой способ достичь.
Ответы
Ответ 1
Попробуйте это,
Сначала проверьте наличие физической клавиатуры:
KeyboardCapabilities keyboardCapabilities = new Windows.Devices.Input.KeyboardCapabilities();
return keyboardCapabilities.KeyboardPresent != 0 ? true : false;
Если вы не найдете физическую клавиатуру, используйте встроенную виртуальную клавиатуру окон:
Process.Start(Environment.GetFolderPath(Environment.SpecialFolder.System) + Path.DirectorySeparatorChar + "osk.exe");
Получите помощь отсюда:
ссылка 1
ссылка 2
Ответ 2
Я опубликовал образец того, как запускать сенсорную клавиатуру в приложениях WPF, когда пользователь нажимает на текстовое поле, здесь:
http://code.msdn.microsoft.com/Enabling-Windows-8-Touch-7fb4e6de
Это то, над чем я работал много месяцев, я рад наконец внести этот пример в наше сообщество. Пожалуйста, дайте мне знать, есть ли какие-либо вопросы, предложения, проблемы и т.д. В поле Q & A
Ответ 3
Это решение очень просто:
http://code.msdn.microsoft.com/windowsapps/Enabling-Windows-8-Touch-7fb4e6de
Шаги подробно описаны в приведенной выше ссылке, вот короткая версия:
- Добавить ссылку UIAutomationClient
- Использовать IFrameworkInputPane из управляемого кода (DLL по ссылке или конвертировать inputpanelconfiguration.idl в DLL, см. шаги ниже)
- Создайте новый класс InkInputHelper для отключения поддержки чернил (код ниже)
- Вызов
InkInputHelper.DisableWPFTabletSupport();
из MainWindow
конструктора или аналогичного
- Добавить
using System.Windows.Interop;
-
Добавить в MainWindow_Loaded или подобное:
System.Windows.Automation.AutomationElement asForm =
System.Windows.Automation.AutomationElement.FromHandle(new WindowInteropHelper(this).Handle);
InputPanelConfigurationLib.InputPanelConfiguration inputPanelConfig = new InputPanelConfigurationLib.InputPanelConfiguration();
inputPanelConfig.EnableFocusTracking();
Чтобы преобразовать inputpanelconfiguration.idl в DLL
В Windows 8.1:
c:\Program Files (x86)\Windows Kits\8.1\Include\um\inputpanelconfiguration.idl
Чтобы создать DLL из IDL, выполните следующие действия:
- Запустите командную строку
- Используйте средство компиляции MIDL для создания TLB файла библиотеки типов
- Пример:
midl /tbld {filename}
- Используйте инструмент TLBIMP для преобразования вышеприведенной библиотеки типов (TLB файла) в DLL, которую .NET может использовать, выполнив следующую команду
- Пример:
TLBIMP.exe InputpanelConfiguration.tlb /publickey:{pathToKey} /delaysign
Класс InkInputHelper:
using System;
using System.Reflection;
using System.Windows.Input;
namespace ModernWPF.Win8TouchKeyboard.Desktop
{
public static class InkInputHelper
{
public static void DisableWPFTabletSupport()
{
// Get a collection of the tablet devices for this window.
TabletDeviceCollection devices = System.Windows.Input.Tablet.TabletDevices;
if (devices.Count > 0)
{
// Get the Type of InputManager.
Type inputManagerType = typeof(System.Windows.Input.InputManager);
// Call the StylusLogic method on the InputManager.Current instance.
object stylusLogic = inputManagerType.InvokeMember("StylusLogic",
BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
null, InputManager.Current, null);
if (stylusLogic != null)
{
// Get the type of the stylusLogic returned from the call to StylusLogic.
Type stylusLogicType = stylusLogic.GetType();
// Loop until there are no more devices to remove.
while (devices.Count > 0)
{
// Remove the first tablet device in the devices collection.
stylusLogicType.InvokeMember("OnTabletRemoved",
BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic,
null, stylusLogic, new object[] { (uint)0 });
}
}
}
}
}
}
Это должно сработать. Опять же, гораздо лучшая информация и загружаемый образец в ссылке. Я только копировал вставку основ для целей архивирования.
Ответ 4
Я создал библиотеку для автоматизации всего, что касается интеграции TabTip в приложении WPF.
Вы можете получить его на nuget, и после этого все, что вам нужно, это простая конфигурация в логике запуска приложений:
TabTipAutomation.BindTo<TextBox>();
Вы можете связать логику автоматизации TabTip с любым UIElement. Виртуальная клавиатура откроется, когда любой элемент указанного типа получит фокус, и он закроется, когда элемент потеряет фокус. Не только это, но TabTipAutomation переместит UIElement (или Window) в представление, так что TabTip не будет блокировать сфокусированный элемент.
Для получения дополнительной информации обратитесь к сайту проекта.
Ответ 5
Я видел это в сеансе TechEd, вам нужно сначала отключить поддержку Inking (DisableWPFTabletSupport), затем вы можете создать InputPanelConfiguration (AutomationElement.FromHandle(новый WindowsInteropHelper (this).Handle) и вызвать EnableFocusTracking.
DisableWPFTabletSupport: http://msdn.microsoft.com/en-us/library/ee230087.aspx
EnableFocusTracking: http://msdn.microsoft.com/en-us/library/windows/desktop/jj126268(v=vs.85).aspx
Ответ 6
public static class InkInputHelper
{
public static void DisableWPFTabletSupport()
{
// Get a collection of the tablet devices for this window.
TabletDeviceCollection devices = System.Windows.Input.Tablet.TabletDevices;
if (devices.Count > 0)
{
// Get the Type of InputManager.
Type inputManagerType = typeof(System.Windows.Input.InputManager);
// Call the StylusLogic method on the InputManager.Current instance.
object stylusLogic = inputManagerType.InvokeMember("StylusLogic",
BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
null, InputManager.Current, null);
if (stylusLogic != null)
{
// Get the type of the stylusLogic returned from the call to StylusLogic.
Type stylusLogicType = stylusLogic.GetType();
// Loop until there are no more devices to remove.
while (devices.Count > 0)
{
// Remove the first tablet device in the devices collection.
stylusLogicType.InvokeMember("OnTabletRemoved",
BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic,
null, stylusLogic, new object[] { (uint)0 });
}
}
}
}
}
используйте этот класс, чтобы определить, есть ли физическая клавиатура или аналогичный способ, который может лучше соответствовать вашим потребностям.
Я использовал этот класс, чтобы открывать и закрывать клавиатуру там, где я хотел.
class KeyboardManager
{
public static void LaunchOnScreenKeyboard()
{
var processes = Process.GetProcessesByName("osk").ToArray();
if (processes.Any())
return;
string keyboardManagerPath = "KeyboardExecuter.exe";
Process.Start(keyboardManagerPath);
}
public static void KillOnScreenKeyboard()
{
var processes = Process.GetProcessesByName("osk").ToArray();
foreach (var proc in processes)
{
proc.Kill();
}
}
public static void killTabTip()
{
var processes = Process.GetProcessesByName("TabTip").ToArray();
foreach (var proc in processes)
{
proc.Kill();
}
}
public static void LaunchTabTip()
{
Process.Start("TabTip.exe");
}
}
помните следующее:
Я добавил копию обоих osk.exe AND tabtip.exe.
добавив, что в моей программе решена проблема, когда либо tabtip, либо osk не будут работать с 32/64 бит.
osk - клавиатура, tabtip - это закрепленная версия.
keyboardexecuter - это программа, которую я сделал, которая используется в качестве резервного метода.
note * В настоящее время я не могу проверить это на устройстве с сенсорным экраном. вы должны попробовать это самостоятельно.
для этого, чтобы все работало правильно, я использовал этот код в моем главном окне:
public int selectedTableNum;
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
// Disables inking in the WPF application and enables us to track touch events to properly trigger the touch keyboard
InkInputHelper.DisableWPFTabletSupport();
//remove navigationbar
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
{
var navWindow = Window.GetWindow(this) as NavigationWindow;
if (navWindow != null) navWindow.ShowsNavigationUI = false;
}));
KeyboardManager.LaunchTabTip();
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
//Windows 8 API to enable touch keyboard to monitor for focus tracking in this WPF application
InputPanelConfiguration cp = new InputPanelConfiguration();
IInputPanelConfiguration icp = cp as IInputPanelConfiguration;
if (icp != null)
icp.EnableFocusTracking();
mainFrame.Content = new LoginPage();
}
//public bool HasTouchInput()
//{
// foreach (TabletDevice tabletDevice in Tablet.TabletDevices)
// {
// //Only detect if it is a touch Screen not how many touches (i.e. Single touch or Multi-touch)
// if (tabletDevice.Type == TabletDeviceType.Touch)
// return true;
// }
// return false;
//}
i включил комментарии, потому что может быть полезно кому-то, если есть ошибка.
конфигурация входной панели:
[Guid("41C81592-514C-48BD-A22E-E6AF638521A6")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IInputPanelConfiguration
{
/// <summary>
/// Enables a client process to opt-in to the focus tracking mechanism for Windows Store apps that controls the invoking and dismissing semantics of the touch keyboard.
/// </summary>
/// <returns>If this method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.</returns>
int EnableFocusTracking();
}
[ComImport, Guid("2853ADD3-F096-4C63-A78F-7FA3EA837FB7")]
class InputPanelConfiguration
{
}
Надеюсь, это поможет будущим посетителям этого вопроса.
Ответ 7
При нацеливании на .Net 4.6.2
+ вам не нужно ничего делать:
https://riptutorial.com/wpf/example/23104/showing-touch-keyboard-on-windows-8-and-windows-10
Ответ 8
Самый простой вариант, когда не требуется вывод SecureString, - использовать TextBox и использовать что-то вроде Wingdings в качестве шрифта.