Skip to content

Commit

Permalink
Refactored some classes
Browse files Browse the repository at this point in the history
  • Loading branch information
king.nakama committed Sep 20, 2022
1 parent e76bc0f commit a33101d
Show file tree
Hide file tree
Showing 10 changed files with 109 additions and 104 deletions.
5 changes: 2 additions & 3 deletions Src/ContainerModule.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Autofac;
using NClicker.Hooks;
using NClicker.Repositories;
using NClicker.Services;
using NClicker.Storage;
Expand All @@ -20,10 +19,10 @@ protected override void Load(ContainerBuilder builder)
builder.Register(c => new MouseControllerService(new System.Random()))
.As<IMouseControllerService>().SingleInstance();

builder.Register(c => new GlobalKeyboardHook()).SingleInstance();
builder.Register(c => new GlobalKeyboardService()).SingleInstance();

builder.Register(c => new KeyboardService(
c.Resolve<GlobalKeyboardHook>())).As<IKeyboardService>().SingleInstance();
c.Resolve<GlobalKeyboardService>())).As<IKeyboardService>().SingleInstance();

builder.Register(c => new MainViewModel(c.Resolve<IPresetService>(),
c.Resolve<IKeyboardService>())).SingleInstance();
Expand Down
49 changes: 49 additions & 0 deletions Src/Helpers/Win32KernelApi.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using NClicker.Services;
using System;
using System.Runtime.InteropServices;

namespace NClicker.Helpers
{
public class Win32KernelApi
{
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr LoadLibrary(string lpFileName);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool FreeLibrary(IntPtr hModule);

/// <summary>
/// The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain.
/// You would install a hook procedure to monitor the system for certain types of events. These events are
/// associated either with a specific thread or with all threads in the same desktop as the calling thread.
/// </summary>
/// <param name="idHook">hook type</param>
/// <param name="lpfn">hook procedure</param>
/// <param name="hMod">handle to application instance</param>
/// <param name="dwThreadId">thread identifier</param>
/// <returns>If the function succeeds, the return value is the handle to the hook procedure.</returns>
[DllImport("USER32", SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, GlobalKeyboardService.HookProc hookProc, IntPtr hMod, int dwThreadId);
/// <summary>
/// The UnhookWindowsHookEx function removes a hook procedure installed in a hook chain by the SetWindowsHookEx function.
/// </summary>
/// <param name="hhk">handle to hook procedure</param>
/// <returns>If the function succeeds, the return value is true.</returns>
[DllImport("USER32", SetLastError = true)]
public static extern bool UnhookWindowsHookEx(IntPtr hHook);

/// <summary>
/// The CallNextHookEx function passes the hook information to the next hook procedure in the current hook chain.
/// A hook procedure can call this function either before or after processing the hook information.
/// </summary>
/// <param name="hHook">handle to current hook</param>
/// <param name="code">hook code passed to hook procedure</param>
/// <param name="wParam">value passed to hook procedure</param>
/// <param name="lParam">value passed to hook procedure</param>
/// <returns>If the function succeeds, the return value is true.</returns>
[DllImport("USER32", SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hHook, int code, IntPtr wParam, IntPtr lParam);


}
}
18 changes: 0 additions & 18 deletions Src/Hooks/GlobalKeyboardHookEventArgs.cs

This file was deleted.

18 changes: 18 additions & 0 deletions Src/Models/GlobalKeyboardHookEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using NClicker.Services;
using System.ComponentModel;

namespace NClicker.Models
{
public class GlobalKeyboardHookEventArgs : HandledEventArgs
{
public GlobalKeyboardService.KeyboardState KeyboardState { get; }
public GlobalKeyboardService.LowLevelKeyboardInputEvent KeyboardData { get; }

public GlobalKeyboardHookEventArgs(GlobalKeyboardService.LowLevelKeyboardInputEvent keyboardData,
GlobalKeyboardService.KeyboardState keyboardState)
{
KeyboardData = keyboardData;
KeyboardState = keyboardState;
}
}
}
1 change: 1 addition & 0 deletions Src/NClicker.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<PackageProjectUrl>https://github.com/Buryyy/NClicker</PackageProjectUrl>
<PackageIcon>nclicker.png</PackageIcon>
<StartupObject>NClicker.App</StartupObject>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
using System;
using NClicker.Helpers;
using NClicker.Models;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace NClicker.Hooks
namespace NClicker.Services
{
public sealed class GlobalKeyboardHook : IDisposable
public sealed class GlobalKeyboardService : IDisposable
{
public event EventHandler<GlobalKeyboardHookEventArgs> KeyboardPressed;
private IntPtr _windowsHookHandle;
private IntPtr _user32LibraryHandle;
private HookProc _hookProc;

public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);

public GlobalKeyboardHook()
public GlobalKeyboardService()
{
_windowsHookHandle = IntPtr.Zero;
_user32LibraryHandle = IntPtr.Zero;
_hookProc =
LowLevelKeyboardProc; // we must keep alive _hookProc, because GC is not aware about SetWindowsHookEx behaviour.
_hookProc = LowLevelKeyboardProc; // we must keep alive _hookProc, because GC is not aware about SetWindowsHookEx behaviour.

_user32LibraryHandle = LoadLibrary("User32");
_user32LibraryHandle = Win32KernelApi.LoadLibrary("User32");
if (_user32LibraryHandle == IntPtr.Zero)
{
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception(errorCode,
$"Failed to load library 'User32.dll'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}.");
}

_windowsHookHandle = SetWindowsHookEx(WH_KEYBOARD_LL, _hookProc, _user32LibraryHandle, 0);
_windowsHookHandle = Win32KernelApi.SetWindowsHookEx(WH_KEYBOARD_LL, _hookProc, _user32LibraryHandle, 0);
if (_windowsHookHandle == IntPtr.Zero)
{
int errorCode = Marshal.GetLastWin32Error();
Expand All @@ -40,7 +46,7 @@ private void Dispose(bool disposing)
// because we can unhook only in the same thread, not in garbage collector thread
if (_windowsHookHandle != IntPtr.Zero)
{
if (!UnhookWindowsHookEx(_windowsHookHandle))
if (!Win32KernelApi.UnhookWindowsHookEx(_windowsHookHandle))
{
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception(errorCode,
Expand All @@ -56,7 +62,7 @@ private void Dispose(bool disposing)

if (_user32LibraryHandle != IntPtr.Zero)
{
if (!FreeLibrary(_user32LibraryHandle)) // reduces reference to library by 1.
if (!Win32KernelApi.FreeLibrary(_user32LibraryHandle)) // reduces reference to library by 1.
{
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception(errorCode,
Expand All @@ -67,61 +73,6 @@ private void Dispose(bool disposing)
}
}

~GlobalKeyboardHook()
{
Dispose(false);
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

private IntPtr _windowsHookHandle;
private IntPtr _user32LibraryHandle;
private HookProc _hookProc;

private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);

[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr LoadLibrary(string lpFileName);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool FreeLibrary(IntPtr hModule);

/// <summary>
/// The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain.
/// You would install a hook procedure to monitor the system for certain types of events. These events are
/// associated either with a specific thread or with all threads in the same desktop as the calling thread.
/// </summary>
/// <param name="idHook">hook type</param>
/// <param name="lpfn">hook procedure</param>
/// <param name="hMod">handle to application instance</param>
/// <param name="dwThreadId">thread identifier</param>
/// <returns>If the function succeeds, the return value is the handle to the hook procedure.</returns>
[DllImport("USER32", SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);

/// <summary>
/// The UnhookWindowsHookEx function removes a hook procedure installed in a hook chain by the SetWindowsHookEx function.
/// </summary>
/// <param name="hhk">handle to hook procedure</param>
/// <returns>If the function succeeds, the return value is true.</returns>
[DllImport("USER32", SetLastError = true)]
private static extern bool UnhookWindowsHookEx(IntPtr hHook);

/// <summary>
/// The CallNextHookEx function passes the hook information to the next hook procedure in the current hook chain.
/// A hook procedure can call this function either before or after processing the hook information.
/// </summary>
/// <param name="hHook">handle to current hook</param>
/// <param name="code">hook code passed to hook procedure</param>
/// <param name="wParam">value passed to hook procedure</param>
/// <param name="lParam">value passed to hook procedure</param>
/// <returns>If the function succeeds, the return value is true.</returns>
[DllImport("USER32", SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hHook, int code, IntPtr wParam, IntPtr lParam);

[StructLayout(LayoutKind.Sequential)]
public struct LowLevelKeyboardInputEvent
Expand Down Expand Up @@ -172,7 +123,7 @@ public enum KeyboardState
//const int VkControl = 0x11;
private const int KfAltdown = 0x2000;

public const int LlkhfAltdown = (KfAltdown >> 8);
public const int LlkhfAltdown = KfAltdown >> 8;

public IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam)
{
Expand All @@ -191,7 +142,19 @@ public IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam)
fEatKeyStroke = eventArguments.Handled;
}

return fEatKeyStroke ? (IntPtr)1 : CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam);
return fEatKeyStroke ? (IntPtr)1 : Win32KernelApi.CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam);

}

~GlobalKeyboardService()
{
Dispose(false);
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
2 changes: 1 addition & 1 deletion Src/Services/IMouseControllerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{
public interface IMouseControllerService
{
void LoopClick(int seconds, int milliseconds, int randomSeconds, int randomMilliseconds);
void OnLoopClick(int seconds, int milliseconds, int randomSeconds, int randomMilliseconds);

void Stop();
}
Expand Down
10 changes: 5 additions & 5 deletions Src/Services/KeyboardService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Autofac;
using NClicker.Hooks;
using NClicker.Models;
using NClicker.ViewModels;

namespace NClicker.Services
Expand All @@ -9,13 +9,13 @@ public class KeyboardService : IKeyboardService
private const int VirtualKeyF1 = 0x70;
private const int VirtualKeyF2 = 0x71;

private readonly GlobalKeyboardHook _globalKeyboardHook;
private readonly GlobalKeyboardService _globalKeyboardService;
private bool _blockKeys;

public KeyboardService(GlobalKeyboardHook globalKeyboardHook)
public KeyboardService(GlobalKeyboardService globalKeyboardService)
{
_globalKeyboardHook = globalKeyboardHook;
_globalKeyboardHook.KeyboardPressed += OnKeyPressed;
_globalKeyboardService = globalKeyboardService;
_globalKeyboardService.KeyboardPressed += OnKeyPressed;
}

private void OnKeyPressed(object sender, GlobalKeyboardHookEventArgs @event)
Expand Down
11 changes: 2 additions & 9 deletions Src/Services/MouseControllerService.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using NClicker.Helpers;
using NClicker.Models;
using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

namespace NClicker.Services
Expand All @@ -14,16 +13,10 @@ public class MouseControllerService : IMouseControllerService

public MouseControllerService(Random random)
{
_random = new Random();
_random = Random.Shared;
}



[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetCursorPos(out Position lpPoint);

public void LoopClick(int seconds, int milliseconds, int randomSeconds, int randomMilliseconds)
public void OnLoopClick(int seconds, int milliseconds, int randomSeconds, int randomMilliseconds)
{
if (IsRunning) return;
Task.Run(async () =>
Expand Down
2 changes: 1 addition & 1 deletion Src/ViewModels/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public MainViewModel(IPresetService presetService,
}

App.Context.Resolve<IMouseControllerService>()
.LoopClick(_seconds, _milliseconds, _randomSeconds, _randomMilliseconds);
.OnLoopClick(_seconds, _milliseconds, _randomSeconds, _randomMilliseconds);
}
catch (Exception exception)
{
Expand Down

0 comments on commit a33101d

Please sign in to comment.