diff --git a/src/Snap.Hutao/Snap.Hutao.Win32/NativeMethods.json b/src/Snap.Hutao/Snap.Hutao.Win32/NativeMethods.json
deleted file mode 100644
index b25812f1..00000000
--- a/src/Snap.Hutao/Snap.Hutao.Win32/NativeMethods.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "$schema": "https://raw.githubusercontent.com/microsoft/CsWin32/main/src/Microsoft.Windows.CsWin32/settings.schema.json",
- "allowMarshaling": true,
- "useSafeHandles": false,
- "comInterop": {
- "preserveSigMethods": [
- "IFileOpenDialog.Show",
- "IFileSaveDialog.Show"
- ]
- }
-}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao.Win32/NativeMethods.txt b/src/Snap.Hutao/Snap.Hutao.Win32/NativeMethods.txt
deleted file mode 100644
index 90723ffc..00000000
--- a/src/Snap.Hutao/Snap.Hutao.Win32/NativeMethods.txt
+++ /dev/null
@@ -1,117 +0,0 @@
-// ADVAPI32
-RegCloseKey
-RegOpenKeyExW
-RegNotifyChangeKeyValue
-
-// COMCTL32
-DefSubclassProc
-RemoveWindowSubclass
-SetWindowSubclass
-
-// DWMAPI
-DwmSetWindowAttribute
-
-// GDI32
-GetDeviceCaps
-
-// KERNEL32
-AllocConsole
-CloseHandle
-CreateEventW
-CreateRemoteThread
-FreeConsole
-GetConsoleMode
-GetModuleHandleW
-GetProcAddress
-GetStdHandle
-K32EnumProcessModules
-K32GetModuleBaseNameW
-K32GetModuleInformation
-ReadProcessMemory
-SetConsoleMode
-SetConsoleTitle
-SetEvent
-VirtualAlloc
-VirtualAllocEx
-VirtualFree
-VirtualFreeEx
-WaitForSingleObject
-WriteProcessMemory
-
-// OLE32
-CoCreateInstance
-CoWaitForMultipleObjects
-
-// SHELL32
-SHCreateItemFromParsingName
-
-// USER32
-AttachThreadInput
-FindWindowExW
-GetCursorPos
-GetDC
-GetDpiForWindow
-GetForegroundWindow
-GetWindowLongPtrW
-GetWindowPlacement
-GetWindowThreadProcessId
-ReleaseDC
-RegisterHotKey
-SendInput
-SetForegroundWindow
-SetWindowLongPtrW
-UnregisterHotKey
-
-// COM
-FileOpenDialog
-FileSaveDialog
-IFileOpenDialog
-IFileSaveDialog
-IPersistFile
-IShellLinkDataList
-IShellLinkW
-ShellLink
-SHELL_LINK_DATA_FLAGS
-
-// WinRT
-IMemoryBufferByteAccess
-
-// Macro
-HRESULT_FROM_WIN32
-
-// Const value
-INFINITE
-MAX_PATH
-WM_ERASEBKGND
-WM_GETMINMAXINFO
-WM_HOTKEY
-WM_NCRBUTTONDOWN
-WM_NCRBUTTONUP
-WM_NULL
-
-// HKEY
-HKEY_CLASSES_ROOT
-HKEY_CURRENT_CONFIG
-HKEY_CURRENT_USER
-HKEY_LOCAL_MACHINE
-HKEY_USERS
-
-// HRESULT
-E_FAIL
-RPC_E_WRONG_THREAD
-
-// System.Com
-CWMO_FLAGS
-
-// System.Registry
-REG_NOTIFY_FILTER
-
-// System.Threading
-LPTHREAD_START_ROUTINE
-
-// UI.Shell
-SLGP_FLAGS
-
-// UI.WindowsAndMessaging
-MINMAXINFO
-WINDOW_EX_STYLE
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao.Win32/PInvoke.cs b/src/Snap.Hutao/Snap.Hutao.Win32/PInvoke.cs
deleted file mode 100644
index a54fa034..00000000
--- a/src/Snap.Hutao/Snap.Hutao.Win32/PInvoke.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using Windows.Win32.Foundation;
-using Windows.Win32.System.Com;
-
-namespace Windows.Win32;
-
-internal static partial class PInvoke
-{
- ///
- internal static unsafe HRESULT CoCreateInstance(object? pUnkOuter, CLSCTX dwClsContext, out TInterface ppv)
- where TInterface : class
- {
- HRESULT hr = CoCreateInstance(typeof(TClass).GUID, pUnkOuter, dwClsContext, typeof(TInterface).GUID, out object o);
- ppv = (TInterface)o;
- return hr;
- }
-}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao.Win32/Snap.Hutao.Win32.csproj b/src/Snap.Hutao/Snap.Hutao.Win32/Snap.Hutao.Win32.csproj
deleted file mode 100644
index df2df533..00000000
--- a/src/Snap.Hutao/Snap.Hutao.Win32/Snap.Hutao.Win32.csproj
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
- net8.0-windows10.0.22621.0
- disable
- enable
- x64
-
-
-
-
-
-
-
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
diff --git a/src/Snap.Hutao/Snap.Hutao.Win32/StructMarshal.cs b/src/Snap.Hutao/Snap.Hutao.Win32/StructMarshal.cs
deleted file mode 100644
index 6225225f..00000000
--- a/src/Snap.Hutao/Snap.Hutao.Win32/StructMarshal.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) DGP Studio. All rights reserved.
-// Licensed under the MIT license.
-
-using System.Runtime.CompilerServices;
-using Windows.Win32.UI.WindowsAndMessaging;
-
-[assembly: InternalsVisibleTo("Snap.Hutao")]
-
-namespace Snap.Hutao.Win32;
-
-///
-/// 结构体封送
-///
-internal static class StructMarshal
-{
- ///
- /// 构造一个新的
- ///
- /// 新的实例
- public static unsafe WINDOWPLACEMENT WINDOWPLACEMENT()
- {
- return new() { length = unchecked((uint)sizeof(WINDOWPLACEMENT)) };
- }
-}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao.sln b/src/Snap.Hutao/Snap.Hutao.sln
index d888d68b..96dc94bc 100644
--- a/src/Snap.Hutao/Snap.Hutao.sln
+++ b/src/Snap.Hutao/Snap.Hutao.sln
@@ -13,8 +13,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Snap.Hutao.Test", "Snap.Hutao.Test\Snap.Hutao.Test.csproj", "{D691BA9F-904C-4229-87A5-E14F2EFF2F64}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Snap.Hutao.Win32", "Snap.Hutao.Win32\Snap.Hutao.Win32.csproj", "{0F7ABEB2-5107-4037-B9DC-84D288FB0801}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -67,32 +65,16 @@ Global
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Release|x64.Build.0 = Release|Any CPU
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Release|x86.ActiveCfg = Release|Any CPU
{D691BA9F-904C-4229-87A5-E14F2EFF2F64}.Release|x86.Build.0 = Release|Any CPU
- {0F7ABEB2-5107-4037-B9DC-84D288FB0801}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {0F7ABEB2-5107-4037-B9DC-84D288FB0801}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {0F7ABEB2-5107-4037-B9DC-84D288FB0801}.Debug|arm64.ActiveCfg = Debug|Any CPU
- {0F7ABEB2-5107-4037-B9DC-84D288FB0801}.Debug|arm64.Build.0 = Debug|Any CPU
- {0F7ABEB2-5107-4037-B9DC-84D288FB0801}.Debug|x64.ActiveCfg = Debug|Any CPU
- {0F7ABEB2-5107-4037-B9DC-84D288FB0801}.Debug|x64.Build.0 = Debug|Any CPU
- {0F7ABEB2-5107-4037-B9DC-84D288FB0801}.Debug|x86.ActiveCfg = Debug|Any CPU
- {0F7ABEB2-5107-4037-B9DC-84D288FB0801}.Debug|x86.Build.0 = Debug|Any CPU
- {0F7ABEB2-5107-4037-B9DC-84D288FB0801}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {0F7ABEB2-5107-4037-B9DC-84D288FB0801}.Release|Any CPU.Build.0 = Release|Any CPU
- {0F7ABEB2-5107-4037-B9DC-84D288FB0801}.Release|arm64.ActiveCfg = Release|Any CPU
- {0F7ABEB2-5107-4037-B9DC-84D288FB0801}.Release|arm64.Build.0 = Release|Any CPU
- {0F7ABEB2-5107-4037-B9DC-84D288FB0801}.Release|x64.ActiveCfg = Release|Any CPU
- {0F7ABEB2-5107-4037-B9DC-84D288FB0801}.Release|x64.Build.0 = Release|Any CPU
- {0F7ABEB2-5107-4037-B9DC-84D288FB0801}.Release|x86.ActiveCfg = Release|Any CPU
- {0F7ABEB2-5107-4037-B9DC-84D288FB0801}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
- RESX_Rules = {"EnabledRules":["StringFormat","WhiteSpaceLead","WhiteSpaceTail","PunctuationLead"]}
- RESX_ShowErrorsInErrorList = False
- RESX_SortFileContentOnSave = True
- SolutionGuid = {E4449B1C-0E6A-4D19-955E-1CA491656ABA}
- RESX_NeutralResourcesLanguage = zh-CN
RESX_AutoApplyExistingTranslations = False
+ RESX_NeutralResourcesLanguage = zh-CN
+ SolutionGuid = {E4449B1C-0E6A-4D19-955E-1CA491656ABA}
+ RESX_SortFileContentOnSave = True
+ RESX_ShowErrorsInErrorList = False
+ RESX_Rules = {"EnabledRules":["StringFormat","WhiteSpaceLead","WhiteSpaceTail","PunctuationLead"]}
EndGlobalSection
EndGlobal
diff --git a/src/Snap.Hutao/Snap.Hutao/App.xaml.cs b/src/Snap.Hutao/Snap.Hutao/App.xaml.cs
index 0f40c101..bfa9a750 100644
--- a/src/Snap.Hutao/Snap.Hutao/App.xaml.cs
+++ b/src/Snap.Hutao/Snap.Hutao/App.xaml.cs
@@ -50,7 +50,6 @@ public sealed partial class App : Application
{
// Load app resource
InitializeComponent();
-
activation = serviceProvider.GetRequiredService();
logger = serviceProvider.GetRequiredService>();
serviceProvider.GetRequiredService().Record(this);
diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Media/SoftwareBitmapExtension.cs b/src/Snap.Hutao/Snap.Hutao/Control/Media/SoftwareBitmapExtension.cs
index 09596e7c..190fcd6f 100644
--- a/src/Snap.Hutao/Snap.Hutao/Control/Media/SoftwareBitmapExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Control/Media/SoftwareBitmapExtension.cs
@@ -1,10 +1,9 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using Snap.Hutao.Win32.System.WinRT;
using Windows.Foundation;
using Windows.Graphics.Imaging;
-using Windows.Win32;
-using Windows.Win32.System.WinRT;
using WinRT;
namespace Snap.Hutao.Control.Media;
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/Http/DynamicProxy/DynamicHttpProxy.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/Http/DynamicProxy/DynamicHttpProxy.cs
index 3485479c..3cee1312 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/IO/Http/DynamicProxy/DynamicHttpProxy.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/Http/DynamicProxy/DynamicHttpProxy.cs
@@ -18,6 +18,7 @@ internal sealed partial class DynamicHttpProxy : IWebProxy, IDisposable
private IWebProxy innerProxy = default!;
+ [SuppressMessage("", "CA1810")]
static DynamicHttpProxy()
{
Type? systemProxyInfoType = typeof(System.Net.Http.SocketsHttpHandler).Assembly.GetType("System.Net.Http.SystemProxyInfo");
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppInstanceExtension.cs b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppInstanceExtension.cs
index d7f8b25c..9992994b 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppInstanceExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppInstanceExtension.cs
@@ -2,10 +2,11 @@
// Licensed under the MIT license.
using Microsoft.Windows.AppLifecycle;
-using Windows.Win32.Foundation;
-using Windows.Win32.Security;
-using Windows.Win32.System.Com;
-using static Windows.Win32.PInvoke;
+using Snap.Hutao.Win32.Foundation;
+using Snap.Hutao.Win32.System.Com;
+using static Snap.Hutao.Win32.ConstValues;
+using static Snap.Hutao.Win32.Kernel32;
+using static Snap.Hutao.Win32.Ole32;
namespace Snap.Hutao.Core.LifeCycle;
@@ -18,7 +19,7 @@ internal static class AppInstanceExtension
private static readonly WaitCallback RunActionWaitCallback = RunAction;
// Hold the reference here to prevent memory corruption.
- private static HANDLE redirectEventHandle = HANDLE.Null;
+ private static HANDLE redirectEventHandle;
///
/// 同步非阻塞重定向
@@ -27,19 +28,24 @@ internal static class AppInstanceExtension
/// 参数
public static unsafe void RedirectActivationTo(this AppInstance appInstance, AppActivationArguments args)
{
- redirectEventHandle = CreateEvent(default(SECURITY_ATTRIBUTES*), true, false, null);
-
- // use ThreadPool.UnsafeQueueUserWorkItem to cancel stacktrace
- // like ExecutionContext.SuppressFlow
- ThreadPool.UnsafeQueueUserWorkItem(RunActionWaitCallback, () =>
+ try
{
- appInstance.RedirectActivationToAsync(args).AsTask().Wait();
- SetEvent(redirectEventHandle);
- });
+ redirectEventHandle = CreateEventW(default, true, false, default);
- ReadOnlySpan handles = new(ref redirectEventHandle);
- CoWaitForMultipleObjects((uint)CWMO_FLAGS.CWMO_DEFAULT, INFINITE, handles, out uint _);
- CloseHandle(redirectEventHandle);
+ // use ThreadPool.UnsafeQueueUserWorkItem to cancel stacktrace
+ // like ExecutionContext.SuppressFlow
+ ThreadPool.UnsafeQueueUserWorkItem(RunActionWaitCallback, () =>
+ {
+ appInstance.RedirectActivationToAsync(args).AsTask().Wait();
+ SetEvent(redirectEventHandle);
+ });
+
+ CoWaitForMultipleObjects((uint)CWMO_FLAGS.CWMO_DEFAULT, INFINITE, [redirectEventHandle], out uint _);
+ }
+ finally
+ {
+ CloseHandle(redirectEventHandle);
+ }
}
[SuppressMessage("", "SH007")]
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/CurrentWindowReferenceExtension.cs b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/CurrentWindowReferenceExtension.cs
index 47d674cf..ab424676 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/CurrentWindowReferenceExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/CurrentWindowReferenceExtension.cs
@@ -3,7 +3,7 @@
using Microsoft.UI.Xaml;
using Snap.Hutao.Core.Windowing;
-using Windows.Win32.Foundation;
+using Snap.Hutao.Win32.Foundation;
using WinRT.Interop;
namespace Snap.Hutao.Core.LifeCycle;
@@ -19,6 +19,6 @@ internal static class CurrentWindowReferenceExtension
{
return reference.Window is IWindowOptionsSource optionsSource
? optionsSource.WindowOptions.Hwnd
- : (HWND)WindowNative.GetWindowHandle(reference.Window);
+ : WindowNative.GetWindowHandle(reference.Window);
}
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Logging/ConsoleWindowLifeTime.cs b/src/Snap.Hutao/Snap.Hutao/Core/Logging/ConsoleWindowLifeTime.cs
index c00607ff..d40544eb 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Logging/ConsoleWindowLifeTime.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Logging/ConsoleWindowLifeTime.cs
@@ -2,9 +2,9 @@
// Licensed under the MIT license.
using Snap.Hutao.Core.Setting;
-using Windows.Win32.Foundation;
-using Windows.Win32.System.Console;
-using static Windows.Win32.PInvoke;
+using Snap.Hutao.Win32.Foundation;
+using Snap.Hutao.Win32.System.Console;
+using static Snap.Hutao.Win32.Kernel32;
namespace Snap.Hutao.Core.Logging;
@@ -26,7 +26,7 @@ internal sealed class ConsoleWindowLifeTime : IDisposable
SetConsoleMode(inputHandle, mode);
}
- SetConsoleTitle("Snap Hutao Debug Console");
+ SetConsoleTitleW("Snap Hutao Debug Console");
}
}
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Shell/ShellLinkInterop.cs b/src/Snap.Hutao/Snap.Hutao/Core/Shell/ShellLinkInterop.cs
index 12fd5256..ae04f288 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Shell/ShellLinkInterop.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Shell/ShellLinkInterop.cs
@@ -1,15 +1,14 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using Snap.Hutao.Win32.Foundation;
+using Snap.Hutao.Win32.System.Com;
+using Snap.Hutao.Win32.UI.Shell;
+using Snap.Hutao.Win32.UI.WindowsAndMessaging;
using System.IO;
-using System.Runtime.InteropServices;
using Windows.Storage;
-using Windows.Win32;
-using Windows.Win32.Foundation;
-using Windows.Win32.System.Com;
-using Windows.Win32.UI.Shell;
-using Windows.Win32.UI.WindowsAndMessaging;
-using static Windows.Win32.PInvoke;
+using static Snap.Hutao.Win32.Macros;
+using static Snap.Hutao.Win32.Ole32;
namespace Snap.Hutao.Core.Shell;
@@ -34,31 +33,44 @@ internal sealed partial class ShellLinkInterop : IShellLinkInterop
return false;
}
- HRESULT result = CoCreateInstance(null, CLSCTX.CLSCTX_INPROC_SERVER, out IShellLinkW shellLink);
- Marshal.ThrowExceptionForHR(result);
+ return UnsafeTryCreateDesktopShoutcutForElevatedLaunch(targetLogoPath);
+ }
- shellLink.SetPath($"shell:AppsFolder\\{runtimeOptions.FamilyName}!App");
- shellLink.SetShowCmd(SHOW_WINDOW_CMD.SW_NORMAL);
- shellLink.SetIconLocation(targetLogoPath, 0);
+ private unsafe bool UnsafeTryCreateDesktopShoutcutForElevatedLaunch(string targetLogoPath)
+ {
+ bool result = false;
- IShellLinkDataList shellLinkDataList = (IShellLinkDataList)shellLink;
- shellLinkDataList.GetFlags(out uint flags);
- flags |= (uint)SHELL_LINK_DATA_FLAGS.SLDF_RUNAS_USER;
- shellLinkDataList.SetFlags(flags);
-
- string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
- string target = Path.Combine(desktop, $"{SH.FormatAppNameAndVersion(runtimeOptions.Version)}.lnk");
-
- IPersistFile persistFile = (IPersistFile)shellLink;
- try
+ // DO NOT revert if condition, COM interfaces need to be released properly
+ HRESULT hr = CoCreateInstance(ref ShellLink.CLSID, default, CLSCTX.CLSCTX_INPROC_SERVER, ref IShellLinkW.IID, out IShellLinkW* pShellLink);
+ if (SUCCEEDED(hr))
{
- persistFile.Save(target, false);
- }
- catch (UnauthorizedAccessException)
- {
- return false;
+ pShellLink->SetPath($"shell:AppsFolder\\{runtimeOptions.FamilyName}!App");
+ pShellLink->SetShowCmd(SHOW_WINDOW_CMD.SW_NORMAL);
+ pShellLink->SetIconLocation(targetLogoPath, 0);
+
+ if (SUCCEEDED(pShellLink->QueryInterface(ref IShellLinkDataList.IID, out IShellLinkDataList* pShellLinkDataList)))
+ {
+ pShellLinkDataList->GetFlags(out uint flags);
+ pShellLinkDataList->SetFlags(flags | (uint)SHELL_LINK_DATA_FLAGS.SLDF_RUNAS_USER);
+ pShellLinkDataList->Release();
+ }
+
+ if (SUCCEEDED(pShellLink->QueryInterface(ref IPersistFile.IID, out IPersistFile* pPersistFile)))
+ {
+ string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
+ string target = Path.Combine(desktop, $"{SH.FormatAppNameAndVersion(runtimeOptions.Version)}.lnk");
+
+ if (SUCCEEDED(pPersistFile->Save(target, false)))
+ {
+ result = true;
+ }
+
+ pPersistFile->Release();
+ }
+
+ pShellLink->Release();
}
- return true;
+ return result;
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/HotKey/HotKeyCombination.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/HotKey/HotKeyCombination.cs
index 62b0eb44..eddc9fd7 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/HotKey/HotKeyCombination.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/HotKey/HotKeyCombination.cs
@@ -5,11 +5,11 @@ using CommunityToolkit.Mvvm.ComponentModel;
using Snap.Hutao.Core.LifeCycle;
using Snap.Hutao.Core.Setting;
using Snap.Hutao.Model;
+using Snap.Hutao.Win32.Foundation;
+using Snap.Hutao.Win32.UI.Input.KeyboardAndMouse;
using System.Text;
using Windows.System;
-using Windows.Win32.Foundation;
-using Windows.Win32.UI.Input.KeyboardAndMouse;
-using static Windows.Win32.PInvoke;
+using static Snap.Hutao.Win32.User32;
namespace Snap.Hutao.Core.Windowing.HotKey;
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/HotKey/HotKeyController.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/HotKey/HotKeyController.cs
index ffb070e6..c8fd4c78 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/HotKey/HotKeyController.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/HotKey/HotKeyController.cs
@@ -1,9 +1,9 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using Snap.Hutao.Win32.UI.Input.KeyboardAndMouse;
using System.Runtime.InteropServices;
-using Windows.Win32.UI.Input.KeyboardAndMouse;
-using static Windows.Win32.PInvoke;
+using static Snap.Hutao.Win32.User32;
namespace Snap.Hutao.Core.Windowing.HotKey;
@@ -14,7 +14,7 @@ internal sealed partial class HotKeyController : IHotKeyController
{
private static readonly WaitCallback RunMouseClickRepeatForever = MouseClickRepeatForever;
- private readonly object locker = new();
+ private readonly object syncRoot = new();
private readonly HotKeyOptions hotKeyOptions;
@@ -75,7 +75,7 @@ internal sealed partial class HotKeyController : IHotKeyController
private void ToggleMouseClickRepeatForever()
{
- lock (locker)
+ lock (syncRoot)
{
if (hotKeyOptions.IsMouseClickRepeatForeverOn)
{
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/HotKey/HotKeyParameter.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/HotKey/HotKeyParameter.cs
index 69a6b7d4..74207349 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/HotKey/HotKeyParameter.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/HotKey/HotKeyParameter.cs
@@ -1,8 +1,8 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using Snap.Hutao.Win32.UI.Input.KeyboardAndMouse;
using Windows.System;
-using Windows.Win32.UI.Input.KeyboardAndMouse;
namespace Snap.Hutao.Core.Windowing.HotKey;
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/IMinMaxInfoHandler.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/IMinMaxInfoHandler.cs
index eee91675..0d447049 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/IMinMaxInfoHandler.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/IMinMaxInfoHandler.cs
@@ -1,7 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
-using Windows.Win32.UI.WindowsAndMessaging;
+using Snap.Hutao.Win32.UI.WindowsAndMessaging;
namespace Snap.Hutao.Core.Windowing;
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowController.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowController.cs
index e0175d73..5d3d9c3b 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowController.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowController.cs
@@ -9,13 +9,14 @@ using Microsoft.UI.Xaml.Media;
using Snap.Hutao.Core.LifeCycle;
using Snap.Hutao.Core.Setting;
using Snap.Hutao.Service;
+using Snap.Hutao.Win32.Foundation;
+using Snap.Hutao.Win32.Graphics.Dwm;
+using Snap.Hutao.Win32.UI.WindowsAndMessaging;
using System.IO;
using Windows.Graphics;
using Windows.UI;
-using Windows.Win32.Foundation;
-using Windows.Win32.Graphics.Dwm;
-using Windows.Win32.UI.WindowsAndMessaging;
-using static Windows.Win32.PInvoke;
+using static Snap.Hutao.Win32.DwmApi;
+using static Snap.Hutao.Win32.User32;
namespace Snap.Hutao.Core.Windowing;
@@ -104,7 +105,7 @@ internal sealed class WindowController
return;
}
- WINDOWPLACEMENT windowPlacement = Win32.StructMarshal.WINDOWPLACEMENT();
+ WINDOWPLACEMENT windowPlacement = WINDOWPLACEMENT.Create();
GetWindowPlacement(options.Hwnd, ref windowPlacement);
// prevent save value when we are maximized.
@@ -194,7 +195,7 @@ internal sealed class WindowController
private unsafe void UpdateImmersiveDarkMode(FrameworkElement titleBar, object discard)
{
BOOL isDarkMode = Control.Theme.ThemeHelper.IsDarkMode(titleBar.ActualTheme);
- DwmSetWindowAttribute(options.Hwnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, &isDarkMode, unchecked((uint)sizeof(BOOL)));
+ DwmSetWindowAttribute(options.Hwnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, ref isDarkMode);
}
private void UpdateDragRectangles()
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowExtension.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowExtension.cs
index 97f41793..fec7d2f7 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowExtension.cs
@@ -2,11 +2,11 @@
// Licensed under the MIT license.
using Microsoft.UI.Xaml;
+using Snap.Hutao.Win32.Foundation;
+using Snap.Hutao.Win32.UI.WindowsAndMessaging;
using System.Runtime.CompilerServices;
-using Windows.Win32.Foundation;
-using Windows.Win32.UI.WindowsAndMessaging;
using WinRT.Interop;
-using static Windows.Win32.PInvoke;
+using static Snap.Hutao.Win32.User32;
namespace Snap.Hutao.Core.Windowing;
@@ -24,8 +24,8 @@ internal static class WindowExtension
public static void SetLayeredWindow(this Window window)
{
HWND hwnd = (HWND)WindowNative.GetWindowHandle(window);
- nint style = GetWindowLongPtr(hwnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE);
+ nint style = GetWindowLongPtrW(hwnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE);
style |= (nint)WINDOW_EX_STYLE.WS_EX_LAYERED;
- SetWindowLongPtr(hwnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, style);
+ SetWindowLongPtrW(hwnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, style);
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowOptions.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowOptions.cs
index 698bedf7..d65b4aa2 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowOptions.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowOptions.cs
@@ -4,10 +4,10 @@
using Microsoft.UI.Input;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
+using Snap.Hutao.Win32.Foundation;
using Windows.Graphics;
-using Windows.Win32.Foundation;
using WinRT.Interop;
-using static Windows.Win32.PInvoke;
+using static Snap.Hutao.Win32.User32;
namespace Snap.Hutao.Core.Windowing;
@@ -55,7 +55,7 @@ internal readonly struct WindowOptions
/// 持久化尺寸
public WindowOptions(Window window, FrameworkElement titleBar, SizeInt32 initSize, bool persistSize = false)
{
- Hwnd = (HWND)WindowNative.GetWindowHandle(window);
+ Hwnd = WindowNative.GetWindowHandle(window);
InputNonClientPointerSource = InputNonClientPointerSource.GetForWindowId(window.AppWindow.Id);
TitleBar = titleBar;
InitSize = initSize;
@@ -80,8 +80,8 @@ internal readonly struct WindowOptions
{
HWND fgHwnd = GetForegroundWindow();
- uint threadIdHwnd = GetWindowThreadProcessId(Hwnd);
- uint threadIdFgHwnd = GetWindowThreadProcessId(fgHwnd);
+ uint threadIdHwnd = GetWindowThreadProcessId(Hwnd, default);
+ uint threadIdFgHwnd = GetWindowThreadProcessId(fgHwnd, default);
if (threadIdHwnd != threadIdFgHwnd)
{
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowSubclass.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowSubclass.cs
index 4b12b05c..862cd1be 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowSubclass.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowSubclass.cs
@@ -4,10 +4,13 @@
using Microsoft.UI.Xaml;
using Snap.Hutao.Core.Windowing.Backdrop;
using Snap.Hutao.Core.Windowing.HotKey;
-using Windows.Win32.Foundation;
-using Windows.Win32.UI.Shell;
-using Windows.Win32.UI.WindowsAndMessaging;
-using static Windows.Win32.PInvoke;
+using Snap.Hutao.Win32.Foundation;
+using Snap.Hutao.Win32.UI.Shell;
+using Snap.Hutao.Win32.UI.WindowsAndMessaging;
+using System.Runtime.InteropServices;
+using static Snap.Hutao.Win32.ComCtl32;
+using static Snap.Hutao.Win32.ConstValues;
+using static Snap.Hutao.Win32.User32;
namespace Snap.Hutao.Core.Windowing;
@@ -26,8 +29,8 @@ internal sealed class WindowSubclass : IDisposable
private readonly IHotKeyController hotKeyController;
// We have to explicitly hold a reference to SUBCLASSPROC
- private SUBCLASSPROC? windowProc;
- private SUBCLASSPROC? legacyDragBarProc;
+ private SUBCLASSPROC windowProc = default!;
+ private SUBCLASSPROC legacyDragBarProc = default!;
public WindowSubclass(Window window, in WindowOptions options, IServiceProvider serviceProvider)
{
@@ -57,7 +60,7 @@ internal sealed class WindowSubclass : IDisposable
}
titleBarHooked = false;
- HWND hwndDragBar = FindWindowEx(options.Hwnd, default, "DRAG_BAR_WINDOW_CLASS", default);
+ HWND hwndDragBar = FindWindowExW(options.Hwnd, default, "DRAG_BAR_WINDOW_CLASS", default);
if (hwndDragBar.IsNull)
{
@@ -76,12 +79,12 @@ internal sealed class WindowSubclass : IDisposable
hotKeyController.UnregisterAll();
RemoveWindowSubclass(options.Hwnd, windowProc, WindowSubclassId);
- windowProc = null;
+ windowProc = default!;
if (options.UseLegacyDragBarImplementation)
{
RemoveWindowSubclass(options.Hwnd, legacyDragBarProc, DragBarSubclassId);
- legacyDragBarProc = null;
+ legacyDragBarProc = default!;
}
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Factory/Picker/FileSystemPickerInteraction.cs b/src/Snap.Hutao/Snap.Hutao/Factory/Picker/FileSystemPickerInteraction.cs
index 1c97aebf..58310359 100644
--- a/src/Snap.Hutao/Snap.Hutao/Factory/Picker/FileSystemPickerInteraction.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Factory/Picker/FileSystemPickerInteraction.cs
@@ -3,13 +3,14 @@
using Snap.Hutao.Core.IO;
using Snap.Hutao.Core.LifeCycle;
+using Snap.Hutao.Win32.Foundation;
+using Snap.Hutao.Win32.System.Com;
+using Snap.Hutao.Win32.UI.Shell;
+using Snap.Hutao.Win32.UI.Shell.Common;
using System.Runtime.InteropServices;
-using Windows.Win32;
-using Windows.Win32.Foundation;
-using Windows.Win32.System.Com;
-using Windows.Win32.UI.Shell;
-using Windows.Win32.UI.Shell.Common;
-using static Windows.Win32.PInvoke;
+using static Snap.Hutao.Win32.Macros;
+using static Snap.Hutao.Win32.Ole32;
+using static Snap.Hutao.Win32.Shell32;
namespace Snap.Hutao.Factory.Picker;
@@ -21,32 +22,33 @@ internal sealed partial class FileSystemPickerInteraction : IFileSystemPickerInt
public unsafe ValueResult PickFile(string? title, string? defaultFileName, (string Name, string Type)[]? filters)
{
- CoCreateInstance(default, CLSCTX.CLSCTX_INPROC_SERVER, out IFileOpenDialog dialog).ThrowOnFailure();
+ HRESULT hr = CoCreateInstance(ref FileOpenDialog.CLSID, default, CLSCTX.CLSCTX_INPROC_SERVER, ref IFileDialog.IID, out IFileDialog* pFileDialog);
+ Marshal.ThrowExceptionForHR(hr);
FILEOPENDIALOGOPTIONS options =
FILEOPENDIALOGOPTIONS.FOS_NOTESTFILECREATE |
FILEOPENDIALOGOPTIONS.FOS_FORCEFILESYSTEM |
FILEOPENDIALOGOPTIONS.FOS_NOCHANGEDIR;
- dialog.SetOptions(options);
- SetDesktopAsStartupFolder(dialog);
-
- if (!string.IsNullOrEmpty(title))
- {
- dialog.SetTitle(title);
- }
+ pFileDialog->SetOptions(options);
+ SetDesktopAsStartupFolder(pFileDialog);
if (!string.IsNullOrEmpty(defaultFileName))
{
- dialog.SetFileName(defaultFileName);
+ pFileDialog->SetFileName(defaultFileName);
+ }
+
+ if (!string.IsNullOrEmpty(title))
+ {
+ pFileDialog->SetTitle(title);
}
if (filters is { Length: > 0 })
{
- SetFileTypes(dialog, filters);
+ SetFileTypes(pFileDialog, filters);
}
- HRESULT res = dialog.Show(currentWindowReference.GetWindowHandle());
+ HRESULT res = pFileDialog->Show(currentWindowReference.GetWindowHandle());
if (res == HRESULT_FROM_WIN32(WIN32_ERROR.ERROR_CANCELLED))
{
return new(false, default);
@@ -56,18 +58,18 @@ internal sealed partial class FileSystemPickerInteraction : IFileSystemPickerInt
Marshal.ThrowExceptionForHR(res);
}
- dialog.GetResult(out IShellItem item);
+ HRESULT t = pFileDialog->GetResult(out IShellItem* pShellItem);
PWSTR displayName = default;
string file;
try
{
- item.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out displayName);
- file = new((char*)displayName);
+ pShellItem->GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out displayName);
+ file = new(displayName);
}
finally
{
- Marshal.FreeCoTaskMem((nint)displayName.Value);
+ CoTaskMemFree(displayName);
}
return new(true, file);
@@ -75,7 +77,8 @@ internal sealed partial class FileSystemPickerInteraction : IFileSystemPickerInt
public unsafe ValueResult SaveFile(string? title, string? defaultFileName, (string Name, string Type)[]? filters)
{
- CoCreateInstance(default, CLSCTX.CLSCTX_INPROC_SERVER, out IFileSaveDialog dialog).ThrowOnFailure();
+ HRESULT hr = CoCreateInstance(ref FileSaveDialog.CLSID, default, CLSCTX.CLSCTX_INPROC_SERVER, ref IFileDialog.IID, out IFileDialog* pFileDialog);
+ Marshal.ThrowExceptionForHR(hr);
FILEOPENDIALOGOPTIONS options =
FILEOPENDIALOGOPTIONS.FOS_NOTESTFILECREATE |
@@ -83,25 +86,25 @@ internal sealed partial class FileSystemPickerInteraction : IFileSystemPickerInt
FILEOPENDIALOGOPTIONS.FOS_STRICTFILETYPES |
FILEOPENDIALOGOPTIONS.FOS_NOCHANGEDIR;
- dialog.SetOptions(options);
- SetDesktopAsStartupFolder(dialog);
-
- if (!string.IsNullOrEmpty(title))
- {
- dialog.SetTitle(title);
- }
+ pFileDialog->SetOptions(options);
+ SetDesktopAsStartupFolder(pFileDialog);
if (!string.IsNullOrEmpty(defaultFileName))
{
- dialog.SetFileName(defaultFileName);
+ pFileDialog->SetFileName(defaultFileName);
+ }
+
+ if (!string.IsNullOrEmpty(title))
+ {
+ pFileDialog->SetTitle(title);
}
if (filters is { Length: > 0 })
{
- SetFileTypes(dialog, filters);
+ SetFileTypes(pFileDialog, filters);
}
- HRESULT res = dialog.Show(currentWindowReference.GetWindowHandle());
+ HRESULT res = pFileDialog->Show(currentWindowReference.GetWindowHandle());
if (res == HRESULT_FROM_WIN32(WIN32_ERROR.ERROR_CANCELLED))
{
return new(false, default);
@@ -111,18 +114,18 @@ internal sealed partial class FileSystemPickerInteraction : IFileSystemPickerInt
Marshal.ThrowExceptionForHR(res);
}
- dialog.GetResult(out IShellItem item);
+ pFileDialog->GetResult(out IShellItem* pShellItem);
PWSTR displayName = default;
string file;
try
{
- item.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out displayName);
- file = new((char*)displayName);
+ pShellItem->GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out displayName);
+ file = new(displayName);
}
finally
{
- Marshal.FreeCoTaskMem((nint)displayName.Value);
+ CoTaskMemFree(displayName);
}
return new(true, file);
@@ -130,7 +133,8 @@ internal sealed partial class FileSystemPickerInteraction : IFileSystemPickerInt
public unsafe ValueResult PickFolder(string? title)
{
- CoCreateInstance(default, CLSCTX.CLSCTX_INPROC_SERVER, out IFileOpenDialog dialog).ThrowOnFailure();
+ HRESULT hr = CoCreateInstance(ref FileOpenDialog.CLSID, default, CLSCTX.CLSCTX_INPROC_SERVER, ref IFileDialog.IID, out IFileDialog* pFileDialog);
+ Marshal.ThrowExceptionForHR(hr);
FILEOPENDIALOGOPTIONS options =
FILEOPENDIALOGOPTIONS.FOS_NOTESTFILECREATE |
@@ -138,15 +142,15 @@ internal sealed partial class FileSystemPickerInteraction : IFileSystemPickerInt
FILEOPENDIALOGOPTIONS.FOS_PICKFOLDERS |
FILEOPENDIALOGOPTIONS.FOS_NOCHANGEDIR;
- dialog.SetOptions(options);
- SetDesktopAsStartupFolder(dialog);
+ pFileDialog->SetOptions(options);
+ SetDesktopAsStartupFolder(pFileDialog);
if (!string.IsNullOrEmpty(title))
{
- dialog.SetTitle(title);
+ pFileDialog->SetTitle(title);
}
- HRESULT res = dialog.Show(currentWindowReference.GetWindowHandle());
+ HRESULT res = pFileDialog->Show(currentWindowReference.GetWindowHandle());
if (res == HRESULT_FROM_WIN32(WIN32_ERROR.ERROR_CANCELLED))
{
return new(false, default!);
@@ -156,25 +160,24 @@ internal sealed partial class FileSystemPickerInteraction : IFileSystemPickerInt
Marshal.ThrowExceptionForHR(res);
}
- dialog.GetResult(out IShellItem item);
+ pFileDialog->GetResult(out IShellItem* pShellItem);
PWSTR displayName = default;
string file;
try
{
- item.GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out displayName);
+ pShellItem->GetDisplayName(SIGDN.SIGDN_FILESYSPATH, out displayName);
file = new((char*)displayName);
}
finally
{
- Marshal.FreeCoTaskMem((nint)displayName.Value);
+ CoTaskMemFree(displayName);
}
return new(true, file);
}
- private static unsafe void SetFileTypes(TDialog dialog, (string Name, string Type)[] filters)
- where TDialog : IFileDialog
+ private static unsafe void SetFileTypes(IFileDialog* pFileDialog, (string Name, string Type)[] filters)
{
List unmanagedStringPtrs = new(filters.Length * 2);
List filterSpecs = new(filters.Length);
@@ -190,10 +193,7 @@ internal sealed partial class FileSystemPickerInteraction : IFileSystemPickerInt
filterSpecs.Add(spec);
}
- fixed (COMDLG_FILTERSPEC* ptr = CollectionsMarshal.AsSpan(filterSpecs))
- {
- dialog.SetFileTypes((uint)filterSpecs.Count, ptr);
- }
+ pFileDialog->SetFileTypes(CollectionsMarshal.AsSpan(filterSpecs));
foreach (ref readonly nint ptr in CollectionsMarshal.AsSpan(unmanagedStringPtrs))
{
@@ -201,11 +201,11 @@ internal sealed partial class FileSystemPickerInteraction : IFileSystemPickerInt
}
}
- private static unsafe void SetDesktopAsStartupFolder(TDialog dialog)
- where TDialog : IFileDialog
+ private static unsafe void SetDesktopAsStartupFolder(IFileDialog* pFileDialog)
{
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
- SHCreateItemFromParsingName(desktopPath, default, typeof(IShellItem).GUID, out object shellItem).ThrowOnFailure();
- dialog.SetFolder((IShellItem)shellItem);
+ HRESULT hr = SHCreateItemFromParsingName(desktopPath, default, ref IShellItem.IID, out IShellItem* pShellItem);
+ Marshal.ThrowExceptionForHR(hr);
+ pFileDialog->SetFolder(pShellItem);
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/GuideWindow.xaml.cs b/src/Snap.Hutao/Snap.Hutao/GuideWindow.xaml.cs
index 82122e58..e168639b 100644
--- a/src/Snap.Hutao/Snap.Hutao/GuideWindow.xaml.cs
+++ b/src/Snap.Hutao/Snap.Hutao/GuideWindow.xaml.cs
@@ -3,7 +3,7 @@
using Microsoft.UI.Xaml;
using Snap.Hutao.Core.Windowing;
-using Windows.Win32.UI.WindowsAndMessaging;
+using Snap.Hutao.Win32.UI.WindowsAndMessaging;
namespace Snap.Hutao;
@@ -32,9 +32,9 @@ internal sealed partial class GuideWindow : Window, IWindowOptionsSource, IMinMa
public unsafe void HandleMinMaxInfo(ref MINMAXINFO info, double scalingFactor)
{
- info.ptMinTrackSize.X = (int)Math.Max(MinWidth * scalingFactor, info.ptMinTrackSize.X);
- info.ptMinTrackSize.Y = (int)Math.Max(MinHeight * scalingFactor, info.ptMinTrackSize.Y);
- info.ptMaxTrackSize.X = (int)Math.Min(MaxWidth * scalingFactor, info.ptMaxTrackSize.X);
- info.ptMaxTrackSize.Y = (int)Math.Min(MaxHeight * scalingFactor, info.ptMaxTrackSize.Y);
+ info.ptMinTrackSize.x = (int)Math.Max(MinWidth * scalingFactor, info.ptMinTrackSize.x);
+ info.ptMinTrackSize.y = (int)Math.Max(MinHeight * scalingFactor, info.ptMinTrackSize.y);
+ info.ptMaxTrackSize.x = (int)Math.Min(MaxWidth * scalingFactor, info.ptMaxTrackSize.x);
+ info.ptMaxTrackSize.y = (int)Math.Min(MaxHeight * scalingFactor, info.ptMaxTrackSize.y);
}
-}
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs b/src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs
index 43d75331..7143fa0e 100644
--- a/src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs
+++ b/src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs
@@ -4,7 +4,7 @@
using Microsoft.UI.Xaml;
using Snap.Hutao.Core.Windowing;
using Snap.Hutao.ViewModel.Game;
-using Windows.Win32.UI.WindowsAndMessaging;
+using Snap.Hutao.Win32.UI.WindowsAndMessaging;
namespace Snap.Hutao;
@@ -50,9 +50,9 @@ internal sealed partial class LaunchGameWindow : Window, IDisposable, IWindowOpt
///
public unsafe void HandleMinMaxInfo(ref MINMAXINFO info, double scalingFactor)
{
- info.ptMinTrackSize.X = (int)Math.Max(MinWidth * scalingFactor, info.ptMinTrackSize.X);
- info.ptMinTrackSize.Y = (int)Math.Max(MinHeight * scalingFactor, info.ptMinTrackSize.Y);
- info.ptMaxTrackSize.X = (int)Math.Min(MaxWidth * scalingFactor, info.ptMaxTrackSize.X);
- info.ptMaxTrackSize.Y = (int)Math.Min(MaxHeight * scalingFactor, info.ptMaxTrackSize.Y);
+ info.ptMinTrackSize.x = (int)Math.Max(MinWidth * scalingFactor, info.ptMinTrackSize.x);
+ info.ptMinTrackSize.y = (int)Math.Max(MinHeight * scalingFactor, info.ptMinTrackSize.y);
+ info.ptMaxTrackSize.x = (int)Math.Min(MaxWidth * scalingFactor, info.ptMaxTrackSize.x);
+ info.ptMaxTrackSize.y = (int)Math.Min(MaxHeight * scalingFactor, info.ptMaxTrackSize.y);
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs b/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs
index a59757e6..463bc5f4 100644
--- a/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs
+++ b/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs
@@ -3,7 +3,7 @@
using Microsoft.UI.Xaml;
using Snap.Hutao.Core.Windowing;
-using Windows.Win32.UI.WindowsAndMessaging;
+using Snap.Hutao.Win32.UI.WindowsAndMessaging;
namespace Snap.Hutao;
@@ -37,7 +37,7 @@ internal sealed partial class MainWindow : Window, IWindowOptionsSource, IMinMax
///
public unsafe void HandleMinMaxInfo(ref MINMAXINFO pInfo, double scalingFactor)
{
- pInfo.ptMinTrackSize.X = (int)Math.Max(MinWidth * scalingFactor, pInfo.ptMinTrackSize.X);
- pInfo.ptMinTrackSize.Y = (int)Math.Max(MinHeight * scalingFactor, pInfo.ptMinTrackSize.Y);
+ pInfo.ptMinTrackSize.x = (int)Math.Max(MinWidth * scalingFactor, pInfo.ptMinTrackSize.x);
+ pInfo.ptMinTrackSize.y = (int)Math.Max(MinHeight * scalingFactor, pInfo.ptMinTrackSize.y);
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs
index 95deb042..5b261631 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs
@@ -7,12 +7,12 @@ using Snap.Hutao.Model;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Service.Game.PathAbstraction;
+using Snap.Hutao.Win32.Graphics.Gdi;
using System.Collections.Immutable;
using System.Globalization;
using Windows.Graphics;
-using Windows.Win32.Foundation;
-using Windows.Win32.Graphics.Gdi;
-using static Windows.Win32.PInvoke;
+using static Snap.Hutao.Win32.Gdi32;
+using static Snap.Hutao.Win32.User32;
namespace Snap.Hutao.Service.Game;
@@ -82,12 +82,12 @@ internal sealed class LaunchOptions : DbStoreOptions
HDC hDC = default;
try
{
- hDC = GetDC(HWND.Null);
+ hDC = GetDC(default);
fps = GetDeviceCaps(hDC, GET_DEVICE_CAPS_INDEX.VREFRESH);
}
finally
{
- _ = ReleaseDC(HWND.Null, hDC);
+ _ = ReleaseDC(default, hDC);
}
}
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionGameProcessStartHandler.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionGameProcessStartHandler.cs
index 24fc23b4..30b6c736 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionGameProcessStartHandler.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionGameProcessStartHandler.cs
@@ -1,7 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
-using Windows.Win32.Foundation;
+using Snap.Hutao.Win32.Foundation;
namespace Snap.Hutao.Service.Game.Launching.Handler;
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs
index 1a6c8f65..2dc20ac2 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs
@@ -2,11 +2,11 @@
// Licensed under the MIT license.
using Snap.Hutao.Core.Diagnostics;
+using Snap.Hutao.Win32.Foundation;
using Snap.Hutao.Win32.Memory;
+using Snap.Hutao.Win32.System.ProcessStatus;
using System.Runtime.InteropServices;
-using Windows.Win32.Foundation;
-using Windows.Win32.System.ProcessStatus;
-using static Windows.Win32.PInvoke;
+using static Snap.Hutao.Win32.Kernel32;
namespace Snap.Hutao.Service.Game.Unlocker;
@@ -61,36 +61,29 @@ internal sealed class GameFpsUnlocker : IGameFpsUnlocker
ref readonly Module userAssembly = ref moduleEntryInfo.UserAssembly;
memory = new VirtualMemory(unityPlayer.Size + userAssembly.Size);
- byte* lpBuffer = (byte*)memory.Pointer;
- return ReadProcessMemory((HANDLE)process.Handle, (void*)unityPlayer.Address, lpBuffer, unityPlayer.Size)
- && ReadProcessMemory((HANDLE)process.Handle, (void*)userAssembly.Address, lpBuffer + unityPlayer.Size, userAssembly.Size);
+ return ReadProcessMemory(process.Handle, (void*)unityPlayer.Address, memory.AsSpan()[..(int)unityPlayer.Size], out _)
+ && ReadProcessMemory(process.Handle, (void*)userAssembly.Address, memory.AsSpan()[(int)unityPlayer.Size..], out _);
}
private static unsafe bool UnsafeReadProcessMemory(System.Diagnostics.Process process, nuint baseAddress, out nuint value)
{
- ulong temp = 0;
- bool result = ReadProcessMemory((HANDLE)process.Handle, (void*)baseAddress, (byte*)&temp, 8);
+ value = 0;
+ bool result = ReadProcessMemory((HANDLE)process.Handle, (void*)baseAddress, ref value, out _);
Verify.Operation(result, SH.ServiceGameUnlockerReadProcessMemoryPointerAddressFailed);
-
- value = (nuint)temp;
return result;
}
private static unsafe bool UnsafeWriteProcessMemory(System.Diagnostics.Process process, nuint baseAddress, int value)
{
- return WriteProcessMemory((HANDLE)process.Handle, (void*)baseAddress, &value, sizeof(int));
+ return WriteProcessMemory((HANDLE)process.Handle, (void*)baseAddress, ref value, out _);
}
private static unsafe FindModuleResult UnsafeTryFindModule(in HANDLE hProcess, in ReadOnlySpan moduleName, out Module module)
{
HMODULE[] buffer = new HMODULE[128];
- uint actualSize;
- fixed (HMODULE* pBuffer = buffer)
+ if (!K32EnumProcessModules(hProcess, buffer, out uint actualSize))
{
- if (!K32EnumProcessModules(hProcess, pBuffer, unchecked((uint)(buffer.Length * sizeof(HMODULE))), out actualSize))
- {
- Marshal.ThrowExceptionForHR(Marshal.GetLastPInvokeError());
- }
+ Marshal.ThrowExceptionForHR(Marshal.GetLastPInvokeError());
}
if (actualSize == 0)
@@ -99,18 +92,17 @@ internal sealed class GameFpsUnlocker : IGameFpsUnlocker
return FindModuleResult.NoModuleFound;
}
- Span modules = new(buffer, 0, unchecked((int)(actualSize / sizeof(HMODULE))));
-
- foreach (ref readonly HMODULE hModule in modules)
+ foreach (ref readonly HMODULE hModule in buffer.AsSpan()[..(int)(actualSize / sizeof(HMODULE))])
{
char[] baseName = new char[256];
+
+ if (K32GetModuleBaseNameW(hProcess, hModule, baseName) == 0)
+ {
+ continue;
+ }
+
fixed (char* lpBaseName = baseName)
{
- if (K32GetModuleBaseName(hProcess, hModule, lpBaseName, 256) == 0)
- {
- continue;
- }
-
ReadOnlySpan szModuleName = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(lpBaseName);
if (!szModuleName.SequenceEqual(moduleName))
{
@@ -118,7 +110,7 @@ internal sealed class GameFpsUnlocker : IGameFpsUnlocker
}
}
- if (!K32GetModuleInformation(hProcess, hModule, out MODULEINFO moduleInfo, unchecked((uint)sizeof(MODULEINFO))))
+ if (!K32GetModuleInformation(hProcess, hModule, out MODULEINFO moduleInfo))
{
continue;
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
index 63b4bc16..b3ccd68a 100644
--- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
+++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
@@ -334,9 +334,6 @@
-
-
-