94 lines
3.3 KiB
PowerShell
94 lines
3.3 KiB
PowerShell
# A script to toggle the Touch Keyboard of Windows 11,
|
|
# compatible with both Windows PowerShell and PowerShell 7.
|
|
# Based on code by @torvin (https://stackoverflow.com/users/332528/torvin): https://stackoverflow.com/a/40921638
|
|
# Based on code by @Andrea S. (https://stackoverflow.com/users/5887913/andrea-s): https://stackoverflow.com/a/55513524
|
|
|
|
# Warning: Relies on undocumented behaviour of the Windows Shell
|
|
# and may break with any update.
|
|
# Last tested on Windows 11 Home 22000.978.
|
|
|
|
Add-Type -ReferencedAssemblies $(if ($PSVersionTable.PSEdition -eq "Desktop") {"System.Drawing.dll"} else {$null}) -Language CSharp -TypeDefinition @'
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using System.Runtime.InteropServices;
|
|
|
|
public class TouchKeyboardController
|
|
{
|
|
public static void ToggleTouchKeyboard()
|
|
{
|
|
try
|
|
{
|
|
UIHostNoLaunch uiHostNoLaunch = new UIHostNoLaunch();
|
|
((ITipInvocation)uiHostNoLaunch).Toggle(GetDesktopWindow());
|
|
Marshal.ReleaseComObject(uiHostNoLaunch);
|
|
}
|
|
catch (COMException exc)
|
|
{
|
|
if (exc.HResult == unchecked((int)0x80040154)) // REGDB_E_CLASSNOTREG
|
|
{
|
|
ProcessStartInfo processStartInfo = new ProcessStartInfo("TabTip.exe")
|
|
{
|
|
UseShellExecute = true
|
|
};
|
|
using (Process process = Process.Start(processStartInfo))
|
|
{
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
|
|
[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();
|
|
|
|
|
|
public static bool IsInputPaneOpen()
|
|
{
|
|
FrameworkInputPane frameworkInputPane = new FrameworkInputPane();
|
|
Rectangle rect;
|
|
((IFrameworkInputPane)frameworkInputPane).Location(out rect);
|
|
Marshal.ReleaseComObject(frameworkInputPane);
|
|
return !rect.IsEmpty;
|
|
}
|
|
|
|
[ComImport, Guid("d5120aa3-46ba-44c5-822d-ca8092c1fc72")]
|
|
public class FrameworkInputPane
|
|
{
|
|
}
|
|
|
|
[ComImport, Guid("5752238b-24f0-495a-82f1-2fd593056796")]
|
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
public interface IFrameworkInputPane
|
|
{
|
|
int Advise([MarshalAs(UnmanagedType.IUnknown)] object pWindow, [MarshalAs(UnmanagedType.IUnknown)] object pHandler, out int pdwCookie);
|
|
int AdviseWithHWND(IntPtr hwnd, [MarshalAs(UnmanagedType.IUnknown)] object pHandler, out int pdwCookie);
|
|
int Unadvise(int pdwCookie);
|
|
int Location(out Rectangle prcInputPaneScreenLocation);
|
|
}
|
|
}
|
|
'@
|
|
|
|
# Toggle the Touch Keyboard regardless of whether it is currently shown or not.
|
|
#[TouchKeyboardController]::ToggleTouchKeyboard()
|
|
|
|
# Alternatively, if you only want to show the Touch Keyboard
|
|
# and not hide it if it is already active:
|
|
if ([TouchKeyboardController]::IsInputPaneOpen()) {
|
|
[TouchKeyboardController]::ToggleTouchKeyboard()
|
|
} |