tactil - Cómo hacer que el control de entrada de WPF muestre el teclado virtual cuando se enfocó en la pantalla táctil
teclado virtual en c# (7)
Creé una biblioteca para automatizar todo lo relacionado con la integración de TabTip en la aplicación WPF.
Puede obtenerlo en nuget , y después de eso, todo lo que necesita es una configuración simple en la lógica de inicio de sus aplicaciones:
TabTipAutomation.BindTo<TextBox>();
Puede enlazar la lógica de automatización de TabTip a cualquier UIElement. El teclado virtual se abrirá cuando cualquier elemento del tipo especificado se enfoque, y se cerrará cuando el elemento pierda el foco. No solo eso, sino que TabTipAutomation moverá UIElement (o Window) a la vista, de modo que TabTip no bloquee el elemento enfocado.
Para más información consulte el sitio del proyecto .
Para nuestra aplicación WPF, cuando se ejecuta en la pantalla táctil (Surface Pro .etc), el TextBox
/ PasswordBox
no puede mostrar el teclado virtual cuando se enfocan.
¿Alguna buena manera de implementar esta característica en WPF?
Actualizado:
Lo que queremos lograr finalmente es algo así:
Si el usuario ejecuta la aplicación en la PC , no nos importa esta función, lo que significa que si el usuario tiene un teclado físico, no hacemos nada como la aplicación WPF que se ejecuta en la PC.
Si el usuario se ejecuta en Surface Pro , cuando hace clic en el TextBox
, el teclado virtual incorporado puede aparecer y debería ser fácil de usar, como el teclado nunca cubrirá el elemento de entrada.
Actualizado 2:
Entonces, ¿WPF no puede establecer fácilmente alguna propiedad para implementar esta característica? En mi opinión, esta característica debe estar incorporada en WPF, no entiendo por qué no puedo encontrar una manera fácil de lograr.
Esta solución es muy simple: http://code.msdn.microsoft.com/windowsapps/Enabling-Windows-8-Touch-7fb4e6de
Los pasos se detallan en el enlace de arriba, aquí está la versión corta:
- Añadir una referencia UIAutomationClient
- Use IFrameworkInputPane desde el código administrado (DLL en el enlace o convierta inputpanelconfiguration.idl a DLL, vea los pasos a continuación)
- Cree una nueva clase InkInputHelper para deshabilitar el soporte de entintado (código a continuación)
- Llame a
InkInputHelper.DisableWPFTabletSupport();
del constructorMainWindow
o similar - Añadir
using System.Windows.Interop;
Añadir a MainWindow_Loaded o similar:
System.Windows.Automation.AutomationElement asForm = System.Windows.Automation.AutomationElement.FromHandle(new WindowInteropHelper(this).Handle); InputPanelConfigurationLib.InputPanelConfiguration inputPanelConfig = new InputPanelConfigurationLib.InputPanelConfiguration(); inputPanelConfig.EnableFocusTracking();
Para convertir inputpanelconfiguration.idl a DLL
En Windows 8.1: c: / Archivos de programa (x86) / Windows Kits / 8.1 / Include / um / inputpanelconfiguration.idl
Para construir una DLL desde el IDL siga los siguientes pasos:
- Iniciar un indicador de comando
- Utilice la herramienta de compilación MIDL para crear un archivo TLB de biblioteca de tipos
- Ejemplo:
midl /tbld {filename}
- Ejemplo:
- Use la herramienta TLBIMP para convertir la biblioteca de tipos (archivo TLB) generada anteriormente en una DLL que .NET puede usar ejecutando el siguiente comando
- Ejemplo:
TLBIMP.exe InputpanelConfiguration.tlb /publickey:{pathToKey} /delaysign
- Ejemplo:
Clase 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 });
}
}
}
}
}
}
Esto debería funcionar. Una vez más, mucho mejor información y una muestra descargable en el enlace. Solo copio lo básico pegado para fines de archivo.
He publicado una muestra sobre cómo activar el teclado táctil en las aplicaciones WPF cuando un usuario hace clic en un cuadro de texto, está aquí:
http://code.msdn.microsoft.com/Enabling-Windows-8-Touch-7fb4e6de
Ha sido algo en lo que he estado trabajando durante muchos meses, me complace poder contribuir finalmente con este ejemplo a nuestra comunidad. Déjeme saber si hay preguntas, sugerencias, problemas, etc. en el panel de preguntas y respuestas de muestra
La opción más fácil cuando no se requiere la salida de SecureString es usar TextBox y usar algo como Wingdings como fuente.
Prueba esto,
Primero verifica la presencia de un teclado físico:
KeyboardCapabilities keyboardCapabilities = new Windows.Devices.Input.KeyboardCapabilities();
return keyboardCapabilities.KeyboardPresent != 0 ? true : false;
Si no encuentra un teclado físico, use el teclado virtual integrado de Windows:
Process.Start(Environment.GetFolderPath(Environment.SpecialFolder.System) + Path.DirectorySeparatorChar + "osk.exe");
Vi esto hecho en una sesión de TechEd, primero debe desactivar el soporte de entintado (DisableWPFTabletSupport), luego puede crear una configuración de configuración de entrada (AutomationElement.FromHandle (nuevo WindowsInteropHelper (this) .Handle) y llamar a 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
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 });
}
}
}
}
}
use esa clase para determinar si hay un teclado físico o una forma similar que pueda satisfacer sus necesidades.
Utilicé esta clase para abrir y cerrar el teclado donde quisiera.
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");
}
}
tenga en cuenta lo siguiente: agregué una copia de osk.exe Y tabtip.exe. agregando esto en mi programa resolví un problema donde tabtip u osk no funcionaban en 32/64 bits.
osk es el teclado, tabtip es la versión acoplada del mismo. keyboardexecuter es un programa que hice que se usa como un método alternativo.
nota * actualmente no puedo probar esto en un dispositivo de pantalla táctil. Tienes que intentarlo por tu cuenta.
Para que esto funcione correctamente, utilicé este código en mi ventana principal:
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;
//}
Incluí los comentarios porque podría ser útil para alguien si hay un error.
La configuración del panel de entrada:
[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
{
}
Espero que esto pueda ayudar a los futuros visitantes de esta pregunta.