Pour notre application WPF, lorsqu'elle s'exécute sur écran tactile (Surface Pro .etc), le contrôle TextBox
/PasswordBox
ne peut pas afficher clavier virtuel = quand ils se concentrent.
Une bonne façon d'implémenter cette fonctionnalité dans WPF?
ce que nous voulons réaliser enfin, c'est quelque chose comme ça:
Si l'utilisateur exécute l'application sur PC, nous ne nous soucions pas de cette fonctionnalité, ce qui signifie que l'utilisateur dispose d'un clavier physique, nous ne faisons rien comme une application WPF normale exécutée sur PC.
Si l'utilisateur s'exécute sur Surface Pro, lorsqu'il clique sur TextBox
, le clavier virtuel intégré peut apparaître, et qui devrait être convivial, tel que le clavier ne couvrirait jamais jusqu'à l'élément d'entrée.
Donc, WPF ne peut pas facilement définir une propriété pour implémenter cette fonctionnalité? À mon avis, cette fonctionnalité devrait être intégrée à WPF, je ne comprends pas pourquoi je ne peux pas trouver un moyen facile d'y parvenir.
Essaye ça,
Vérifiez d'abord la présence d'un clavier physique:
KeyboardCapabilities keyboardCapabilities = new Windows.Devices.Input.KeyboardCapabilities();
return keyboardCapabilities.KeyboardPresent != 0 ? true : false;
Si vous ne trouvez pas de clavier physique, utilisez le clavier virtuel intégré de Windows:
Process.Start(Environment.GetFolderPath(Environment.SpecialFolder.System) + Path.DirectorySeparatorChar + "osk.exe");
J'ai publié un exemple sur la façon de déclencher le clavier tactile dans les applications WPF lorsqu'un utilisateur clique dans une zone de texte, c'est ici:
http://code.msdn.Microsoft.com/Enabling-Windows-8-Touch-7fb4e6de
C'est quelque chose sur lequel je travaille depuis de nombreux mois, je suis heureux de pouvoir enfin contribuer cet exemple à notre communauté. Veuillez me faire savoir s'il y a des questions, suggestions, problèmes, etc. dans l'exemple de volet Q&R
Cette solution est très simple: http://code.msdn.Microsoft.com/windowsapps/Enabling-Windows-8-Touch-7fb4e6de
Les étapes sont détaillées dans le lien ci-dessus, voici la version courte:
InkInputHelper.DisableWPFTabletSupport();
depuis MainWindow
constructeur ou similaireusing System.Windows.Interop;
Ajouter à MainWindow_Loaded ou similaire:
System.Windows.Automation.AutomationElement asForm =
System.Windows.Automation.AutomationElement.FromHandle(new WindowInteropHelper(this).Handle);
InputPanelConfigurationLib.InputPanelConfiguration inputPanelConfig = new InputPanelConfigurationLib.InputPanelConfiguration();
inputPanelConfig.EnableFocusTracking();
Pour convertir inputpanelconfiguration.idl en DLL
Sous Windows 8.1: c:\Program Files (x86)\Windows Kits\8.1\Include\um\inputpanelconfiguration.idl
Pour créer un DLL à partir de l'IDL, procédez comme suit:
midl /tbld {filename}
TLBIMP.exe InputpanelConfiguration.tlb /publickey:{pathToKey} /delaysign
Classe 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 });
}
}
}
}
}
}
Cela devrait fonctionner. Encore une fois, de bien meilleures informations et un échantillon téléchargeable dans le lien. Je copie uniquement les éléments de base à des fins d'archivage.
J'ai créé une bibliothèque pour automatiser tout ce qui concerne l'intégration TabTip dans l'application WPF.
Vous pouvez l'obtenir sur nuget , et après cela, tout ce dont vous avez besoin est une simple configuration dans la logique de démarrage de vos applications:
TabTipAutomation.BindTo<TextBox>();
Vous pouvez lier la logique d'automatisation TabTip à n'importe quel UIElement. Le clavier virtuel s'ouvrira lorsqu'un élément du type spécifié obtiendra le focus et se fermera lorsque l'élément perdra le focus. Non seulement cela, mais TabTipAutomation déplacera UIElement (ou Window) en vue, de sorte que TabTip ne bloquera pas l'élément focalisé.
Pour plus d'informations, reportez-vous au site du projet .
J'ai vu cela fait dans une session TechEd, vous devez d'abord désactiver la prise en charge de l'encrage (DisableWPFTabletSupport), puis vous pouvez créer une InputPanelConfiguration (AutomationElement.FromHandle (nouveau WindowsInteropHelper (this) .Handle)) et appeler 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
Lors du ciblage .Net 4.6.2
+ vous n'avez rien à faire:
https://riptutorial.com/wpf/example/23104/showing-touch-keyboard-on-windows-8-and-windows-1
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 });
}
}
}
}
}
utilisez cette classe pour déterminer s'il existe un clavier physique ou une méthode similaire qui pourrait mieux répondre à vos besoins.
j'ai utilisé cette classe pour ouvrir et fermer le clavier où je voulais.
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");
}
}
gardez à l'esprit ce qui suit: j'ai ajouté une copie de osk.exe ET tabtip.exe. l'ajout de cela dans mon programme a résolu un problème où tabtip ou osk ne fonctionnerait pas sur 32/64 bits.
osk est le clavier, tabtip en est la version ancrée. keyboardexecuter est un programme que j'ai créé qui est utilisé comme méthode de secours.
note * je ne peux actuellement pas tester cela sur un appareil à écran tactile. vous devez l'essayer par vous-même.
pour que tout fonctionne correctement, j'ai utilisé ce code dans ma fenêtre principale:
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;
//}
j'ai inclus les commentaires car cela pourrait être utile à quelqu'un s'il y a une erreur.
la configuration du panneau d'entrée:
[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
{
}
j'espère que cela pourrait aider les futurs visiteurs de cette question.