In Windows 10 Tablet mode, the TabTip keyboard is shown whenever any textbox (regardless of type, be it from a Java application, a Metro app, or a WPF app) is focused.
It seems impossible to implement this as a service using only simple Window hooks since Metro apps do not return a Window
element, which led to the hypothesis that there must be a system call happening whenever any textfield is focused, when in Tablet mode.
I've been researching for days, but to no avail. The most useful thing I have seen would be this thread where the responder reverse-engineered the behavior when tapping the Keyboard key in the taskbar in Tablet mode.
I also tried this block of code, but this seems to only catch a small portion of the text fields:
public void DetectKeyboard()
{
AttemptKeyboardDetection:
try
{
AttachThreadInput(GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero), GetCurrentThreadId(), true);
IntPtr focus = GetFocus();
AttachThreadInput(GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero), GetCurrentThreadId(), false);
if (GetClassName(focus, this.StringBuilder, this.StringBuilder.Capacity))
{
ActiveProcessFocus = this.StringBuilder.ToString();
Debug.WriteLine("Active Process: " + ActiveProcessFocus);
if ((PreviousProcessFocus != ActiveProcessFocus) && !ActiveProcessFocus.Contains("KeyboardOpener"))
{
Debug.WriteLine("Checking if editing...");
if ((((ActiveProcessFocus == "Edit") || (ActiveProcessFocus == "SearchPane")) || (ActiveProcessFocus.Contains("RichEdit") || ActiveProcessFocus.Contains("SearchEdit"))) || ((ActiveProcessFocus.Contains("TextfieldEdit") || ActiveProcessFocus.Contains("Afx:00400000")) || (((ActiveProcessFocus == "_WwG") || (ActiveProcessFocus == "Scintilla")) || (ActiveProcessFocus == "SPEAD0C4"))))
{
Debug.WriteLine("Editing! Opening keyboard...");
try
{
ProcessStartInfo startInfo = new ProcessStartInfo(@"C:\Program Files\Common Files\Microsoft Shared\ink\TabTip.exe");
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(startInfo);
}
catch
{
}
}
else
{
try
{
SendMessage(FindWindow("IPTip_Main_Window", null), 0x112, (IntPtr) 0xf060, IntPtr.Zero);
foreach (Process process in Process.GetProcessesByName("osk"))
{
process.Kill();
}
}
catch
{
}
}
PreviousProcessFocus = ActiveProcessFocus;
}
}
Thread.Sleep(250);
goto AttemptKeyboardDetection;
}
catch
{
goto AttemptKeyboardDetection;
}
}
[DllImport("user32.dll")]
private static extern IntPtr AttachThreadInput(IntPtr AttachId, IntPtr AttachToId, bool AttachStatus);
[DllImport("user32.dll")]
private static extern bool GetClassName(IntPtr hWnd, StringBuilder ClassName, int ClassMax);
[DllImport("kernel32.dll")]
private static extern IntPtr GetCurrentThreadId();
[DllImport("user32.dll")]
private static extern IntPtr GetFocus();
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, IntPtr ThreadId);
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
since not all text field elements contain "Edit", etc. in their element names.
Since I'm sure I've exhausted what I can find with my limited knowledge in Windows programming and through research, does anyone know of a system call that can be listened to that is similar to the one called when in Tablet mode? Or is this really impossible without diving in to assembly or even making viruses?