Created
March 4, 2015 23:37
-
-
Save JoeRobich/81ae679ee2d29efa3fa5 to your computer and use it in GitHub Desktop.
WPF AttachedProperty to show the on-screen keyboard when the control get focused by touch then hide it when the control loses focus. Code in this Gist is MIT Licensed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Window x:Class="TouchKeyboardTest.MainWindow" | |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |
xmlns:local="clr-namespace:TouchKeyboardTest" | |
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |
mc:Ignorable="d" | |
Title="Touch Keyboard Test" | |
Height="350" | |
Width="525"> | |
<Grid Margin="25"> | |
<StackPanel> | |
<TextBox Margin="0 5" local:TabletHelper.ShowInputPanelOnTouch="True" /> | |
<DatePicker Margin="0 5" local:TabletHelper.ShowInputPanelOnTouch="True" /> | |
<RichTextBox Margin="0 5" local:TabletHelper.ShowInputPanelOnTouch="True" /> | |
<Button Content="Clear Focus" HorizontalAlignment="Right" /> | |
</StackPanel> | |
</Grid> | |
</Window> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.IO; | |
using System.Runtime.InteropServices; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using System.Windows; | |
using System.Windows.Input; | |
namespace TouchKeyboardTest | |
{ | |
public class TabletHelper | |
{ | |
public static readonly DependencyProperty ShowInputPanelOnTouchProperty = | |
DependencyProperty.RegisterAttached("ShowInputPanelOnTouch", typeof(bool), typeof(TabletHelper), new FrameworkPropertyMetadata(false, ShowInputPanelOnTouchChanged)); | |
[DllImport("user32.dll")] | |
public static extern int FindWindow(string lpClassName, string lpWindowName); | |
[DllImport("user32.dll")] | |
public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam); | |
public const int WM_SYSCOMMAND = 0x0112; | |
public const int SC_CLOSE = 0xF060; | |
private const string TabTipPath = @"microsoft shared\ink\tabtip.exe"; | |
private const string OskPath = @"osk.exe"; | |
readonly static string _expandedTabTipPath; | |
readonly static string _expandedOskPath; | |
static CancellationTokenSource _cancelCloseInputPanel; | |
static TabletHelper() | |
{ | |
var programFilesPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles).Replace(" (x86)", ""); | |
_expandedTabTipPath = Path.Combine(programFilesPath, TabTipPath); | |
var system32Path = Environment.GetFolderPath(Environment.SpecialFolder.System); | |
_expandedOskPath = Path.Combine(system32Path, OskPath); | |
} | |
public static void ShowInputPanel() | |
{ | |
if (_cancelCloseInputPanel != null) | |
_cancelCloseInputPanel.Cancel(); | |
if (File.Exists(_expandedTabTipPath)) | |
Process.Start(_expandedTabTipPath); | |
else if (File.Exists(_expandedOskPath)) | |
Process.Start(_expandedOskPath); | |
} | |
public static void HideInputPanel() | |
{ | |
_cancelCloseInputPanel = new CancellationTokenSource(); | |
Task.Delay(100, _cancelCloseInputPanel.Token) | |
.ContinueWith(t => | |
{ | |
_cancelCloseInputPanel = null; | |
if (t.IsCanceled) | |
return; | |
CloseInputPanelWindow(); | |
}); | |
} | |
private static void CloseInputPanelWindow() | |
{ | |
int inputPanelHandle = FindWindow("OSKMainClass", null); | |
if (inputPanelHandle <= 0) | |
inputPanelHandle = FindWindow("IPTIP_Main_Window", null); | |
if (inputPanelHandle > 0) | |
SendMessage(inputPanelHandle, WM_SYSCOMMAND, SC_CLOSE, 0); | |
} | |
public static bool GetShowInputPanelOnTouch(DependencyObject obj) | |
{ | |
return (bool)obj.GetValue(ShowInputPanelOnTouchProperty); | |
} | |
public static void SetShowInputPanelOnTouch(DependencyObject obj, bool value) | |
{ | |
obj.SetValue(ShowInputPanelOnTouchProperty, value); | |
} | |
private static void ShowInputPanelOnTouchChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) | |
{ | |
var uiElement = (UIElement)obj; | |
uiElement.GotKeyboardFocus -= UIElement_GotKeyboardFocus; | |
uiElement.TouchDown -= UIElement_TouchDown; | |
if ((bool)e.NewValue) | |
{ | |
uiElement.GotKeyboardFocus += UIElement_GotKeyboardFocus; | |
uiElement.TouchDown += UIElement_TouchDown; | |
} | |
} | |
private static void UIElement_TouchDown(object sender, TouchEventArgs e) | |
{ | |
var uiElement = (UIElement)sender; | |
uiElement.TouchLeave -= UIElement_TouchLeave; | |
uiElement.TouchUp -= UIElement_TouchUp; | |
if (!uiElement.IsFocused) | |
return; | |
uiElement.TouchLeave += UIElement_TouchLeave; | |
uiElement.TouchUp += UIElement_TouchUp; | |
} | |
private static void UIElement_TouchLeave(object sender, TouchEventArgs e) | |
{ | |
var uiElement = (UIElement)sender; | |
uiElement.TouchLeave -= UIElement_TouchLeave; | |
uiElement.TouchUp -= UIElement_TouchUp; | |
} | |
private static void UIElement_TouchUp(object sender, TouchEventArgs e) | |
{ | |
var uiElement = (UIElement)sender; | |
uiElement.TouchLeave -= UIElement_TouchLeave; | |
uiElement.TouchUp -= UIElement_TouchUp; | |
ShowInputPanel(); | |
uiElement.LostKeyboardFocus += UIElement_LostKeyboardFocus; | |
} | |
private static void UIElement_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) | |
{ | |
var uiElement = (UIElement)sender; | |
uiElement.LostKeyboardFocus -= UIElement_LostKeyboardFocus; | |
if (!uiElement.AreAnyTouchesOver) | |
return; | |
ShowInputPanel(); | |
uiElement.LostKeyboardFocus += UIElement_LostKeyboardFocus; | |
} | |
private static void UIElement_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) | |
{ | |
var uiElement = (UIElement)sender; | |
uiElement.LostKeyboardFocus -= UIElement_LostKeyboardFocus; | |
HideInputPanel(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment