diff --git a/src/Magpie/AdaptersService.cpp b/src/Magpie/AdaptersService.cpp new file mode 100644 index 00000000..ae7b0500 --- /dev/null +++ b/src/Magpie/AdaptersService.cpp @@ -0,0 +1,13 @@ +#include "pch.h" +#include "AdaptersService.h" + +namespace Magpie { + +bool Magpie::AdaptersService::Initialize() noexcept { + return false; +} + +void Magpie::AdaptersService::Uninitialize() noexcept { +} + +} diff --git a/src/Magpie/AdaptersService.h b/src/Magpie/AdaptersService.h new file mode 100644 index 00000000..d5d1364a --- /dev/null +++ b/src/Magpie/AdaptersService.h @@ -0,0 +1,23 @@ +#pragma once + +namespace Magpie { + +class AdaptersService { +public: + static AdaptersService& Get() noexcept { + static AdaptersService instance; + return instance; + } + + AdaptersService(const AdaptersService&) = delete; + AdaptersService(AdaptersService&&) = delete; + + bool Initialize() noexcept; + + void Uninitialize() noexcept; + +private: + AdaptersService() = default; +}; + +} diff --git a/src/Magpie/App.cpp b/src/Magpie/App.cpp index ea10040b..4c76cc42 100644 --- a/src/Magpie/App.cpp +++ b/src/Magpie/App.cpp @@ -38,6 +38,7 @@ #include "IsNullStateTrigger.h" #include "TextBlockHelper.h" #include "MainWindow.h" +#include "AdaptersService.h" using namespace ::Magpie; using namespace winrt; @@ -146,6 +147,7 @@ bool App::Initialize(const wchar_t* arguments) { if (settings.IsAlwaysRunAsAdmin() && !Win32Helper::IsProcessElevated()) { Restart(true, arguments); + _Uninitialize(); return false; } @@ -164,6 +166,10 @@ bool App::Initialize(const wchar_t* arguments) { LocalizationService::Get().Initialize(); ToastService::Get().Initialize(); + if (!AdaptersService::Get().Initialize()) { + _Uninitialize(); + return false; + } ShortcutService::Get().Initialize(); ScalingService::Get().Initialize(); UpdateService::Get().Initialize(); @@ -178,7 +184,7 @@ bool App::Initialize(const wchar_t* arguments) { // 不显示托盘图标时忽略 -t 参数 if (!notifyIconService.IsShow() || arguments != L"-t"sv) { if (!_mainWindow->Create()) { - Quit(); + _Uninitialize(); return false; } } @@ -249,10 +255,11 @@ const com_ptr& App::RootPage() const noexcept { void App::_Uninitialize() { NotifyIconService::Get().Uninitialize(); ScalingService::Get().Uninitialize(); - // 不显示托盘图标的情况下关闭主窗口仍会在后台驻留数秒,推测和 XAML Islands 有关。 - // 这里提前取消热键注册,这样关闭 Magpie 后立即重新打开不会注册热键失败。 + // 提前取消热键注册,这样关闭 Magpie 后立即重新打开不会注册热键失败 ShortcutService::Get().Uninitialize(); + AdaptersService::Get().Uninitialize(); ToastService::Get().Uninitialize(); + EffectsService::Get().Uninitialize(); _isShowNotifyIconChangedRevoker.Revoke(); _themeChangedRevoker.Revoke(); diff --git a/src/Magpie/EffectsService.cpp b/src/Magpie/EffectsService.cpp index 413a3483..5fd06644 100644 --- a/src/Magpie/EffectsService.cpp +++ b/src/Magpie/EffectsService.cpp @@ -99,6 +99,11 @@ fire_and_forget EffectsService::Initialize() { _initialized.notify_one(); } +void EffectsService::Uninitialize() { + // 等待解析完成,防止退出时崩溃 + _WaitForInitialize(); +} + const std::vector& EffectsService::Effects() noexcept { _WaitForInitialize(); return _effects; diff --git a/src/Magpie/EffectsService.h b/src/Magpie/EffectsService.h index 36e3b120..c9a4b6b7 100644 --- a/src/Magpie/EffectsService.h +++ b/src/Magpie/EffectsService.h @@ -37,6 +37,8 @@ class EffectsService { winrt::fire_and_forget Initialize(); + void Uninitialize(); + const std::vector& Effects() noexcept; const EffectInfo* GetEffect(std::wstring_view name) noexcept; diff --git a/src/Magpie/Magpie.vcxproj b/src/Magpie/Magpie.vcxproj index b61fcacb..290719fd 100644 --- a/src/Magpie/Magpie.vcxproj +++ b/src/Magpie/Magpie.vcxproj @@ -77,6 +77,7 @@ AboutViewModel.idl Code + @@ -260,6 +261,7 @@ AboutViewModel.idl Code + diff --git a/src/Magpie/Magpie.vcxproj.filters b/src/Magpie/Magpie.vcxproj.filters index 7198253c..5393e671 100644 --- a/src/Magpie/Magpie.vcxproj.filters +++ b/src/Magpie/Magpie.vcxproj.filters @@ -73,6 +73,9 @@ Helpers + + Services + @@ -154,6 +157,9 @@ Resources + + Services + diff --git a/src/Magpie/NotifyIconService.cpp b/src/Magpie/NotifyIconService.cpp index be78c755..18ebd98c 100644 --- a/src/Magpie/NotifyIconService.cpp +++ b/src/Magpie/NotifyIconService.cpp @@ -11,7 +11,7 @@ namespace Magpie { // 当任务栏被创建时会广播此消息。用于在资源管理器被重新启动时重新创建托盘图标 // https://learn.microsoft.com/en-us/windows/win32/shell/taskbar#taskbar-creation-notification -static UINT WM_TASKBARCREATED; +static UINT WM_TASKBARCREATED = 0; void NotifyIconService::Initialize() noexcept { WM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated"); @@ -23,7 +23,15 @@ void NotifyIconService::Initialize() noexcept { _nid.uID = 0; } +bool NotifyIconService::_IsInitialized() const noexcept { + return WM_TASKBARCREATED; +} + void NotifyIconService::Uninitialize() noexcept { + if (!_IsInitialized()) { + return; + } + IsShow(false); if (_nid.hWnd) { diff --git a/src/Magpie/NotifyIconService.h b/src/Magpie/NotifyIconService.h index cd59bb22..5270344a 100644 --- a/src/Magpie/NotifyIconService.h +++ b/src/Magpie/NotifyIconService.h @@ -13,12 +13,14 @@ class NotifyIconService { void Uninitialize() noexcept; void IsShow(bool value) noexcept; - bool IsShow() noexcept { + bool IsShow() const noexcept { // 返回 _shouldShow 而不是 _isShow,对外接口假设总是创建成功 return _shouldShow; } private: + bool _IsInitialized() const noexcept; + static LRESULT _NotifyIconWndProcStatic(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { return Get()._NotifyIconWndProc(hWnd, msg, wParam, lParam); } diff --git a/src/Magpie/ScalingService.cpp b/src/Magpie/ScalingService.cpp index f2077324..ff959f2c 100644 --- a/src/Magpie/ScalingService.cpp +++ b/src/Magpie/ScalingService.cpp @@ -52,7 +52,15 @@ void ScalingService::Initialize() { _CheckForegroundTimer_Tick(nullptr); } +bool ScalingService::_IsInitialized() const noexcept { + return (bool)_checkForegroundTimer; +} + void ScalingService::Uninitialize() { + if (!_IsInitialized()) { + return; + } + _checkForegroundTimer.Cancel(); _countDownTimer.Stop(); _scalingRuntime.reset(); diff --git a/src/Magpie/ScalingService.h b/src/Magpie/ScalingService.h index 6131a1d9..0e088b55 100644 --- a/src/Magpie/ScalingService.h +++ b/src/Magpie/ScalingService.h @@ -57,6 +57,8 @@ class ScalingService { private: ScalingService() = default; + bool _IsInitialized() const noexcept; + void _WndToRestore(HWND value); void _ShortcutService_ShortcutPressed(winrt::Magpie::ShortcutAction action); diff --git a/src/Magpie/ShortcutService.cpp b/src/Magpie/ShortcutService.cpp index 6ed8b372..8c2d895a 100644 --- a/src/Magpie/ShortcutService.cpp +++ b/src/Magpie/ShortcutService.cpp @@ -53,7 +53,15 @@ void ShortcutService::Initialize() { } } +bool ShortcutService::_IsInitialized() const noexcept { + return (bool)_hwndHotkey; +} + void ShortcutService::Uninitialize() { + if (!_IsInitialized()) { + return; + } + _keyboardHook.reset(); for (int i = 0; i < (int)ShortcutAction::COUNT_OR_NONE; ++i) { diff --git a/src/Magpie/ShortcutService.h b/src/Magpie/ShortcutService.h index 938af5aa..41ce19c6 100644 --- a/src/Magpie/ShortcutService.h +++ b/src/Magpie/ShortcutService.h @@ -35,6 +35,8 @@ class ShortcutService { private: ShortcutService() = default; + bool _IsInitialized() const noexcept; + static LRESULT _WndProcStatic(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { return Get()._WndProc(hWnd, msg, wParam, lParam); }