In Windows 8 und Windows 10 vor dem Anniversary-Update war es möglich, die Touch-Tastatur beim Start anzuzeigen
C:\Program Files\Common Files\Microsoft shared\ink\TabTip.exe
Es funktioniert nicht mehr in Windows 10 Anniversary Update; Der TabTip.exe
-Prozess wird ausgeführt, aber die Tastatur wird nicht angezeigt.
Gibt es eine Möglichkeit, es programmgesteuert anzuzeigen?
UPDATE
Ich habe eine Problemumgehung gefunden - einen falschen Mausklick auf das Touch-Tastatur-Symbol in der Taskleiste. Hier ist Code in Delphi
// Find tray icon window
function FindTrayButtonWindow: THandle;
var
ShellTrayWnd: THandle;
TrayNotifyWnd: THandle;
begin
Result := 0;
ShellTrayWnd := FindWindow('Shell_TrayWnd', nil);
if ShellTrayWnd > 0 then
begin
TrayNotifyWnd := FindWindowEx(ShellTrayWnd, 0, 'TrayNotifyWnd', nil);
if TrayNotifyWnd > 0 then
begin
Result := FindWindowEx(TrayNotifyWnd, 0, 'TIPBand', nil);
end;
end;
end;
// Post mouse click messages to it
TrayButtonWindow := FindTrayButtonWindow;
if TrayButtonWindow > 0 then
begin
PostMessage(TrayButtonWindow, WM_LBUTTONDOWN, MK_LBUTTON, $00010001);
PostMessage(TrayButtonWindow, WM_LBUTTONUP, 0, $00010001);
end;
UPDATE 2
Eine andere Sache, die ich gefunden habe, ist, dass das Setzen dieses Registrierungsschlüssels die alte Funktionalität wiederherstellt, wenn TabTip.exe die Berührungs-Tastatur zeigt
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\TabletTip\1.7\EnableDesktopModeAutoInvoke=1
OK, ich habe das, was Explorer tut, rückgängig gemacht, wenn der Benutzer diese Taste in der Taskleiste drückt.
Im Grunde erstellt es eine Instanz einer undokumentierten Schnittstelle ITipInvocation
und ruft die Toggle(HWND)
-Methode auf, wobei das Desktopfenster als Argument übergeben wird. Wie der Name vermuten lässt, zeigt oder versteckt die Methode die Tastatur je nach aktuellem Status.
Bitte beachten Sie dass der Explorer bei jedem Klicken der Schaltfläche eine Instanz von ITipInvocation
erstellt. Ich glaube also, dass die Instanz nicht zwischengespeichert werden sollte. Ich habe auch bemerkt, dass der Explorer niemals Release()
für die erhaltene Instanz aufruft. Ich bin nicht so vertraut mit COM, aber das sieht nach einem Fehler aus.
Ich habe dies in Windows 8.1, Windows 10 und Windows 10 Anniversary Edition getestet und funktioniert einwandfrei. Hier ist ein minimales Beispiel in C, dem offensichtlich einige Fehlerprüfungen fehlen.
#include <initguid.h>
#include <Objbase.h>
#pragma hdrstop
// 4ce576fa-83dc-4F88-951c-9d0782b4e376
DEFINE_GUID(CLSID_UIHostNoLaunch,
0x4CE576FA, 0x83DC, 0x4f88, 0x95, 0x1C, 0x9D, 0x07, 0x82, 0xB4, 0xE3, 0x76);
// 37c994e7_432b_4834_a2f7_dce1f13b834b
DEFINE_GUID(IID_ITipInvocation,
0x37c994e7, 0x432b, 0x4834, 0xa2, 0xf7, 0xdc, 0xe1, 0xf1, 0x3b, 0x83, 0x4b);
struct ITipInvocation : IUnknown
{
virtual HRESULT STDMETHODCALLTYPE Toggle(HWND wnd) = 0;
};
int WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HRESULT hr;
hr = CoInitialize(0);
ITipInvocation* tip;
hr = CoCreateInstance(CLSID_UIHostNoLaunch, 0, CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER, IID_ITipInvocation, (void**)&tip);
tip->Toggle(GetDesktopWindow());
tip->Release();
return 0;
}
Hier ist auch die C # -Version:
class Program
{
static void Main(string[] args)
{
var uiHostNoLaunch = new UIHostNoLaunch();
var tipInvocation = (ITipInvocation)uiHostNoLaunch;
tipInvocation.Toggle(GetDesktopWindow());
Marshal.ReleaseComObject(uiHostNoLaunch);
}
[ComImport, Guid("4ce576fa-83dc-4F88-951c-9d0782b4e376")]
class UIHostNoLaunch
{
}
[ComImport, Guid("37c994e7-432b-4834-a2f7-dce1f13b834b")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface ITipInvocation
{
void Toggle(IntPtr hwnd);
}
[DllImport("user32.dll", SetLastError = false)]
static extern IntPtr GetDesktopWindow();
}
Update: per @EugeneK-Kommentare. Ich glaube, dass tabtip.exe
der COM-Server für die betreffende COM-Komponente ist. Wenn Ihr Code REGDB_E_CLASSNOTREG
erhält, sollte er tabtip.exe
wahrscheinlich ausführen und es erneut versuchen.
Die einzige Lösung, die ich gefunden habe, ist das Senden von PostMessage, wie Sie es in Antwort 1 erwähnt haben. Hier ist die C # -Version davon, falls jemand es braucht.
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr FindWindow(string sClassName, string sAppName);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);
[DllImport("User32.Dll", EntryPoint = "PostMessageA")]
static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
var trayWnd = FindWindow("Shell_TrayWnd", null);
var nullIntPtr = new IntPtr(0);
if (trayWnd != nullIntPtr)
{
var trayNotifyWnd = FindWindowEx(trayWnd, nullIntPtr, "TrayNotifyWnd", null);
if (trayNotifyWnd != nullIntPtr)
{
var tIPBandWnd = FindWindowEx(trayNotifyWnd, nullIntPtr, "TIPBand", null);
if (tIPBandWnd != nullIntPtr)
{
PostMessage(tIPBandWnd, (UInt32)WMessages.WM_LBUTTONDOWN, 1, 65537);
PostMessage(tIPBandWnd, (UInt32)WMessages.WM_LBUTTONUP, 1, 65537);
}
}
}
public enum WMessages : int
{
WM_LBUTTONDOWN = 0x201,
WM_LBUTTONUP = 0x202,
WM_KEYDOWN = 0x100,
WM_KEYUP = 0x101,
WH_KEYBOARD_LL = 13,
WH_MOUSE_LL = 14,
}
Ich hatte auch das gleiche Problem. Es hat mir viel Zeit und Kopfschmerzen gekostet, aber dank Alexei und Torvin konnte ich endlich Win 10 1709 zum Laufen bringen. Sichtprüfung war die Schwierigkeit. Vielleicht könnte das OSKlib-Nuget aktualisiert werden. Lassen Sie mich die vollständige Zusammenfassung zusammenfassen (Natürlich hat mein Code jetzt einige unnötige Zeilen):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.ComponentModel;
using Osklib.Interop;
using System.Runtime.InteropServices;
using System.Threading;
namespace OSK
{
public static class OnScreenKeyboard
{
static OnScreenKeyboard()
{
var version = Environment.OSVersion.Version;
switch (version.Major)
{
case 6:
switch (version.Minor)
{
case 2:
// Windows 10 (ok)
break;
}
break;
default:
break;
}
}
private static void StartTabTip()
{
var p = Process.Start(@"C:\Program Files\Common Files\Microsoft Shared\ink\TabTip.exe");
int handle = 0;
while ((handle = NativeMethods.FindWindow("IPTIP_Main_Window", "")) <= 0)
{
Thread.Sleep(100);
}
}
public static void ToggleVisibility()
{
var type = Type.GetTypeFromCLSID(Guid.Parse("4ce576fa-83dc-4F88-951c-9d0782b4e376"));
var instance = (ITipInvocation)Activator.CreateInstance(type);
instance.Toggle(NativeMethods.GetDesktopWindow());
Marshal.ReleaseComObject(instance);
}
public static void Show()
{
int handle = NativeMethods.FindWindow("IPTIP_Main_Window", "");
if (handle <= 0) // nothing found
{
StartTabTip();
Thread.Sleep(100);
}
// on some devices starting TabTip don't show keyboard, on some does ¯\_(ツ)_/¯
if (!IsOpen())
{
ToggleVisibility();
}
}
public static void Hide()
{
if (IsOpen())
{
ToggleVisibility();
}
}
public static bool Close()
{
// find it
int handle = NativeMethods.FindWindow("IPTIP_Main_Window", "");
bool active = handle > 0;
if (active)
{
// don't check style - just close
NativeMethods.SendMessage(handle, NativeMethods.WM_SYSCOMMAND, NativeMethods.SC_CLOSE, 0);
}
return active;
}
public static bool IsOpen()
{
return GetIsOpen1709() ?? GetIsOpenLegacy();
}
[DllImport("user32.dll", SetLastError = false)]
private static extern IntPtr FindWindowEx(IntPtr parent, IntPtr after, string className, string title = null);
[DllImport("user32.dll", SetLastError = false)]
private static extern uint GetWindowLong(IntPtr wnd, int index);
private static bool? GetIsOpen1709()
{
// if there is a top-level window - the keyboard is closed
var wnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, WindowClass1709, WindowCaption1709);
if (wnd != IntPtr.Zero)
return false;
var parent = IntPtr.Zero;
for (;;)
{
parent = FindWindowEx(IntPtr.Zero, parent, WindowParentClass1709);
if (parent == IntPtr.Zero)
return null; // no more windows, keyboard state is unknown
// if it's a child of a WindowParentClass1709 window - the keyboard is open
wnd = FindWindowEx(parent, IntPtr.Zero, WindowClass1709, WindowCaption1709);
if (wnd != IntPtr.Zero)
return true;
}
}
private static bool GetIsOpenLegacy()
{
var wnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, WindowClass);
if (wnd == IntPtr.Zero)
return false;
var style = GetWindowStyle(wnd);
return style.HasFlag(WindowStyle.Visible)
&& !style.HasFlag(WindowStyle.Disabled);
}
private const string WindowClass = "IPTip_Main_Window";
private const string WindowParentClass1709 = "ApplicationFrameWindow";
private const string WindowClass1709 = "Windows.UI.Core.CoreWindow";
private const string WindowCaption1709 = "Microsoft Text Input Application";
private enum WindowStyle : uint
{
Disabled = 0x08000000,
Visible = 0x10000000,
}
private static WindowStyle GetWindowStyle(IntPtr wnd)
{
return (WindowStyle)GetWindowLong(wnd, -16);
}
}
[ComImport]
[Guid("37c994e7-432b-4834-a2f7-dce1f13b834b")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface ITipInvocation
{
void Toggle(IntPtr hwnd);
}
internal static class NativeMethods
{
[DllImport("user32.dll", EntryPoint = "FindWindow")]
internal static extern int FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", EntryPoint = "SendMessage")]
internal static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
[DllImport("user32.dll", EntryPoint = "GetDesktopWindow", SetLastError = false)]
internal static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
internal static extern int GetWindowLong(int hWnd, int nIndex);
internal const int GWL_STYLE = -16;
internal const int GWL_EXSTYLE = -20;
internal const int WM_SYSCOMMAND = 0x0112;
internal const int SC_CLOSE = 0xF060;
internal const int WS_DISABLED = 0x08000000;
internal const int WS_VISIBLE = 0x10000000;
}
}
Ich entdecke 4 Situationen, wenn ich versuche, die Touch-Tastatur unter Windows 10 Anniversary Update zu öffnen
1 - nichts zu tun
2 + 3 - Aktivierung über COM
4 - interessantestes Szenario. Bei einigen Geräten wird beim Starten des TabTip-Prozesses die Touch-Tastatur geöffnet, bei einigen nicht. Wir müssen also den TabTip-Prozess starten, auf das erscheinende Fenster "IPTIP_Main_Window" warten, es auf Sichtbarkeit prüfen und falls nötig über COM aktivieren.
Ich mache eine kleine Bibliothek für mein Projekt, Sie können es verwenden - osklib
Es ist immer noch ein Rätsel, wie die Touch-Tastatur durch das Windows 10 Anniversary Update sichtbar gemacht wird. Ich habe genau das gleiche Problem und hier sind die neuesten Infos, die ich gefunden habe:
Windows 10 1607 arbeitet in zwei Modi: Desktop und Tablet. Im Desktop-Modus kann TabTip.exe aufgerufen werden, wird jedoch nicht angezeigt. Im Tablet-Modus funktioniert alles einwandfrei: TabTip.exe zeigt sich beim Aufruf. Eine 100% ige Problemumgehung besteht darin, Ihren Computer in den Tablet-Modus zu versetzen. Wer möchte jedoch, dass sein Desktop/Laptop im Tablet-Modus arbeitet? Nicht ich sowieso!
Sie können die Taste "EnableDesktopModeAutoInvoke
" (HKCU, DWORD auf 1) verwenden. Auf einigen Computern, auf denen 1607 ausgeführt wird, hat es im Desktop-Modus hervorragend funktioniert. Aus unbekannten Gründen funktioniert es jedoch nicht auf meinem HP Touchpad.
Bitte beachten Sie, dass dieser Registrierungswert die Option "Touch-Tastatur im Desktop-Modus anzeigen, wenn keine Tastatur angeschlossen ist" in den Windows-Parametern ist> touch
Bis jetzt auf 4 verschiedenen Computern getestet und ich kann nicht, dass irgendetwas bei allen funktioniert ...
Die Implementierung des IValueProvider/ITextProviders in Ihrem Steuerelement ist ein korrekter Weg, um dies zu erreichen, wie hier beschrieben: https://stackoverflow.com/a/43886052/1184950
Das Problem scheint bei der Einstellung des Windows-Betriebssystems zu liegen. Ich habe mit der App, die ich entwickelt habe, das gleiche Problem. Unter Windows 8 und 10 (vor dem Update) funktionierte der Code mit der Tastatur einwandfrei, aber nach dem Update funktionierte dies nicht. Nachdem ich diesen Artikel gelesen habe, habe ich folgendes gemacht:
Drücken Sie Win + I, um die App Einstellungen zu öffnen
Klicken Sie auf Geräte> Eingabe
Deaktiviert "Zeigt die Touch-Tastatur automatisch in Anwendungen mit Fenstern an, wenn an Ihrem Gerät keine Tastatur angeschlossen ist".
Gleich danach erscheint die Tastatur auch in Windows 10.
Der folgende Code funktioniert immer, da er die neueste MS-API verwendet
Ich habe es in eine DLL (Erforderlich für ein Delphi-Projekt), aber es ist ein einfaches C.
Auch nützlich, um die Tastaturgröße zu erhalten und das Layout der Anwendung anzupassen
//*******************************************************************
//
// RETURNS KEYBOARD RECTANGLE OR EMPTY ONE IF KEYBOARD IS NOT VISIBLE
//
//*******************************************************************
RECT __stdcall GetKeyboardRect()
{
IFrameworkInputPane *inputPane = NULL;
RECT prcInputPaneScreenLocation = { 0,0,0,0 };
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_FrameworkInputPane, NULL, CLSCTX_INPROC_SERVER, IID_IFrameworkInputPane, (LPVOID*)&inputPane);
if (SUCCEEDED(hr))
{
hr=inputPane->Location(&prcInputPaneScreenLocation);
if (!SUCCEEDED(hr))
{
}
inputPane->Release();
}
}
CoUninitialize();
return prcInputPaneScreenLocation;
}
Verwenden Sie diese Methode:
Erstellen Sie die Datei osk.bat und speichern Sie sie in Ihrem Programmordner. C:\My Software\osk.bat
Tippe in diese osk.bat den folgenden cmd ein:
"C:\Program Files\Common Files\Microsoft Shared\Ink\Tabtip.exe"
Verwenden Sie Windows Script, um diese Bat-Datei auszuführen
oWSH = CREATEOBJECT("wscript.Shell")
oWSH.Run("osk.bat", 0, .T.)