diff --git a/src/Magpie/MainWindow.cpp b/src/Magpie/MainWindow.cpp index 642e5e5a..ec0c861a 100644 --- a/src/Magpie/MainWindow.cpp +++ b/src/Magpie/MainWindow.cpp @@ -49,10 +49,7 @@ bool MainWindow::Create() noexcept { _appThemeChangedRevoker = App::Get().ThemeChanged(winrt::auto_revoke, [this](bool) { _UpdateTheme(); }); _UpdateTheme(); - const bool isMaximized = AppSettings::Get().IsMainWindowMaximized(); - if (isMaximized) { - _SetInitialMaximized(); - } + _SetInitialMaximized(AppSettings::Get().IsMainWindowMaximized()); // 1. 设置初始 XAML Islands 窗口的尺寸 // 2. 刷新窗口边框 @@ -62,8 +59,8 @@ bool MainWindow::Create() noexcept { (sizeToSet.cx == 0 ? (SWP_NOMOVE | SWP_NOSIZE) : 0) | SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOCOPYBITS); // Xaml 控件加载完成后显示主窗口 - Content()->Loaded([this, isMaximized](winrt::IInspectable const&, winrt::RoutedEventArgs const&) { - if (isMaximized) { + Content()->Loaded([this](winrt::IInspectable const&, winrt::RoutedEventArgs const&) { + if (AppSettings::Get().IsMainWindowMaximized()) { // ShowWindow(Handle(), SW_SHOWMAXIMIZED) 会显示错误的动画。因此我们以窗口化显示, // 但位置和大小都和最大化相同,显示完毕后将状态设为最大化。 // @@ -79,20 +76,22 @@ bool MainWindow::Create() noexcept { GetMonitorInfo(hMon, &mi); // 播放窗口显示动画 - /*SetWindowPos( + SetWindowPos( Handle(), NULL, mi.rcWork.left, mi.rcWork.top, mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.bottom - mi.rcMonitor.top, - SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW - );*/ + SWP_SHOWWINDOW + ); } // 将状态设为最大化,也还原了原始的窗口化位置 wp.showCmd = SW_SHOWMAXIMIZED; SetWindowPlacement(Handle(), &wp); + + _SetInitialMaximized(false); } else { ShowWindow(Handle(), SW_SHOWNORMAL); } diff --git a/src/Magpie/XamlWindow.h b/src/Magpie/XamlWindow.h index 95ade92e..22e63e4f 100644 --- a/src/Magpie/XamlWindow.h +++ b/src/Magpie/XamlWindow.h @@ -78,10 +78,10 @@ class XamlWindowT : public WindowBaseT { return _isMaximized; } - // 窗口尚未显示无法最大化,通过这个方法设置 _isMaximized 使 XamlWindow 估计 XAML Islands 窗口尺寸。 - // 否则在显示窗口时可能会看到 NavigationView 的导航栏的展开动画。 - void _SetInitialMaximized() noexcept { - _isMaximized = true; + // 窗口尚未显示无法最大化,通过这个方法设置 _isMaximized 使 _UpdateIslandPosition 估计 + // XAML Islands 窗口尺寸。否则在显示窗口时可能会看到 NavigationView 的导航栏的展开动画。 + void _SetInitialMaximized(bool value) noexcept { + _isInitialMaximized = value; } void _SetTheme(bool isLightTheme) noexcept { @@ -149,7 +149,6 @@ class XamlWindowT : public WindowBaseT { } const HWND hWnd = this->Handle(); - _isWindowShown = IsWindowVisible(hWnd); NCCALCSIZE_PARAMS* params = (NCCALCSIZE_PARAMS*)lParam; RECT& clientRect = params->rgrc[0]; @@ -167,7 +166,7 @@ class XamlWindowT : public WindowBaseT { clientRect.top = originalTop; // WM_NCCALCSIZE 在 WM_SIZE 前 - _UpdateMaximizedState(); + _isMaximized = IsMaximized(hWnd); if (_isMaximized) { // 最大化的窗口的实际尺寸比屏幕的工作区更大一点,这是为了将可调整窗口大小的区域隐藏在屏幕外面 @@ -356,7 +355,7 @@ class XamlWindowT : public WindowBaseT { } case WM_SIZE: { - _UpdateMaximizedState(); + _isMaximized = IsMaximized(this->Handle()); if (wParam != SIZE_MINIMIZED) { _UpdateIslandPosition(LOWORD(lParam), HIWORD(lParam)); @@ -388,7 +387,6 @@ class XamlWindowT : public WindowBaseT { _hwndXamlIsland = NULL; _isMaximized = false; - _isWindowShown = false; _isLightTheme = true; _content = nullptr; @@ -428,10 +426,11 @@ class XamlWindowT : public WindowBaseT { private: void _UpdateIslandPosition(int width, int height) const noexcept { - if (!IsWindowVisible(this->Handle()) && _isMaximized) { - // 初始化过程中此函数会被调用两次。如果窗口以最大化显示,则两次传入的尺寸不一致。第一次 - // 调用此函数时主窗口尚未显示,因此无法最大化,我们必须估算最大化窗口的尺寸。不执行这个 - // 操作可能导致窗口显示时展示 NavigationView 导航展开的动画。 + // 当窗口以最大化显示时,为了修正动画,实际上是先窗口化显示然后改为最大化。这个过程中此函数 + // 会被调用多次,而且传入的尺寸不一致。我们想让 XAML Islands 窗口尺寸保持稳定以避免不必要 + // 的动画,因此需要估算最大化窗口的尺寸。 + // 由于没考虑自动隐藏的任务栏,计算结果可能不准确,但最多相差两个像素,可以接受。 + if (_isInitialMaximized && !_isMaximized) { if (HMONITOR hMon = MonitorFromWindow(this->Handle(), MONITOR_DEFAULTTONEAREST)) { MONITORINFO monInfo{}; monInfo.cbSize = sizeof(MONITORINFO); @@ -459,13 +458,6 @@ class XamlWindowT : public WindowBaseT { ); } - void _UpdateMaximizedState() noexcept { - // 如果窗口尚未显示,不碰 _isMaximized - if (_isWindowShown) { - _isMaximized = IsMaximized(this->Handle()); - } - } - void _UpdateFrameMargins() const noexcept { if (Win32Helper::GetOSVersion().IsWin11()) { return; @@ -519,7 +511,7 @@ class XamlWindowT : public WindowBaseT { uint32_t _nativeTopBorderHeight = 1; bool _isLightTheme = true; - bool _isWindowShown = false; + bool _isInitialMaximized = false; bool _isMaximized = false; };