From e7fd0b964217e9ac338de8b5707210fe009076db Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Mon, 26 Jun 2023 22:33:15 +0100 Subject: [PATCH] Minor restructuring --- Bloxstrap/App.xaml.cs | 4 +- Bloxstrap/Bootstrapper.cs | 13 +- Bloxstrap/{Singletons => }/FastFlagManager.cs | 18 +- Bloxstrap/{Singletons => }/JsonManager.cs | 2 +- Bloxstrap/{Singletons => }/Logger.cs | 2 +- .../WinForms/DialogBase.cs | 2 + .../UI/Menu/ViewModels/FastFlagsViewModel.cs | 35 ++- .../UI/Menu/ViewModels/GlobalViewModel.cs | 2 +- Bloxstrap/Updater.cs | 2 +- Bloxstrap/Utilities.cs | 60 +----- Bloxstrap/{Tools => Utility}/AsyncMutex.cs | 204 +++++++++--------- Bloxstrap/Utility/MD5Hash.cs | 34 +++ Bloxstrap/{ => Utility}/NativeMethods.cs | 4 +- Bloxstrap/{Tools => Utility}/SystemEvent.cs | 94 ++++---- Bloxstrap/{ => Utility}/WindowScaling.cs | 65 +++--- 15 files changed, 256 insertions(+), 285 deletions(-) rename Bloxstrap/{Singletons => }/FastFlagManager.cs (98%) rename Bloxstrap/{Singletons => }/JsonManager.cs (98%) rename Bloxstrap/{Singletons => }/Logger.cs (98%) rename Bloxstrap/{Tools => Utility}/AsyncMutex.cs (97%) create mode 100644 Bloxstrap/Utility/MD5Hash.cs rename Bloxstrap/{ => Utility}/NativeMethods.cs (91%) rename Bloxstrap/{Tools => Utility}/SystemEvent.cs (96%) rename Bloxstrap/{ => Utility}/WindowScaling.cs (78%) diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index 2890972..affaefa 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -15,10 +15,10 @@ using Microsoft.Win32; using Bloxstrap.Extensions; using Bloxstrap.Models; -using Bloxstrap.Singletons; using Bloxstrap.UI.BootstrapperDialogs; using Bloxstrap.UI.Menu.Views; - +using Bloxstrap.Utility; + namespace Bloxstrap { /// diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index a52d885..66cfddc 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -256,7 +256,7 @@ namespace Bloxstrap if (_launchCommandLine == "--app" && App.Settings.Prop.UseDisableAppPatch) { - Utilities.OpenWebsite("https://www.roblox.com/games"); + Utilities.ShellExecute("https://www.roblox.com/games"); Dialog?.CloseBootstrapper(); return; } @@ -562,7 +562,7 @@ namespace Bloxstrap private async Task CheckForUpdates() { // don't update if there's another instance running (likely running in the background) - if (Utilities.GetProcessCount(App.ProjectName) > 1) + if (Process.GetProcessesByName(App.ProjectName).Count() > 1) { App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] More than one Bloxstrap instance running, aborting update check"); return; @@ -616,7 +616,7 @@ namespace Bloxstrap private void Uninstall() { // prompt to shutdown roblox if its currently running - if (Utilities.CheckIfRobloxRunning()) + if (Process.GetProcessesByName(App.RobloxAppName).Any()) { App.Logger.WriteLine($"[Bootstrapper::Uninstall] Prompting to shut down all open Roblox instances"); @@ -1004,7 +1004,7 @@ namespace Bloxstrap if (File.Exists(fileVersionFolder)) { - if (Utilities.MD5File(fileModFolder) == Utilities.MD5File(fileVersionFolder)) + if (Utility.MD5Hash.FromFile(fileModFolder) == Utility.MD5Hash.FromFile(fileVersionFolder)) continue; } @@ -1072,7 +1072,7 @@ namespace Bloxstrap await File.WriteAllBytesAsync(modFolderLocation, binaryData); } } - else if (File.Exists(modFolderLocation) && Utilities.MD5File(modFolderLocation) == Utilities.MD5Data(binaryData)) + else if (File.Exists(modFolderLocation) && Utility.MD5Hash.FromFile(modFolderLocation) == Utility.MD5Hash.FromBytes(binaryData)) { File.Delete(modFolderLocation); } @@ -1091,7 +1091,8 @@ namespace Bloxstrap { FileInfo file = new(packageLocation); - string calculatedMD5 = Utilities.MD5File(packageLocation); + string calculatedMD5 = Utility.MD5Hash.FromFile(packageLocation); + if (calculatedMD5 != package.Signature) { App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is corrupted ({calculatedMD5} != {package.Signature})! Deleting and re-downloading..."); diff --git a/Bloxstrap/Singletons/FastFlagManager.cs b/Bloxstrap/FastFlagManager.cs similarity index 98% rename from Bloxstrap/Singletons/FastFlagManager.cs rename to Bloxstrap/FastFlagManager.cs index f0ee4d0..104905e 100644 --- a/Bloxstrap/Singletons/FastFlagManager.cs +++ b/Bloxstrap/FastFlagManager.cs @@ -1,10 +1,8 @@ -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Text.Json; -namespace Bloxstrap.Singletons +namespace Bloxstrap { public class FastFlagManager : JsonManager> { @@ -103,18 +101,18 @@ namespace Bloxstrap.Singletons // this will set the flag to the corresponding value if the condition is true // if the condition is not true, the flag will be erased - public void SetValueIf(bool condition, string key, object? value) - { + public void SetValueIf(bool condition, string key, object? value) + { if (condition) SetValue(key, value); else if (GetValue(key) is not null) - SetValue(key, null); + SetValue(key, null); } - public void SetValueOnce(string key, object? value) - { + public void SetValueOnce(string key, object? value) + { if (GetValue(key) is null) - SetValue(key, value); + SetValue(key, value); } // this returns null if the fflag doesn't exist diff --git a/Bloxstrap/Singletons/JsonManager.cs b/Bloxstrap/JsonManager.cs similarity index 98% rename from Bloxstrap/Singletons/JsonManager.cs rename to Bloxstrap/JsonManager.cs index 7f212e8..f888341 100644 --- a/Bloxstrap/Singletons/JsonManager.cs +++ b/Bloxstrap/JsonManager.cs @@ -2,7 +2,7 @@ using System.IO; using System.Text.Json; -namespace Bloxstrap.Singletons +namespace Bloxstrap { public class JsonManager where T : new() { diff --git a/Bloxstrap/Singletons/Logger.cs b/Bloxstrap/Logger.cs similarity index 98% rename from Bloxstrap/Singletons/Logger.cs rename to Bloxstrap/Logger.cs index 190f8b5..ad4bc93 100644 --- a/Bloxstrap/Singletons/Logger.cs +++ b/Bloxstrap/Logger.cs @@ -5,7 +5,7 @@ using System.IO; using System.Text; using System.Threading; -namespace Bloxstrap.Singletons +namespace Bloxstrap { // https://stackoverflow.com/a/53873141/11852173 // TODO - this kind of sucks diff --git a/Bloxstrap/UI/BootstrapperDialogs/WinForms/DialogBase.cs b/Bloxstrap/UI/BootstrapperDialogs/WinForms/DialogBase.cs index dfcc15e..af9b34a 100644 --- a/Bloxstrap/UI/BootstrapperDialogs/WinForms/DialogBase.cs +++ b/Bloxstrap/UI/BootstrapperDialogs/WinForms/DialogBase.cs @@ -1,7 +1,9 @@ using System; using System.Windows; using System.Windows.Forms; + using Bloxstrap.Extensions; +using Bloxstrap.Utility; namespace Bloxstrap.UI.BootstrapperDialogs.WinForms { diff --git a/Bloxstrap/UI/Menu/ViewModels/FastFlagsViewModel.cs b/Bloxstrap/UI/Menu/ViewModels/FastFlagsViewModel.cs index ce1e301..afb4a8c 100644 --- a/Bloxstrap/UI/Menu/ViewModels/FastFlagsViewModel.cs +++ b/Bloxstrap/UI/Menu/ViewModels/FastFlagsViewModel.cs @@ -1,13 +1,10 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; +using System.ComponentModel; using System.IO; using System.Windows.Input; using CommunityToolkit.Mvvm.Input; -using Bloxstrap.Singletons; -using System.ComponentModel; - namespace Bloxstrap.UI.Menu.ViewModels { public class FastFlagsViewModel : INotifyPropertyChanged @@ -17,7 +14,7 @@ namespace Bloxstrap.UI.Menu.ViewModels public ICommand OpenClientSettingsCommand => new RelayCommand(OpenClientSettings); - private void OpenClientSettings() => Utilities.OpenWebsite(Path.Combine(Directories.Modifications, "ClientSettings\\ClientAppSettings.json")); + private void OpenClientSettings() => Utilities.ShellExecute(Path.Combine(Directories.Modifications, "ClientSettings\\ClientAppSettings.json")); public int FramerateLimit { @@ -40,19 +37,19 @@ namespace Bloxstrap.UI.Menu.ViewModels return "Automatic"; } - set - { - foreach (var mode in RenderingModes) - { - if (mode.Key != "Automatic") - App.FastFlags.SetValue(mode.Value, null); - } - - if (value == "Automatic") - return; - - App.FastFlags.SetValue(RenderingModes[value], "True"); - App.FastFlags.SetValueIf(value == "Vulkan", "FFlagRenderVulkanFixMinimizeWindow", "True"); + set + { + foreach (var mode in RenderingModes) + { + if (mode.Key != "Automatic") + App.FastFlags.SetValue(mode.Value, null); + } + + if (value == "Automatic") + return; + + App.FastFlags.SetValue(RenderingModes[value], "True"); + App.FastFlags.SetValueIf(value == "Vulkan", "FFlagRenderVulkanFixMinimizeWindow", "True"); } } diff --git a/Bloxstrap/UI/Menu/ViewModels/GlobalViewModel.cs b/Bloxstrap/UI/Menu/ViewModels/GlobalViewModel.cs index 0b292a5..689945d 100644 --- a/Bloxstrap/UI/Menu/ViewModels/GlobalViewModel.cs +++ b/Bloxstrap/UI/Menu/ViewModels/GlobalViewModel.cs @@ -14,7 +14,7 @@ namespace Bloxstrap.UI.Menu.ViewModels if (location is null) return; - Utilities.OpenWebsite(location); + Utilities.ShellExecute(location); } } } diff --git a/Bloxstrap/Updater.cs b/Bloxstrap/Updater.cs index 5a7e979..d229f1c 100644 --- a/Bloxstrap/Updater.cs +++ b/Bloxstrap/Updater.cs @@ -78,7 +78,7 @@ namespace Bloxstrap if (isAutoUpgrade) { - EventHandler ReleaseNotesLauncher = new((_, _) => Utilities.OpenWebsite($"https://github.com/{App.ProjectRepository}/releases/tag/v{currentVersionInfo.ProductVersion}")); + EventHandler ReleaseNotesLauncher = new((_, _) => Utilities.ShellExecute($"https://github.com/{App.ProjectRepository}/releases/tag/v{currentVersionInfo.ProductVersion}")); App.Notification.BalloonTipTitle = $"Bloxstrap has been upgraded to v{currentVersionInfo.ProductVersion}"; App.Notification.BalloonTipText = "Click here to see what's new in this version"; diff --git a/Bloxstrap/Utilities.cs b/Bloxstrap/Utilities.cs index 5cce944..53571d9 100644 --- a/Bloxstrap/Utilities.cs +++ b/Bloxstrap/Utilities.cs @@ -10,11 +10,6 @@ namespace Bloxstrap { static class Utilities { - public static bool IsDirectoryEmpty(string path) - { - return !Directory.EnumerateFileSystemEntries(path).Any(); - } - public static long GetFreeDiskSpace(string path) { foreach (DriveInfo drive in DriveInfo.GetDrives()) @@ -26,24 +21,7 @@ namespace Bloxstrap return -1; } - public static int GetProcessCount(string processName, bool log = true) - { - if (log) - App.Logger.WriteLine($"[Utilities::CheckIfProcessRunning] Checking if '{processName}' is running..."); - - Process[] processes = Process.GetProcessesByName(processName); - - if (log) - App.Logger.WriteLine($"[Utilities::CheckIfProcessRunning] Found {processes.Length} process(es) running for '{processName}'"); - - return processes.Length; - } - - public static bool CheckIfProcessRunning(string processName, bool log = true) => GetProcessCount(processName, log) >= 1; - - public static bool CheckIfRobloxRunning(bool log = true) => CheckIfProcessRunning("RobloxPlayerBeta", log); - - public static void OpenWebsite(string website) => Process.Start(new ProcessStartInfo { FileName = website, UseShellExecute = true }); + public static void ShellExecute(string website) => Process.Start(new ProcessStartInfo { FileName = website, UseShellExecute = true }); public static async Task GetJson(string url) { @@ -61,41 +39,5 @@ namespace Bloxstrap return default; } } - - public static string MD5File(string filename) - { - using (MD5 md5 = MD5.Create()) - { - using (FileStream stream = File.OpenRead(filename)) - { - byte[] hash = md5.ComputeHash(stream); - return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); - } - } - } - - public static string MD5Data(byte[] data) - { - using (MD5 md5 = MD5.Create()) - { - byte[] hash = md5.ComputeHash(data); - return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); - } - } - - // quick and hacky way of getting a value from any key/value pair formatted list - // (command line args, uri params, etc) - public static string? GetKeyValue(string subject, string key, char delimiter) - { - if (subject.LastIndexOf(key) == -1) - return null; - - string substr = subject.Substring(subject.LastIndexOf(key) + key.Length); - - if (!substr.Contains(delimiter)) - return null; - - return substr.Split(delimiter)[0]; - } } } diff --git a/Bloxstrap/Tools/AsyncMutex.cs b/Bloxstrap/Utility/AsyncMutex.cs similarity index 97% rename from Bloxstrap/Tools/AsyncMutex.cs rename to Bloxstrap/Utility/AsyncMutex.cs index fa6d137..e6e972f 100644 --- a/Bloxstrap/Tools/AsyncMutex.cs +++ b/Bloxstrap/Utility/AsyncMutex.cs @@ -1,102 +1,102 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace Bloxstrap.Tools -{ - // https://gist.github.com/dfederm/35c729f6218834b764fa04c219181e4e - - public sealed class AsyncMutex : IAsyncDisposable - { - private readonly string _name; - private Task? _mutexTask; - private ManualResetEventSlim? _releaseEvent; - private CancellationTokenSource? _cancellationTokenSource; - - public AsyncMutex(string name) - { - _name = name; - } - - public Task AcquireAsync(CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - TaskCompletionSource taskCompletionSource = new(); - - _releaseEvent = new ManualResetEventSlim(); - _cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); - - // Putting all mutex manipulation in its own task as it doesn't work in async contexts - // Note: this task should not throw. - _mutexTask = Task.Factory.StartNew( - state => - { - try - { - CancellationToken cancellationToken = _cancellationTokenSource.Token; - using var mutex = new Mutex(false, _name); - try - { - // Wait for either the mutex to be acquired, or cancellation - if (WaitHandle.WaitAny(new[] { mutex, cancellationToken.WaitHandle }) != 0) - { - taskCompletionSource.SetCanceled(cancellationToken); - return; - } - } - catch (AbandonedMutexException) - { - // Abandoned by another process, we acquired it. - } - - taskCompletionSource.SetResult(); - - // Wait until the release call - _releaseEvent.Wait(); - - mutex.ReleaseMutex(); - } - catch (OperationCanceledException) - { - taskCompletionSource.TrySetCanceled(cancellationToken); - } - catch (Exception ex) - { - taskCompletionSource.TrySetException(ex); - } - }, - state: null, - cancellationToken, - TaskCreationOptions.LongRunning, - TaskScheduler.Default); - - return taskCompletionSource.Task; - } - - public async Task ReleaseAsync() - { - _releaseEvent?.Set(); - - if (_mutexTask != null) - { - await _mutexTask; - } - } - - public async ValueTask DisposeAsync() - { - // Ensure the mutex task stops waiting for any acquire - _cancellationTokenSource?.Cancel(); - - // Ensure the mutex is released - await ReleaseAsync(); - - _releaseEvent?.Dispose(); - _cancellationTokenSource?.Dispose(); - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Bloxstrap.Tools +{ + // https://gist.github.com/dfederm/35c729f6218834b764fa04c219181e4e + + public sealed class AsyncMutex : IAsyncDisposable + { + private readonly string _name; + private Task? _mutexTask; + private ManualResetEventSlim? _releaseEvent; + private CancellationTokenSource? _cancellationTokenSource; + + public AsyncMutex(string name) + { + _name = name; + } + + public Task AcquireAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + TaskCompletionSource taskCompletionSource = new(); + + _releaseEvent = new ManualResetEventSlim(); + _cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + + // Putting all mutex manipulation in its own task as it doesn't work in async contexts + // Note: this task should not throw. + _mutexTask = Task.Factory.StartNew( + state => + { + try + { + CancellationToken cancellationToken = _cancellationTokenSource.Token; + using var mutex = new Mutex(false, _name); + try + { + // Wait for either the mutex to be acquired, or cancellation + if (WaitHandle.WaitAny(new[] { mutex, cancellationToken.WaitHandle }) != 0) + { + taskCompletionSource.SetCanceled(cancellationToken); + return; + } + } + catch (AbandonedMutexException) + { + // Abandoned by another process, we acquired it. + } + + taskCompletionSource.SetResult(); + + // Wait until the release call + _releaseEvent.Wait(); + + mutex.ReleaseMutex(); + } + catch (OperationCanceledException) + { + taskCompletionSource.TrySetCanceled(cancellationToken); + } + catch (Exception ex) + { + taskCompletionSource.TrySetException(ex); + } + }, + state: null, + cancellationToken, + TaskCreationOptions.LongRunning, + TaskScheduler.Default); + + return taskCompletionSource.Task; + } + + public async Task ReleaseAsync() + { + _releaseEvent?.Set(); + + if (_mutexTask != null) + { + await _mutexTask; + } + } + + public async ValueTask DisposeAsync() + { + // Ensure the mutex task stops waiting for any acquire + _cancellationTokenSource?.Cancel(); + + // Ensure the mutex is released + await ReleaseAsync(); + + _releaseEvent?.Dispose(); + _cancellationTokenSource?.Dispose(); + } + } +} diff --git a/Bloxstrap/Utility/MD5Hash.cs b/Bloxstrap/Utility/MD5Hash.cs new file mode 100644 index 0000000..9e1abcb --- /dev/null +++ b/Bloxstrap/Utility/MD5Hash.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace Bloxstrap.Utility +{ + public static class MD5Hash + { + public static string FromFile(string filename) + { + using (MD5 md5 = MD5.Create()) + { + using (FileStream stream = File.OpenRead(filename)) + { + byte[] hash = md5.ComputeHash(stream); + return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); + } + } + } + + public static string FromBytes(byte[] data) + { + using (MD5 md5 = MD5.Create()) + { + byte[] hash = md5.ComputeHash(data); + return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); + } + } + } +} diff --git a/Bloxstrap/NativeMethods.cs b/Bloxstrap/Utility/NativeMethods.cs similarity index 91% rename from Bloxstrap/NativeMethods.cs rename to Bloxstrap/Utility/NativeMethods.cs index 7cf6981..f27c0e1 100644 --- a/Bloxstrap/NativeMethods.cs +++ b/Bloxstrap/Utility/NativeMethods.cs @@ -4,8 +4,8 @@ using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; - -namespace Bloxstrap + +namespace Bloxstrap.Utility { static class NativeMethods { diff --git a/Bloxstrap/Tools/SystemEvent.cs b/Bloxstrap/Utility/SystemEvent.cs similarity index 96% rename from Bloxstrap/Tools/SystemEvent.cs rename to Bloxstrap/Utility/SystemEvent.cs index 098dc63..05eb590 100644 --- a/Bloxstrap/Tools/SystemEvent.cs +++ b/Bloxstrap/Utility/SystemEvent.cs @@ -1,47 +1,47 @@ -/* - * Roblox Studio Mod Manager (ProjectSrc/Utility/SystemEvent.cs) - * MIT License - * Copyright (c) 2015-present MaximumADHD -*/ - -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace Bloxstrap.Tools -{ - public class SystemEvent : EventWaitHandle - { - public string Name { get; private set; } - - public SystemEvent(string name, bool init = false, EventResetMode mode = EventResetMode.AutoReset) : base(init, mode, name) - { - if (init) - Reset(); - else - Set(); - - Name = name; - } - - public override string ToString() - { - return Name; - } - - public Task WaitForEvent() - { - return Task.Run(WaitOne); - } - - public Task WaitForEvent(TimeSpan timeout, bool exitContext = false) - { - return Task.Run(() => WaitOne(timeout, exitContext)); - } - - public Task WaitForEvent(int millisecondsTimeout, bool exitContext = false) - { - return Task.Run(() => WaitOne(millisecondsTimeout, exitContext)); - } - } -} +/* + * Roblox Studio Mod Manager (ProjectSrc/Utility/SystemEvent.cs) + * MIT License + * Copyright (c) 2015-present MaximumADHD +*/ + +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Bloxstrap.Tools +{ + public class SystemEvent : EventWaitHandle + { + public string Name { get; private set; } + + public SystemEvent(string name, bool init = false, EventResetMode mode = EventResetMode.AutoReset) : base(init, mode, name) + { + if (init) + Reset(); + else + Set(); + + Name = name; + } + + public override string ToString() + { + return Name; + } + + public Task WaitForEvent() + { + return Task.Run(WaitOne); + } + + public Task WaitForEvent(TimeSpan timeout, bool exitContext = false) + { + return Task.Run(() => WaitOne(timeout, exitContext)); + } + + public Task WaitForEvent(int millisecondsTimeout, bool exitContext = false) + { + return Task.Run(() => WaitOne(millisecondsTimeout, exitContext)); + } + } +} diff --git a/Bloxstrap/WindowScaling.cs b/Bloxstrap/Utility/WindowScaling.cs similarity index 78% rename from Bloxstrap/WindowScaling.cs rename to Bloxstrap/Utility/WindowScaling.cs index 3908587..c75139e 100644 --- a/Bloxstrap/WindowScaling.cs +++ b/Bloxstrap/Utility/WindowScaling.cs @@ -1,34 +1,31 @@ -using System; -using System.Windows; -using System.Windows.Forms; - -namespace Bloxstrap -{ - public static class WindowScaling - { - public static double GetFactor() - { - return Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth; - } - - public static int GetScaledNumber(int number) - { - return (int)Math.Ceiling(number * GetFactor()); - } - - public static System.Drawing.Size GetScaledSize(System.Drawing.Size size) - { - return new System.Drawing.Size(GetScaledNumber(size.Width), GetScaledNumber(size.Height)); - } - - public static System.Drawing.Point GetScaledPoint(System.Drawing.Point point) - { - return new System.Drawing.Point(GetScaledNumber(point.X), GetScaledNumber(point.Y)); - } - - public static Padding GetScaledPadding(Padding padding) - { - return new Padding(GetScaledNumber(padding.Left), GetScaledNumber(padding.Top), GetScaledNumber(padding.Right), GetScaledNumber(padding.Bottom)); - } - } -} +using System; +using System.Windows; +using System.Windows.Forms; + +namespace Bloxstrap.Utility +{ + public static class WindowScaling + { + public static double ScaleFactor => Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth; + + public static int GetScaledNumber(int number) + { + return (int)Math.Ceiling(number * ScaleFactor); + } + + public static System.Drawing.Size GetScaledSize(System.Drawing.Size size) + { + return new System.Drawing.Size(GetScaledNumber(size.Width), GetScaledNumber(size.Height)); + } + + public static System.Drawing.Point GetScaledPoint(System.Drawing.Point point) + { + return new System.Drawing.Point(GetScaledNumber(point.X), GetScaledNumber(point.Y)); + } + + public static Padding GetScaledPadding(Padding padding) + { + return new Padding(GetScaledNumber(padding.Left), GetScaledNumber(padding.Top), GetScaledNumber(padding.Right), GetScaledNumber(padding.Bottom)); + } + } +}