diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1f8dd0a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,244 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +#### Core EditorConfig Options #### + +# Indentation and spacing +indent_size = 4 +indent_style = space +tab_width = 4 + +# New line preferences +end_of_line = crlf +insert_final_newline = false + +#### .NET Code Actions #### + +# Type members +dotnet_hide_advanced_members = false +dotnet_member_insertion_location = with_other_members_of_the_same_kind +dotnet_property_generation_behavior = prefer_throwing_properties + +# Symbol search +dotnet_search_reference_assemblies = true + +#### .NET Coding Conventions #### + +# Organize usings +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = false +file_header_template = Copyright (C) 2024 Ryan Luu\n\nThis file is part of Fluent Auto Clicker.\n\nFluent Auto Clicker is free software: you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published\nby the Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nFluent Auto Clicker is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with Fluent Auto Clicker. If not, see . + +# this. and Me. preferences +dotnet_style_qualification_for_event = false +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false +dotnet_style_qualification_for_property = false + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_operators = never_if_unnecessary +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members + +# Expression-level preferences +dotnet_prefer_system_hash_code = true +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true +dotnet_style_explicit_tuple_names = true +dotnet_style_namespace_match_folder = true +dotnet_style_null_propagation = true +dotnet_style_object_initializer = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true +dotnet_style_prefer_collection_expression = when_types_loosely_match +dotnet_style_prefer_compound_assignment = true +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed +dotnet_style_prefer_inferred_anonymous_type_member_names = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +dotnet_style_prefer_simplified_boolean_expressions = true +dotnet_style_prefer_simplified_interpolation = true + +# Field preferences +dotnet_style_readonly_field = true + +# Parameter preferences +dotnet_code_quality_unused_parameters = all + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none + +# New line preferences +dotnet_style_allow_multiple_blank_lines_experimental = true +dotnet_style_allow_statement_immediately_after_block_experimental = true + +#### C# Coding Conventions #### + +# var preferences +csharp_style_var_elsewhere = false +csharp_style_var_for_built_in_types = false +csharp_style_var_when_type_is_apparent = false + +# Expression-bodied members +csharp_style_expression_bodied_accessors = true +csharp_style_expression_bodied_constructors = false +csharp_style_expression_bodied_indexers = true +csharp_style_expression_bodied_lambdas = true +csharp_style_expression_bodied_local_functions = false +csharp_style_expression_bodied_methods = false +csharp_style_expression_bodied_operators = false +csharp_style_expression_bodied_properties = true + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true +csharp_style_pattern_matching_over_is_with_cast_check = true +csharp_style_prefer_extended_property_pattern = true +csharp_style_prefer_not_pattern = true +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_switch_expression = true + +# Null-checking preferences +csharp_style_conditional_delegate_call = true + +# Modifier preferences +csharp_prefer_static_anonymous_function = true +csharp_prefer_static_local_function = true +csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async +csharp_style_prefer_readonly_struct = true +csharp_style_prefer_readonly_struct_member = true + +# Code-block preferences +csharp_prefer_braces = true +csharp_prefer_simple_using_statement = true +csharp_prefer_system_threading_lock = true +csharp_style_namespace_declarations = file_scoped +csharp_style_prefer_method_group_conversion = true +csharp_style_prefer_primary_constructors = true +csharp_style_prefer_top_level_statements = true + +# Expression-level preferences +csharp_prefer_simple_default_expression = true +csharp_style_deconstructed_variable_declaration = true +csharp_style_implicit_object_creation_when_type_is_apparent = true +csharp_style_inlined_variable_declaration = true +csharp_style_prefer_index_operator = true +csharp_style_prefer_local_over_anonymous_function = true +csharp_style_prefer_null_check_over_type_check = true +csharp_style_prefer_range_operator = true +csharp_style_prefer_tuple_swap = true +csharp_style_prefer_utf8_string_literals = true +csharp_style_throw_expression = true +csharp_style_unused_value_assignment_preference = discard_variable +csharp_style_unused_value_expression_statement_preference = discard_variable + +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace + +# New line preferences +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true +csharp_style_allow_embedded_statements_on_same_line_experimental = true + +#### C# Formatting Rules #### + +# New line preferences +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..16cf501 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,65 @@ +name: Continuous Integration + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + build: + name: Build + runs-on: windows-latest + + strategy: + matrix: + configuration: [Release] + platform: [x64, x86, ARM64] + + env: + Solution_Name: FluentAutoClicker.sln + Dir_Name: FluentAutoClicker + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install .NET Core + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0.x + + - name: Setup MSBuild.exe + uses: microsoft/setup-msbuild@v2 + + - name: Restore the application + run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration + env: + Configuration: ${{ matrix.configuration }} + + - name: Decode the pfx + run: | + $pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.BASE64_ENCODED_PFX }}") + $certificatePath = "GitHubActionsWorkflow.pfx" + [IO.File]::WriteAllBytes("$certificatePath", $pfx_cert_byte) + + - name: Create the app package + run: msbuild $env:Solution_Name /p:Configuration=$env:Configuration /p:Platform=$env:Platform /p:UapAppxPackageBuildMode=$env:Appx_Package_Build_Mode /p:AppxBundle=$env:Appx_Bundle /p:PackageCertificateKeyFile=GitHubActionsWorkflow.pfx /p:AppxPackageDir="$env:Appx_Package_Dir" /p:GenerateAppxPackageOnBuild=true + env: + Appx_Bundle: Never + Appx_Package_Build_Mode: SideloadOnly + Appx_Package_Dir: Packages\ + Configuration: ${{ matrix.configuration }} + Platform: ${{ matrix.platform }} + + - name: Remove the pfx + run: Remove-Item -path GitHubActionsWorkflow.pfx + + - name: Upload MSIX package + uses: actions/upload-artifact@v4 + with: + name: MSIX Package (${{ matrix.configuration }}, ${{ matrix.platform }}) + path: ${{ github.workspace }}\${{ env.Dir_Name }}\Packages\** + compression-level: 0 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 6e59ccb..0cc3a72 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -1,5 +1,8 @@ -name: 'Dependency Review' -on: [pull_request] +name: Dependency Review + +on: + pull_request: + types: [opened] permissions: contents: read @@ -7,12 +10,14 @@ permissions: jobs: dependency-review: + name: Review runs-on: ubuntu-latest + steps: - - name: 'Checkout Repository' + - name: Checkout repository uses: actions/checkout@v4 - - name: 'Dependency Review' - uses: actions/dependency-review-action@v4 + + - name: Run dependency review + uses: actions/actions/dependency-review-action@v4 with: - allow-licenses: MIT, Apache-2.0, Unlicense, BSL-1.0 comment-summary-in-pr: always diff --git a/.imgbotconfig b/.imgbotconfig deleted file mode 100644 index ea2afad..0000000 --- a/.imgbotconfig +++ /dev/null @@ -1,5 +0,0 @@ -{ - "schedule": "daily", - "aggressiveCompression": "true", - "compressWiki": "true", -} diff --git a/.vsconfig b/.vsconfig index 1a966e8..2389b29 100644 --- a/.vsconfig +++ b/.vsconfig @@ -3,24 +3,7 @@ "components": [ "Microsoft.VisualStudio.Component.CoreEditor", "Microsoft.VisualStudio.Workload.CoreEditor", - "Microsoft.VisualStudio.Component.Roslyn.Compiler", - "Microsoft.VisualStudio.Component.Roslyn.LanguageServices", - "Microsoft.VisualStudio.Component.NuGet", - "Microsoft.VisualStudio.Component.SQL.CLR", - "Microsoft.NetCore.Component.Runtime.8.0", - "Microsoft.NetCore.Component.SDK", - "Microsoft.VisualStudio.Component.AppInsights.Tools", - "Microsoft.VisualStudio.Component.DiagnosticTools", - "Microsoft.NetCore.Component.Runtime.6.0", - "Microsoft.VisualStudio.ComponentGroup.WindowsAppSDK.Cs", - "Microsoft.ComponentGroup.Blend", - "Microsoft.Component.NetFX.Native", - "Microsoft.VisualStudio.Component.Graphics", - "Microsoft.VisualStudio.ComponentGroup.WindowsAppDevelopment.Prerequisites", - "Microsoft.VisualStudio.ComponentGroup.UWP.NetCoreAndStandard", "Microsoft.VisualStudio.Workload.Universal" ], - "extensions": [ - "https://marketplace.visualstudio.com/items?itemName=TeamXavalon.XAMLStyler2022" - ] -} \ No newline at end of file + "extensions": [] +} diff --git a/FluentAutoClicker/App.xaml b/FluentAutoClicker/App.xaml index 64214c3..9cb920c 100644 --- a/FluentAutoClicker/App.xaml +++ b/FluentAutoClicker/App.xaml @@ -1,24 +1,4 @@ - - - - + - + - + diff --git a/FluentAutoClicker/App.xaml.cs b/FluentAutoClicker/App.xaml.cs index 279bcf0..ab9d74e 100644 --- a/FluentAutoClicker/App.xaml.cs +++ b/FluentAutoClicker/App.xaml.cs @@ -1,53 +1,50 @@ -/* - Copyright (C) 2024 Ryan Luu - - This file is part of Fluent Auto Clicker. - - Fluent Auto Clicker is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Fluent Auto Clicker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with Fluent Auto Clicker. If not, see . -*/ +// Copyright (C) 2024 Ryan Luu +// +// This file is part of Fluent Auto Clicker. +// +// Fluent Auto Clicker is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Fluent Auto Clicker is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with Fluent Auto Clicker. If not, see . using Microsoft.UI.Xaml; // To learn more about WinUI, the WinUI project structure, // and more about our project templates, see: http://aka.ms/winui-project-info. -namespace FluentAutoClicker +namespace FluentAutoClicker; + +/// +/// Provides application-specific behavior to supplement the default Application class. +/// +public partial class App : Application { /// - /// Provides application-specific behavior to supplement the default Application class. + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). /// - public partial class App : Application + public App() { - /// - /// Initializes the singleton application object. This is the first line of authored code - /// executed, and as such is the logical equivalent of main() or WinMain(). - /// - public App() - { - this.InitializeComponent(); - } - - /// - /// Invoked when the application is launched. - /// - /// Details about the launch request and process. - protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) - { - Window = new MainWindow(); - Window.Activate(); - } + InitializeComponent(); + } - public static Window Window { get; private set; } + /// + /// Invoked when the application is launched. + /// + /// Details about the launch request and process. + protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) + { + Window = new MainWindow(); + Window.Activate(); } + + public static Window Window { get; private set; } } \ No newline at end of file diff --git a/FluentAutoClicker/FluentAutoClicker.csproj b/FluentAutoClicker/FluentAutoClicker.csproj index f438d4c..915ddf4 100644 --- a/FluentAutoClicker/FluentAutoClicker.csproj +++ b/FluentAutoClicker/FluentAutoClicker.csproj @@ -1,57 +1,30 @@ - - - + WinExe net8.0-windows10.0.19041.0 10.0.17763.0 + 10.0.19041.54 FluentAutoClicker app.manifest x86;x64;ARM64 - win-x86;win-x64;win-arm64 - win10-x86;win10-x64;win10-arm64 - 8305 - WMC1501 + win-x86;win-x64;win-arm64 win-$(Platform).pubxml + enable true true - 10.0.19041.35-preview - true - Fluent Auto Clicker + DISABLE_XAML_GENERATED_MAIN + Ryan Luu + Copyright (C) 2024 Ryan Luu Assets\WindowIcon.ico + Fluent Auto Clicker - - - - - - + - - - - + + + False + + + + + False + False + False + + + False + False + False + + + False + False + False + + + False + True + True + + + True + True + True + + + True + True + True + + diff --git a/FluentAutoClicker/Helpers/AutoClicker.cs b/FluentAutoClicker/Helpers/AutoClicker.cs index 70bb12e..3da99d2 100644 --- a/FluentAutoClicker/Helpers/AutoClicker.cs +++ b/FluentAutoClicker/Helpers/AutoClicker.cs @@ -1,26 +1,21 @@ -/* - Copyright (C) 2024 Ryan Luu +// Copyright (C) 2024 Ryan Luu +// +// This file is part of Fluent Auto Clicker. +// +// Fluent Auto Clicker is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Fluent Auto Clicker is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with Fluent Auto Clicker. If not, see . - This file is part of Fluent Auto Clicker. - - Fluent Auto Clicker is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Fluent Auto Clicker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with Fluent Auto Clicker. If not, see . -*/ - -using System; using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; namespace FluentAutoClicker.Helpers; @@ -33,34 +28,47 @@ public static class AutoClicker private static extern uint SendInput(uint nInputs, Input[] pInputs, int cbSize); private static Thread _autoClickerThread; - private static bool IsAutoClickerRunning; - - public static void StartAutoClicker(int ClickInterval, int RepeatAmount, int MouseButton, int ClickOffset) + private static bool _isAutoClickerRunning; + + /// + /// Starts the auto clicker thread. + /// + /// The number of milliseconds to wait before clicks. + /// The number of clicks before stopping the auto clicker thread. + /// The mouse button used to click. + /// The amount of time in milliseconds to add randomly to the millisecond delay between clicks. + public static void StartAutoClicker(int millisecondsDelay, int clickAmount, int mouseButtonType, int clickDelayOffset) { - IsAutoClickerRunning = true; - _autoClickerThread = new Thread(() => AutoClickerThread(ClickInterval, RepeatAmount, MouseButton, ClickOffset)); + // TODO: Evaluate whether a thread is necessary for this. + _isAutoClickerRunning = true; + _autoClickerThread = new Thread(() => AutoClickerThread(millisecondsDelay, clickAmount, mouseButtonType, clickDelayOffset)); _autoClickerThread.Start(); } + /// + /// Stops the auto clicker thread. + /// public static void StopAutoClicker() { - IsAutoClickerRunning = false; + _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) { - var clickCount = 0; - var random = new Random(); - while (IsAutoClickerRunning) + int clickCount = 0; + Random random = new(); + while (_isAutoClickerRunning) { - if (clickCount >= RepeatAmount && RepeatAmount != 0) + if (clickCount >= repeatAmount && repeatAmount != 0) { StopAutoClicker(); break; } - switch (MouseButton) + // TODO: Move this to a enum instead of a number + switch (mouseButton) { case 0: MouseEvent(0, 0, (uint)MouseEventF.LeftDown, 0, 0, IntPtr.Zero); @@ -76,19 +84,22 @@ private static async void AutoClickerThread(int ClickInterval, int RepeatAmount, break; } - if (RepeatAmount > 0) clickCount++; + if (repeatAmount > 0) + { + clickCount++; + } - int randomClickOffset = random.Next(0, ClickOffset); - await Task.Delay(ClickInterval + randomClickOffset); + int randomClickOffset = 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) { - var inputs = new Input[2]; + 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(typeof(Input))); + _ = SendInput((uint)inputs.Length, inputs, Marshal.SizeOf()); } private static Input MouseInput(int dx, int dy, uint mouseData, uint dwFlags, uint time, nint dwExtraInfo) @@ -136,4 +147,4 @@ private enum MouseEventF : uint MiddleDown = 0x0020, MiddleUp = 0x0040 } -} +} \ No newline at end of file diff --git a/FluentAutoClicker/Helpers/ResourceExtensions.cs b/FluentAutoClicker/Helpers/ResourceExtensions.cs index a001efd..0a0b6cb 100644 --- a/FluentAutoClicker/Helpers/ResourceExtensions.cs +++ b/FluentAutoClicker/Helpers/ResourceExtensions.cs @@ -1,30 +1,36 @@ -/* - Copyright (C) 2024 Ryan Luu - - This file is part of Fluent Auto Clicker. - - Fluent Auto Clicker is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Fluent Auto Clicker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with Fluent Auto Clicker. If not, see . -*/ +// Copyright (C) 2024 Ryan Luu +// +// This file is part of Fluent Auto Clicker. +// +// Fluent Auto Clicker is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Fluent Auto Clicker is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with Fluent Auto Clicker. If not, see . using Microsoft.Windows.ApplicationModel.Resources; namespace FluentAutoClicker.Helpers; +/// +/// Helper for getting localized strings from resources. +/// public static class ResourceExtensions { private static readonly ResourceLoader ResourceLoader = new(); + /// + /// Gets the localized string for the resource key. + /// + /// The resource key for the returned localized string. + /// The localized string for the specified resource key. public static string GetLocalized(this string resourceKey) { return ResourceLoader.GetString(resourceKey); diff --git a/FluentAutoClicker/Helpers/WindowMessageHook.cs b/FluentAutoClicker/Helpers/WindowMessageHook.cs index dba96b3..ddc6ca4 100644 --- a/FluentAutoClicker/Helpers/WindowMessageHook.cs +++ b/FluentAutoClicker/Helpers/WindowMessageHook.cs @@ -1,38 +1,33 @@ -/* - Copyright (C) 2024 Ryan Luu - - This file is part of Fluent Auto Clicker. - - Fluent Auto Clicker is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Fluent Auto Clicker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with Fluent Auto Clicker. If not, see . -*/ +// Copyright (C) 2024 Ryan Luu +// +// This file is part of Fluent Auto Clicker. +// +// Fluent Auto Clicker is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Fluent Auto Clicker is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with Fluent Auto Clicker. If not, see . using Microsoft.UI.Xaml; -using System; using System.Collections.Concurrent; -using System.Collections.Generic; using System.ComponentModel; using System.Runtime.InteropServices; -using System.Threading; namespace FluentAutoClicker.Helpers; public class WindowMessageHook : IEquatable, IDisposable { - private delegate nint SUBCLASSPROC(nint hWnd, uint uMsg, nint wParam, nint lParam, nint uIdSubclass, uint dwRefData); + private delegate nint Subclassproc(nint hWnd, uint uMsg, nint wParam, nint lParam, nint uIdSubclass, uint dwRefData); - private static readonly ConcurrentDictionary _hooks = new(); - private static readonly SUBCLASSPROC _proc = SubclassProc; + private static readonly ConcurrentDictionary Hooks = new(); + private static readonly Subclassproc Proc = SubclassProc; public event EventHandler Message; private nint _hWnd; @@ -41,28 +36,44 @@ public WindowMessageHook(Window window) : this(GetHandle(window)) { } public WindowMessageHook(nint hWnd) { if (hWnd == 0) + { throw new ArgumentException(null, nameof(hWnd)); + } _hWnd = hWnd; - _hooks.AddOrUpdate(hWnd, this, (k, o) => + _ = Hooks.AddOrUpdate(hWnd, this, (k, o) => { - if (Equals(o)) return o; + if (Equals(o)) + { + return o; + } + o.Dispose(); return this; }); - if (!SetWindowSubclass(hWnd, _proc, 0, 0)) + if (!SetWindowSubclass(hWnd, Proc, 0, 0)) + { throw new Win32Exception(Marshal.GetLastWin32Error()); + } + } + + protected virtual void OnMessage(object sender, MessageEventArgs e) + { + Message?.Invoke(sender, e); } - protected virtual void OnMessage(object sender, MessageEventArgs e) => Message?.Invoke(sender, e); protected virtual void Dispose(bool disposing) { - if (!disposing) return; - var hWnd = Interlocked.Exchange(ref _hWnd, IntPtr.Zero); + if (!disposing) + { + return; + } + + nint hWnd = Interlocked.Exchange(ref _hWnd, IntPtr.Zero); if (hWnd != IntPtr.Zero) { - RemoveWindowSubclass(hWnd, _proc, 0); - _hooks.Remove(hWnd, out _); + _ = RemoveWindowSubclass(hWnd, Proc, 0); + _ = Hooks.Remove(hWnd, out _); } } @@ -70,13 +81,13 @@ protected virtual void Dispose(bool disposing) public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } [DllImport("comctl32", SetLastError = true)] - private static extern bool SetWindowSubclass(nint hWnd, SUBCLASSPROC pfnSubclass, uint uIdSubclass, uint dwRefData); + private static extern bool SetWindowSubclass(nint hWnd, Subclassproc pfnSubclass, uint uIdSubclass, uint dwRefData); [DllImport("comctl32", SetLastError = true)] private static extern nint DefSubclassProc(nint hWnd, uint uMsg, nint wParam, nint lParam); [DllImport("comctl32", SetLastError = true)] - private static extern bool RemoveWindowSubclass(nint hWnd, SUBCLASSPROC pfnSubclass, uint uIdSubclass); + private static extern bool RemoveWindowSubclass(nint hWnd, Subclassproc pfnSubclass, uint uIdSubclass); private static nint GetHandle(Window window) { @@ -86,20 +97,37 @@ private static nint GetHandle(Window window) private static nint SubclassProc(nint hWnd, uint uMsg, nint wParam, nint lParam, nint uIdSubclass, uint dwRefData) { - if (_hooks.TryGetValue(hWnd, out var hook)) + if (Hooks.TryGetValue(hWnd, out WindowMessageHook hook)) { - var e = new MessageEventArgs(hWnd, uMsg, wParam, lParam); + MessageEventArgs e = new(hWnd, uMsg, wParam, lParam); hook.OnMessage(hook, e); if (e.Result.HasValue) + { return e.Result.Value; + } } return DefSubclassProc(hWnd, uMsg, wParam, lParam); } - public override int GetHashCode() => _hWnd.GetHashCode(); - public override string ToString() => _hWnd.ToString(); - public override bool Equals(object obj) => Equals(obj as WindowMessageHook); - public virtual bool Equals(WindowMessageHook other) => other != null && _hWnd.Equals(other._hWnd); + public override int GetHashCode() + { + return _hWnd.GetHashCode(); + } + + public override string ToString() + { + return _hWnd.ToString(); + } + + public override bool Equals(object obj) + { + return Equals(obj as WindowMessageHook); + } + + public virtual bool Equals(WindowMessageHook other) + { + return other != null && _hWnd.Equals(other._hWnd); + } } public class MessageEventArgs : EventArgs @@ -117,4 +145,4 @@ public MessageEventArgs(nint hWnd, uint uMsg, nint wParam, nint lParam) public nint WParam { get; } public nint LParam { get; } public virtual nint? Result { get; set; } -} +} \ No newline at end of file diff --git a/FluentAutoClicker/MainPage.xaml b/FluentAutoClicker/MainPage.xaml index 23036bc..1a56715 100644 --- a/FluentAutoClicker/MainPage.xaml +++ b/FluentAutoClicker/MainPage.xaml @@ -1,24 +1,4 @@ - - - + @@ -37,12 +18,9 @@ - + + + @@ -54,7 +32,6 @@ - + - - - - - + SelectedIndex="0"> + + + + + + +