Implement core diagnostic memory layer, execution helpers, and high-level facade slices
Implemented: - Core: UTF-16 ReadString boundary/alignment fix, target bitness and process id on MemoryBase - function interception: PatchManager, DetourManager, InstructionAnalyzer, MainThreadDispatcher - Execution: BackgroundTaskExecutor, InProcessInvoker - High-level: Magic facade, RemotePointer, async wrappers - Discovery/external code loading/Window groundwork (PEB/TEB, pattern scanning, raw allocations, DLL external code loading, window/input) Tests: 180 passing, 4 integration/interactive tests skipped.
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using WhiteMagic.Native;
|
||||
|
||||
namespace WhiteMagic.Input;
|
||||
|
||||
/// <summary>
|
||||
/// Mouse buttons supported by <see cref="InputSimulator.SendMouseClick"/>.
|
||||
/// </summary>
|
||||
public enum MouseButton
|
||||
{
|
||||
/// <summary>The left mouse button.</summary>
|
||||
Left,
|
||||
|
||||
/// <summary>The right mouse button.</summary>
|
||||
Right,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simulates keyboard and mouse input directed at a target window via window messages.
|
||||
/// </summary>
|
||||
public sealed class InputSimulator
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends a sequence of character messages to <paramref name="hWnd"/>.
|
||||
/// </summary>
|
||||
/// <returns><see langword="true"/> if every character was posted successfully.</returns>
|
||||
public bool SendKeys(IntPtr hWnd, string text)
|
||||
{
|
||||
if (text is null)
|
||||
throw new ArgumentNullException(nameof(text));
|
||||
|
||||
if (hWnd == IntPtr.Zero)
|
||||
return false;
|
||||
|
||||
foreach (char c in text)
|
||||
{
|
||||
if (!NativeMethods.PostMessageW(hWnd, NativeMethods.WmChar, (nuint)c, 0))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a mouse click at client-area coordinates <paramref name="x"/>,
|
||||
/// <paramref name="y"/> to <paramref name="hWnd"/>.
|
||||
/// </summary>
|
||||
/// <returns><see langword="true"/> if the click was posted successfully.</returns>
|
||||
public bool SendMouseClick(IntPtr hWnd, int x, int y, MouseButton button)
|
||||
{
|
||||
if (hWnd == IntPtr.Zero)
|
||||
return false;
|
||||
|
||||
nint lParam = MakeLong(x, y);
|
||||
|
||||
(uint down, uint up) = button switch
|
||||
{
|
||||
MouseButton.Left => (NativeMethods.WmLButtonDown, NativeMethods.WmLButtonUp),
|
||||
MouseButton.Right => (NativeMethods.WmRButtonDown, NativeMethods.WmRButtonUp),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(button)),
|
||||
};
|
||||
|
||||
if (!NativeMethods.PostMessageW(hWnd, down, 0, lParam))
|
||||
return false;
|
||||
|
||||
return NativeMethods.PostMessageW(hWnd, up, 0, lParam);
|
||||
}
|
||||
|
||||
private static nint MakeLong(int low, int high)
|
||||
{
|
||||
return (nint)((uint)low | ((uint)high << 16));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user