Temporarily switch to English layout for injection
This commit is contained in:
@@ -7,10 +7,13 @@ public sealed class KeyboardInjectionService : IKeyboardInjectionService
|
|||||||
private const uint InputKeyboard = 1;
|
private const uint InputKeyboard = 1;
|
||||||
private const uint KeyEventFKeyUp = 0x0002;
|
private const uint KeyEventFKeyUp = 0x0002;
|
||||||
private const uint KeyEventFUnicode = 0x0004;
|
private const uint KeyEventFUnicode = 0x0004;
|
||||||
|
private const uint KlfActivate = 0x00000001;
|
||||||
|
private const uint WmInputLangChangeRequest = 0x0050;
|
||||||
private const ushort VirtualKeyA = 0x41;
|
private const ushort VirtualKeyA = 0x41;
|
||||||
private const ushort VirtualKeyBack = 0x08;
|
private const ushort VirtualKeyBack = 0x08;
|
||||||
private const ushort VirtualKeyControl = 0x11;
|
private const ushort VirtualKeyControl = 0x11;
|
||||||
private const ushort VirtualKeyReturn = 0x0D;
|
private const ushort VirtualKeyReturn = 0x0D;
|
||||||
|
private static readonly IntPtr EnglishKeyboardLayout = LoadKeyboardLayout("00000409", KlfActivate);
|
||||||
|
|
||||||
public void InsertText(string text)
|
public void InsertText(string text)
|
||||||
{
|
{
|
||||||
@@ -20,6 +23,7 @@ public sealed class KeyboardInjectionService : IKeyboardInjectionService
|
|||||||
}
|
}
|
||||||
|
|
||||||
AppLogger.Info($"Injecting text length: {text.Length}");
|
AppLogger.Info($"Injecting text length: {text.Length}");
|
||||||
|
using var keyboardLayoutScope = KeyboardLayoutScope.SwitchForegroundWindowToEnglish();
|
||||||
foreach (var character in text)
|
foreach (var character in text)
|
||||||
{
|
{
|
||||||
AppLogger.Info($"Injecting char U+{(int)character:X4}: {character}");
|
AppLogger.Info($"Injecting char U+{(int)character:X4}: {character}");
|
||||||
@@ -121,6 +125,66 @@ public sealed class KeyboardInjectionService : IKeyboardInjectionService
|
|||||||
[DllImport("user32.dll", SetLastError = true)]
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
private static extern uint SendInput(uint numberOfInputs, INPUT[] inputs, int sizeOfInputStructure);
|
private static extern uint SendInput(uint numberOfInputs, INPUT[] inputs, int sizeOfInputStructure);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern IntPtr GetForegroundWindow();
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern uint GetWindowThreadProcessId(IntPtr windowHandle, out uint processId);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern IntPtr GetKeyboardLayout(uint threadId);
|
||||||
|
|
||||||
|
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||||
|
private static extern IntPtr LoadKeyboardLayout(string keyboardLayoutId, uint flags);
|
||||||
|
|
||||||
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
|
private static extern bool PostMessage(IntPtr windowHandle, uint message, IntPtr wParam, IntPtr lParam);
|
||||||
|
|
||||||
|
private sealed class KeyboardLayoutScope : IDisposable
|
||||||
|
{
|
||||||
|
private readonly IntPtr foregroundWindow;
|
||||||
|
private readonly IntPtr originalKeyboardLayout;
|
||||||
|
|
||||||
|
private KeyboardLayoutScope(IntPtr foregroundWindow, IntPtr originalKeyboardLayout)
|
||||||
|
{
|
||||||
|
this.foregroundWindow = foregroundWindow;
|
||||||
|
this.originalKeyboardLayout = originalKeyboardLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KeyboardLayoutScope SwitchForegroundWindowToEnglish()
|
||||||
|
{
|
||||||
|
var foregroundWindow = GetForegroundWindow();
|
||||||
|
if (foregroundWindow == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
AppLogger.Error("Cannot switch keyboard layout because no foreground window was found.");
|
||||||
|
return new KeyboardLayoutScope(IntPtr.Zero, IntPtr.Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
var threadId = GetWindowThreadProcessId(foregroundWindow, out _);
|
||||||
|
var originalKeyboardLayout = GetKeyboardLayout(threadId);
|
||||||
|
AppLogger.Info($"Switching foreground keyboard layout from 0x{originalKeyboardLayout.ToInt64():X} to 0x{EnglishKeyboardLayout.ToInt64():X}.");
|
||||||
|
|
||||||
|
if (EnglishKeyboardLayout != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
PostMessage(foregroundWindow, WmInputLangChangeRequest, IntPtr.Zero, EnglishKeyboardLayout);
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new KeyboardLayoutScope(foregroundWindow, originalKeyboardLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (foregroundWindow == IntPtr.Zero || originalKeyboardLayout == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AppLogger.Info($"Restoring foreground keyboard layout to 0x{originalKeyboardLayout.ToInt64():X}.");
|
||||||
|
PostMessage(foregroundWindow, WmInputLangChangeRequest, IntPtr.Zero, originalKeyboardLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
private struct INPUT
|
private struct INPUT
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user