Currently with Windows 8.1, not much functionality seems to be programmatically exposed.
The code below will cause the tabtip.exe to read the registry because the original process is killed.
It is not completely reliable, but is a way to for it to respond to some registry values.
The part about docking is optional, it forces it to dock each time via the registry change.
The process.Kill(); should be in a try/catch since it occasionally doesn't have permission and can throw an exception.
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string sClassName, string sAppName);
[DllImport("user32.dll")]
public static extern IntPtr PostMessage(int hWnd, uint msg, int wParam, int lParam);
private static void KillTabTip()
{
// Kill the previous process so the registry change will take effect.
var processlist = Process.GetProcesses();
foreach (var process in processlist.Where(process => process.ProcessName == "TabTip"))
{
process.Kill();
break;
}
}
public void ShowTouchKeyboard(bool isVisible, bool numericKeyboard)
{
if (isVisible)
{
const string keyName = "HKEY_CURRENT_USER\\Software\\Microsoft\\TabletTip\\1.7";
var regValue = (int) Registry.GetValue(keyName, "KeyboardLayoutPreference", 0);
var regShowNumericKeyboard = regValue == 1;
// Note: Remove this if do not want to control docked state.
var dockedRegValue = (int) Registry.GetValue(keyName, "EdgeTargetDockedState", 1);
var restoreDockedState = dockedRegValue == 0;
if (numericKeyboard && regShowNumericKeyboard == false)
{
// Set the registry so it will show the number pad via the thumb keyboard.
Registry.SetValue(keyName, "KeyboardLayoutPreference", 1, RegistryValueKind.DWord);
// Kill the previous process so the registry change will take effect.
KillTabTip();
}
else if (numericKeyboard == false && regShowNumericKeyboard)
{
// Set the registry so it will NOT show the number pad via the thumb keyboard.
Registry.SetValue(keyName, "KeyboardLayoutPreference", 0, RegistryValueKind.DWord);
// Kill the previous process so the registry change will take effect.
KillTabTip();
}
// Note: Remove this if do not want to control docked state.
if (restoreDockedState)
{
// Set the registry so it will show as docked at the bottom rather than floating.
Registry.SetValue(keyName, "EdgeTargetDockedState", 1, RegistryValueKind.DWord);
// Kill the previous process so the registry change will take effect.
KillTabTip();
}
Process.Start("c:\\Program Files\\Common Files\\Microsoft Shared\\ink\\TabTip.exe");
}
else
{
var win8Version = new Version(6, 2, 9200, 0);
if (Environment.OSVersion.Version >= win8Version)
{
const uint wmSyscommand = 274;
const uint scClose = 61536;
var keyboardWnd = FindWindow("IPTip_Main_Window", null);
PostMessage(keyboardWnd.ToInt32(), wmSyscommand, (int)scClose, 0);
}
}
}
You can call the above method from a custom version of a TextBox where OnTouchDown is overridden and an additional DependencyProperty is created to indicate if the field uses the NumericKeyboard:
#region NumericKeyboard
public static readonly DependencyProperty NumericKeyboardProperty = DependencyProperty.Register("NumericKeyboard", typeof(bool), typeof(CustomTextBox), new FrameworkPropertyMetadata(false));
/// <summary> Returns/set the "NumericKeyboard" state of the CustomTextBox. </summary>
public bool NumericKeyboard
{
get { return (bool)GetValue(NumericKeyboardProperty); }
set { SetValue(NumericKeyboardProperty, value); }
}
#endregion
protected override void OnTouchDown(TouchEventArgs e)
{
base.OnTouchDown(e);
Focus();
if (IsReadOnly == false)
ShowTouchKeyboard(true, NumericKeyboard);
}
Currently, I have not had any success using similar techniques to position the TabTip window around the screen when in a floating (non-docked) state.