Skip to content

Commit

Permalink
Merge pull request #49 from RyanLua/refactor-interop
Browse files Browse the repository at this point in the history
Refactor interop to use CsWin32/LibraryImport
  • Loading branch information
RyanLua authored Jan 9, 2025
2 parents 65eca9a + 89ed34f commit 2f4b123
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 306 deletions.
5 changes: 2 additions & 3 deletions FluentAutoClicker/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace FluentAutoClicker;
/// </summary>
public partial class App : Application
{
public static Window Window { get; private set; } = null!;
public static readonly MainWindow MainWindow = new();

/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
Expand All @@ -44,7 +44,6 @@ public App()
/// <param name="args">Details about the launch request and process.</param>
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
Window = new MainWindow();
Window.Activate();
MainWindow.Activate();
}
}
5 changes: 5 additions & 0 deletions FluentAutoClicker/FluentAutoClicker.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<PublishProfile>win-$(Platform).pubxml</PublishProfile>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<UseWinUI>true</UseWinUI>
<EnableMsixTooling>true</EnableMsixTooling>
<DefineConstants>DISABLE_XAML_GENERATED_MAIN</DefineConstants>
Expand All @@ -37,6 +38,10 @@
<ProjectCapability Include="Msix" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.106">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.1742" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.6.241114003" />
<PackageReference Include="WinUIEx" Version="2.5.0" />
Expand Down
130 changes: 51 additions & 79 deletions FluentAutoClicker/Helpers/AutoClicker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
// along with Fluent Auto Clicker. If not, see <https://www.gnu.org/licenses/>.

using System.Runtime.InteropServices;
using Windows.Win32;
using Windows.Win32.UI.Input.KeyboardAndMouse;

namespace FluentAutoClicker.Helpers;

Expand All @@ -24,9 +26,6 @@ namespace FluentAutoClicker.Helpers;
/// </summary>
public static class AutoClicker
{
[DllImport("user32.dll", SetLastError = true)]
private static extern uint SendInput(uint nInputs, Input[] pInputs, int cbSize);

private static Thread? _autoClickerThread;
private static bool _isAutoClickerRunning;

Expand All @@ -37,114 +36,87 @@ public static class AutoClicker
/// <param name="clickAmount">The number of clicks before stopping the auto clicker thread.</param>
/// <param name="mouseButtonType">The mouse button used to click.</param>
/// <param name="clickDelayOffset">The amount of time in milliseconds to add randomly to the millisecond delay between clicks.</param>
public static void StartAutoClicker(int millisecondsDelay, int clickAmount, int mouseButtonType, int clickDelayOffset)
public static void Start(int millisecondsDelay = 100, int clickAmount = 0,
int mouseButtonType = 0, int clickDelayOffset = 0)
{
// TODO: Evaluate whether a thread is necessary for this.
// TODO: Move the parameters to another function to be able to change parameters while the thread is running.
_isAutoClickerRunning = true;
_autoClickerThread = new Thread(() => AutoClickerThread(millisecondsDelay, clickAmount, mouseButtonType, clickDelayOffset));
_autoClickerThread = new Thread(() =>
AutoClickerThread(millisecondsDelay, clickAmount, mouseButtonType, clickDelayOffset));
_autoClickerThread.Start();
}

/// <summary>
/// Stops the auto clicker thread.
/// </summary>
public static void StopAutoClicker()
public static void Stop()
{
_isAutoClickerRunning = false;
// HACK: Incorrectly stops the thread, but it works for now.
_autoClickerThread?.Join();
}

private static async void AutoClickerThread(int clickInterval, int repeatAmount, int mouseButton, int clickOffset)
private static async void AutoClickerThread(int clickInterval, int repeatAmount, int mouseButton,
int clickOffset)
{
int clickCount = 0;
Random random = new();

while (_isAutoClickerRunning)
{
// Stop if we click more than repeat amount
if (clickCount >= repeatAmount && repeatAmount != 0)
{
StopAutoClicker();
Stop();
break;
}

// TODO: Move this to a enum instead of a number
switch (mouseButton)
{
case 0:
MouseEvent(0, 0, (uint)MouseEventF.LeftDown, 0, 0, IntPtr.Zero);
MouseEvent(0, 0, (uint)MouseEventF.LeftUp, 0, 0, IntPtr.Zero);
break;
case 1:
MouseEvent(0, 0, (uint)MouseEventF.MiddleDown, 0, 0, IntPtr.Zero);
MouseEvent(0, 0, (uint)MouseEventF.MiddleUp, 0, 0, IntPtr.Zero);
break;
case 2:
MouseEvent(0, 0, (uint)MouseEventF.RightDown, 0, 0, IntPtr.Zero);
MouseEvent(0, 0, (uint)MouseEventF.RightUp, 0, 0, IntPtr.Zero);
break;
}

if (repeatAmount > 0)
{
clickCount++;
}
// Click mouse and increment click count
ClickMouse(mouseButton);
clickCount++;

int randomClickOffset = random.Next(0, clickOffset);
// Delay before next click
int randomClickOffset = new Random().Next(0, clickOffset);
await Task.Delay(clickInterval + randomClickOffset);
}
}

private static void MouseEvent(int dx, int dy, uint dwFlags, uint dwData, uint time, nint dwExtraInfo)
/// <summary>
/// Clicks the mouse button.
/// </summary>
/// <param name="button">The mouse button to click.</param>
private static void ClickMouse(int button)
{
Input[] inputs = new Input[2];
inputs[0] = MouseInput(dx, dy, dwData, dwFlags, time, dwExtraInfo);
inputs[1] = MouseInput(dx, dy, dwData, dwFlags, time, dwExtraInfo);
_ = SendInput((uint)inputs.Length, inputs, Marshal.SizeOf<Input>());
if (button == 0) // Left mouse button
{
SendMouseInput(MOUSE_EVENT_FLAGS.MOUSEEVENTF_LEFTDOWN);
SendMouseInput(MOUSE_EVENT_FLAGS.MOUSEEVENTF_LEFTUP);
}
else if (button == 1) // Middle mouse button
{
SendMouseInput(MOUSE_EVENT_FLAGS.MOUSEEVENTF_MIDDLEDOWN);
SendMouseInput(MOUSE_EVENT_FLAGS.MOUSEEVENTF_MIDDLEUP);
}
else if (button == 2) // Right mouse button
{
SendMouseInput(MOUSE_EVENT_FLAGS.MOUSEEVENTF_RIGHTDOWN);
SendMouseInput(MOUSE_EVENT_FLAGS.MOUSEEVENTF_RIGHTUP);
}
}

private static Input MouseInput(int dx, int dy, uint mouseData, uint dwFlags, uint time, nint dwExtraInfo)
/// <summary>
/// Sends a mouse input event.
/// </summary>
/// <param name="dwFlags">The mouse event flags that specify the type of mouse event.</param>
private static void SendMouseInput(MOUSE_EVENT_FLAGS dwFlags)
{
return new Input
{
type = 0,
mi = new InputMouse
INPUT[] inputs =
[
new()
{
dx = dx,
dy = dy,
mouseData = mouseData,
dwFlags = dwFlags,
time = time,
dwExtraInfo = dwExtraInfo
type = INPUT_TYPE.INPUT_MOUSE,
Anonymous = new INPUT._Anonymous_e__Union { mi = new MOUSEINPUT { dwFlags = dwFlags } }
}
};
}
];

[StructLayout(LayoutKind.Sequential)]
private struct Input
{
public int type;
public InputMouse mi;
}

[StructLayout(LayoutKind.Sequential)]
private struct InputMouse
{
public int dx;
public int dy;
public uint mouseData;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}

[Flags]
private enum MouseEventF : uint
{
LeftDown = 0x0002,
LeftUp = 0x0004,
RightDown = 0x0008,
RightUp = 0x0010,
MiddleDown = 0x0020,
MiddleUp = 0x0040
_ = PInvoke.SendInput(inputs, Marshal.SizeOf<INPUT>());
}
}
}
148 changes: 0 additions & 148 deletions FluentAutoClicker/Helpers/WindowMessageHook.cs

This file was deleted.

6 changes: 2 additions & 4 deletions FluentAutoClicker/MainPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,7 @@
<CheckBox
x:Name="ClickRepeatCheckBox"
x:Uid="ClickRepeatCheckBox"
Checked="ClickRepeatCheckBox_Checked"
Unchecked="ClickRepeatCheckBox_Unchecked" />
Click="CheckBox_Click" />
<NumberBox
x:Name="ClickRepeatAmount"
HorizontalAlignment="Left"
Expand All @@ -121,8 +120,7 @@
<CheckBox
x:Name="ClickOffsetCheckBox"
x:Uid="ClickOffsetCheckBox"
Checked="ClickOffsetCheckBox_Checked"
Unchecked="ClickOffsetCheckBox_Unchecked" />
Click="CheckBox_Click" />
<NumberBox
x:Name="ClickOffsetAmount"
HorizontalAlignment="Left"
Expand Down
Loading

0 comments on commit 2f4b123

Please sign in to comment.