Skip to content

Commit

Permalink
fix: 优化最大化显示窗口逻辑
Browse files Browse the repository at this point in the history
  • Loading branch information
Blinue committed Dec 26, 2024
1 parent 033673b commit 1f82b73
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 29 deletions.
17 changes: 8 additions & 9 deletions src/Magpie/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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. 刷新窗口边框
Expand All @@ -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) 会显示错误的动画。因此我们以窗口化显示,
// 但位置和大小都和最大化相同,显示完毕后将状态设为最大化。
//
Expand All @@ -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);
}
Expand Down
32 changes: 12 additions & 20 deletions src/Magpie/XamlWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ class XamlWindowT : public WindowBaseT<T> {
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 {
Expand Down Expand Up @@ -149,7 +149,6 @@ class XamlWindowT : public WindowBaseT<T> {
}

const HWND hWnd = this->Handle();
_isWindowShown = IsWindowVisible(hWnd);

NCCALCSIZE_PARAMS* params = (NCCALCSIZE_PARAMS*)lParam;
RECT& clientRect = params->rgrc[0];
Expand All @@ -167,7 +166,7 @@ class XamlWindowT : public WindowBaseT<T> {
clientRect.top = originalTop;

// WM_NCCALCSIZE 在 WM_SIZE 前
_UpdateMaximizedState();
_isMaximized = IsMaximized(hWnd);

if (_isMaximized) {
// 最大化的窗口的实际尺寸比屏幕的工作区更大一点,这是为了将可调整窗口大小的区域隐藏在屏幕外面
Expand Down Expand Up @@ -356,7 +355,7 @@ class XamlWindowT : public WindowBaseT<T> {
}
case WM_SIZE:
{
_UpdateMaximizedState();
_isMaximized = IsMaximized(this->Handle());

if (wParam != SIZE_MINIMIZED) {
_UpdateIslandPosition(LOWORD(lParam), HIWORD(lParam));
Expand Down Expand Up @@ -388,7 +387,6 @@ class XamlWindowT : public WindowBaseT<T> {
_hwndXamlIsland = NULL;

_isMaximized = false;
_isWindowShown = false;
_isLightTheme = true;

_content = nullptr;
Expand Down Expand Up @@ -428,10 +426,11 @@ class XamlWindowT : public WindowBaseT<T> {

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);
Expand Down Expand Up @@ -459,13 +458,6 @@ class XamlWindowT : public WindowBaseT<T> {
);
}

void _UpdateMaximizedState() noexcept {
// 如果窗口尚未显示,不碰 _isMaximized
if (_isWindowShown) {
_isMaximized = IsMaximized(this->Handle());
}
}

void _UpdateFrameMargins() const noexcept {
if (Win32Helper::GetOSVersion().IsWin11()) {
return;
Expand Down Expand Up @@ -519,7 +511,7 @@ class XamlWindowT : public WindowBaseT<T> {
uint32_t _nativeTopBorderHeight = 1;

bool _isLightTheme = true;
bool _isWindowShown = false;
bool _isInitialMaximized = false;
bool _isMaximized = false;
};

Expand Down

0 comments on commit 1f82b73

Please sign in to comment.