jukebox-software/keyboard-down.ps1

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()
}