diff --git a/lib/domain/dashboard_preferences.dart b/lib/domain/dashboard_preferences.dart index 95bd3fb..f26a326 100644 --- a/lib/domain/dashboard_preferences.dart +++ b/lib/domain/dashboard_preferences.dart @@ -46,6 +46,9 @@ class DashboardPreferences { class DashboardPreferencesRepository { static const _keyRangeMode = 'ringotrack.dashboard.heatmapRangeMode'; static const _keyGlassEffect = 'ringotrack.dashboard.enableGlassEffect'; + // Windows 平台:待生效的玻璃效果设置,下次启动时应用 + static const _keyGlassEffectPending = 'ringotrack.dashboard.enableGlassEffect.pending'; + static const _keyWeekStartMode = 'ringotrack.dashboard.weekStartMode'; Future load() async { @@ -74,4 +77,34 @@ class DashboardPreferencesRepository { await sp.setBool(_keyGlassEffect, prefs.enableGlassEffect); await sp.setString(_keyWeekStartMode, prefs.weekStartMode.name); } + + /// Windows 平台:设置待生效的玻璃效果值(下次启动时应用) + Future setGlassEffectPending(bool enabled) async { + final sp = await SharedPreferences.getInstance(); + await sp.setBool(_keyGlassEffectPending, enabled); + } + + /// Windows 平台:获取待生效的玻璃效果值 + /// 返回 null 表示没有待生效的设置 + Future getGlassEffectPending() async { + final sp = await SharedPreferences.getInstance(); + if (!sp.containsKey(_keyGlassEffectPending)) return null; + return sp.getBool(_keyGlassEffectPending); + } + + /// Windows 平台:启动时调用,将 pending 值应用到实际设置 + /// 返回最终的 enableGlassEffect 值 + Future applyPendingGlassEffect() async { + final sp = await SharedPreferences.getInstance(); + final pending = sp.getBool(_keyGlassEffectPending); + if (pending != null) { + // 将 pending 值应用到实际设置 + await sp.setBool(_keyGlassEffect, pending); + // 清除 pending + await sp.remove(_keyGlassEffectPending); + return pending; + } + // 没有 pending,返回当前值 + return sp.getBool(_keyGlassEffect) ?? false; + } } diff --git a/lib/domain/dashboard_preferences_controller.dart b/lib/domain/dashboard_preferences_controller.dart index 34ad516..0d65d8a 100644 --- a/lib/domain/dashboard_preferences_controller.dart +++ b/lib/domain/dashboard_preferences_controller.dart @@ -1,3 +1,5 @@ +import 'dart:io' show Platform; + import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:ringotrack/domain/dashboard_preferences.dart'; @@ -20,6 +22,16 @@ class DashboardPreferencesController Future setEnableGlassEffect(bool enabled) async { final current = state.value ?? const DashboardPreferences(); + + // Windows 平台:设置 pending 值,下次启动时生效。 + // UI 状态不变,避免背景立即变透明但玻璃效果还没启用。 + if (Platform.isWindows) { + await _repository.setGlassEffectPending(enabled); + // 不更新 state,让 UI 保持当前状态 + return; + } + + // macOS:直接更新,可以实时切换 final next = current.copyWith(enableGlassEffect: enabled); state = AsyncData(next); await _repository.save(next); @@ -42,3 +54,13 @@ final dashboardPreferencesControllerProvider = AsyncNotifierProvider( DashboardPreferencesController.new, ); + +/// Windows 平台:获取玻璃效果的显示值(pending 值优先,否则用当前值) +/// 用于 UI 显示,让用户看到他们设置的值 +final windowsGlassEffectDisplayProvider = FutureProvider((ref) async { + final repo = ref.watch(dashboardPreferencesRepositoryProvider); + final pending = await repo.getGlassEffectPending(); + if (pending != null) return pending; + final prefs = await repo.load(); + return prefs.enableGlassEffect; +}); diff --git a/lib/main.dart b/lib/main.dart index 5e5f17e..e98708a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,7 +1,27 @@ +import 'dart:io' show Platform; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:ringotrack/app.dart'; +import 'package:ringotrack/domain/dashboard_preferences.dart'; +import 'package:ringotrack/platform/glass_tint_controller.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + + // Windows 平台:在启动时一次性决定是否启用玻璃效果。 + // 由于 Windows 上玻璃效果无法在运行时优雅地关闭, + // 所以仅在启动时根据用户偏好来决定是否启用。 + if (Platform.isWindows) { + final repo = DashboardPreferencesRepository(); + // 先应用 pending 值(如果有的话),这样 UI 层读取到的是最新的设置 + final enableGlass = await repo.applyPendingGlassEffect(); + if (enableGlass) { + await GlassTintController.instance.enableGlass(); + } + // 如果 enableGlassEffect 为 false,则完全不启用玻璃效果, + // 窗口将保持默认的不透明背景。 + } -void main() { runApp(const ProviderScope(child: RingoTrackApp())); } diff --git a/lib/pages/clock_page.dart b/lib/pages/clock_page.dart index 9a0bf0b..1b73b45 100644 --- a/lib/pages/clock_page.dart +++ b/lib/pages/clock_page.dart @@ -1,3 +1,4 @@ +import 'dart:io' show Platform; import 'dart:math' as math; import 'package:flutter/material.dart'; @@ -27,7 +28,7 @@ class _ClockPageState extends ConsumerState { @override void dispose() { - // 离开页面时恢复默认白色 tint + // 离开页面时恢复默认白色 tint(macOS/Windows 都支持更新 tint 颜色) GlassTintController.instance.resetTintColor(); super.dispose(); } @@ -93,22 +94,24 @@ class _ClockPageState extends ConsumerState { final pinSupported = WindowPinController.instance.isSupported; final useGlass = ref.watch(useGlassEffectProvider); - // 监听毛玻璃设置变化 - ref.listen(useGlassEffectProvider, (previous, next) { - if (mounted) { - WidgetsBinding.instance.addPostFrameCallback((_) { - if (next) { - // 开启毛玻璃:设置彩色 tint - _updateGlassTint(); - } else { - // 关闭毛玻璃:恢复默认白色 tint - GlassTintController.instance.resetTintColor(); - } - }); - } - }); + // 监听毛玻璃设置变化(仅 macOS,Windows 不支持实时开/关) + if (Platform.isMacOS) { + ref.listen(useGlassEffectProvider, (previous, next) { + if (mounted) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (next) { + // 开启毛玻璃:设置彩色 tint + _updateGlassTint(); + } else { + // 关闭毛玻璃:恢复默认白色 tint + GlassTintController.instance.resetTintColor(); + } + }); + } + }); + } - // 监听主题变化,更新 tint(仅在毛玻璃模式下) + // 监听主题变化,更新 tint(仅在毛玻璃模式下,macOS/Windows 都支持) ref.listen(appThemeProvider, (previous, next) { if (useGlass && mounted) { WidgetsBinding.instance.addPostFrameCallback((_) { diff --git a/lib/pages/dashboard_page.dart b/lib/pages/dashboard_page.dart index bf05610..74cb228 100644 --- a/lib/pages/dashboard_page.dart +++ b/lib/pages/dashboard_page.dart @@ -87,6 +87,7 @@ class _DashboardPageState extends ConsumerState { void initState() { super.initState(); // 确保恢复默认白色 tint(从 ClockPage 返回时) + // macOS/Windows 都支持更新 tint 颜色 WidgetsBinding.instance.addPostFrameCallback((_) { GlassTintController.instance.resetTintColor(); }); diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart index a2e7ad8..566c808 100644 --- a/lib/pages/settings_page.dart +++ b/lib/pages/settings_page.dart @@ -43,6 +43,7 @@ class _SettingsPageState extends ConsumerState { void initState() { super.initState(); // 确保恢复默认白色 tint(从 ClockPage 返回时) + // macOS/Windows 都支持更新 tint 颜色 WidgetsBinding.instance.addPostFrameCallback((_) { GlassTintController.instance.resetTintColor(); }); @@ -1040,11 +1041,6 @@ class _SettingsPageState extends ConsumerState { } Widget _appearanceSection(ThemeData theme) { - final dashboardPrefsAsync = ref.watch( - dashboardPreferencesControllerProvider, - ); - final enableGlass = dashboardPrefsAsync.value?.enableGlassEffect ?? true; - final tiles = [ _dataTile( theme, @@ -1055,12 +1051,42 @@ class _SettingsPageState extends ConsumerState { ]; if (Platform.isMacOS || Platform.isWindows) { - tiles.add( - _dataTile( - theme, - title: '毛玻璃效果(实验性)', - helper: '启用后窗口背景将呈现半透明模糊效果。', - child: Row( + tiles.add(_buildGlassEffectTile(theme)); + } + + return _sectionCard( + theme, + title: '外观', + icon: Icons.palette_outlined, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: _withDividers(tiles, theme), + ), + ); + } + + Widget _buildGlassEffectTile(ThemeData theme) { + // Windows 平台:显示 pending 值(用户设置的值,待重启生效) + // macOS 平台:显示当前生效的值 + final bool enableGlass; + if (Platform.isWindows) { + final displayAsync = ref.watch(windowsGlassEffectDisplayProvider); + enableGlass = displayAsync.value ?? false; + } else { + final dashboardPrefsAsync = ref.watch( + dashboardPreferencesControllerProvider, + ); + enableGlass = dashboardPrefsAsync.value?.enableGlassEffect ?? false; + } + + return _dataTile( + theme, + title: '毛玻璃效果(实验性)', + helper: '启用后窗口背景将呈现半透明模糊效果。', + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( children: [ Switch( value: enableGlass, @@ -1068,6 +1094,11 @@ class _SettingsPageState extends ConsumerState { ref .read(dashboardPreferencesControllerProvider.notifier) .setEnableGlassEffect(value); + // Windows 平台:刷新 display provider 并提示用户需要重启 + if (Platform.isWindows) { + ref.invalidate(windowsGlassEffectDisplayProvider); + _showSnack('设置已保存,重启应用后生效'); + } }, ), SizedBox(width: 8.w), @@ -1077,17 +1108,17 @@ class _SettingsPageState extends ConsumerState { ), ], ), - ), - ); - } - - return _sectionCard( - theme, - title: '外观', - icon: Icons.palette_outlined, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: _withDividers(tiles, theme), + // Windows 平台显示重启提示 + if (Platform.isWindows) ...[ + SizedBox(height: 6.h), + Text( + '⚠️ 需要重启应用才能生效', + style: theme.textTheme.bodySmall?.copyWith( + color: theme.colorScheme.onSurfaceVariant, + ), + ), + ], + ], ), ); } diff --git a/lib/platform/glass_tint_controller.dart b/lib/platform/glass_tint_controller.dart index ef5dd14..7b98eac 100644 --- a/lib/platform/glass_tint_controller.dart +++ b/lib/platform/glass_tint_controller.dart @@ -2,6 +2,7 @@ import 'dart:ffi' as ffi; import 'dart:io' show Platform; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:ringotrack/domain/dashboard_preferences.dart'; typedef _RtSetGlassTintNative = ffi.Int32 Function(ffi.Uint8 r, ffi.Uint8 g, ffi.Uint8 b); @@ -10,14 +11,18 @@ typedef _RtSetGlassTintDart = int Function(int r, int g, int b); typedef _RtResetGlassTintNative = ffi.Int32 Function(); typedef _RtResetGlassTintDart = int Function(); +typedef _RtDisableGlassNative = ffi.Int32 Function(); +typedef _RtDisableGlassDart = int Function(); + /// 毛玻璃 tint 颜色控制器(macOS / Windows) class GlassTintController { - GlassTintController._(this._setTintFn, this._resetTintFn); + GlassTintController._(this._setTintFn, this._resetTintFn, this._disableGlassFn); static final GlassTintController instance = GlassTintController._create(); final _RtSetGlassTintDart? _setTintFn; final _RtResetGlassTintDart? _resetTintFn; + final _RtDisableGlassDart? _disableGlassFn; static GlassTintController _create() { // Windows: 通过 FFI 调用 runner 导出的 C 接口。 @@ -32,19 +37,36 @@ class GlassTintController { .lookupFunction<_RtResetGlassTintNative, _RtResetGlassTintDart>( 'rt_reset_glass_tint', ); - return GlassTintController._(setFn, resetFn); + final disableFn = lib + .lookupFunction<_RtDisableGlassNative, _RtDisableGlassDart>( + 'rt_disable_glass', + ); + return GlassTintController._(setFn, resetFn, disableFn); } catch (e, st) { debugPrint('GlassTintController: Windows FFI lookup failed: $e\n$st'); - return GlassTintController._(null, null); + return GlassTintController._(null, null, null); } } // 其他平台(包含 macOS,使用 MethodChannel 实现)。 - return GlassTintController._(null, null); + return GlassTintController._(null, null, null); } static const MethodChannel _channel = MethodChannel('ringotrack/glass_tint'); + /// Windows 平台:检查用户是否在 preference 中启用了玻璃效果。 + /// 用于避免在页面切换时意外启用玻璃效果。 + Future _isGlassEnabledInPrefs() async { + try { + final repo = DashboardPreferencesRepository(); + final prefs = await repo.load(); + return prefs.enableGlassEffect; + } catch (e) { + debugPrint('GlassTintController._isGlassEnabledInPrefs error: $e'); + return false; + } + } + /// 当前平台是否支持毛玻璃 tint 控制(macOS / Windows) bool get isSupported { if (Platform.isMacOS) { @@ -57,6 +79,7 @@ class GlassTintController { } /// 设置毛玻璃 tint 颜色 + /// Windows 平台会先检查 preference,如果用户禁用了玻璃效果则不执行。 Future setTintColor(Color color) async { if (!isSupported) return false; @@ -76,7 +99,10 @@ class GlassTintController { } // Windows: 通过 FFI 调用 rt_set_glass_tint。 + // 先检查 preference,如果用户禁用了玻璃效果则不执行,避免意外启用玻璃。 if (Platform.isWindows) { + if (!await _isGlassEnabledInPrefs()) return false; + final fn = _setTintFn; if (fn == null) return false; try { @@ -96,6 +122,7 @@ class GlassTintController { } /// 重置为默认白色 tint + /// Windows 平台会先检查 preference,如果用户禁用了玻璃效果则不执行。 Future resetTintColor() async { if (!isSupported) return false; @@ -111,7 +138,10 @@ class GlassTintController { } // Windows: 通过 FFI 调用 rt_reset_glass_tint。 + // 先检查 preference,如果用户禁用了玻璃效果则不执行,避免意外启用玻璃。 if (Platform.isWindows) { + if (!await _isGlassEnabledInPrefs()) return false; + final fn = _resetTintFn; if (fn == null) return false; try { @@ -127,5 +157,41 @@ class GlassTintController { return false; } + + /// 完全禁用毛玻璃效果(仅 Windows 支持,macOS 使用不同的机制) + Future disableGlass() async { + // Windows: 通过 FFI 调用 rt_disable_glass。 + if (Platform.isWindows) { + final fn = _disableGlassFn; + if (fn == null) return false; + try { + final code = fn(); + return code != 0; + } catch (e, st) { + debugPrint( + 'GlassTintController.disableGlass(Windows) error: $e\n$st', + ); + return false; + } + } + + // macOS: 通过 MethodChannel 调用 disableGlass。 + if (Platform.isMacOS) { + try { + final result = await _channel.invokeMethod('disableGlass'); + return result ?? false; + } catch (e, st) { + debugPrint('GlassTintController.disableGlass(macOS) error: $e\n$st'); + return false; + } + } + + return false; + } + + /// 启用毛玻璃效果(使用默认白色 tint) + Future enableGlass() async { + return resetTintColor(); + } } diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp index c4173d6..c68fca7 100644 --- a/windows/runner/flutter_window.cpp +++ b/windows/runner/flutter_window.cpp @@ -5,62 +5,47 @@ #include "flutter/generated_plugin_registrant.h" +// 来自 foreground_tracker_win.cpp:查询当前是否处于 pinned 模式。 +extern "C" int rt_is_pinned(); + namespace { // 原始 Flutter View 窗口过程,用于在自定义处理后转发消息。 WNDPROC g_flutter_view_wndproc = nullptr; // 针对 Flutter 子窗口的自定义窗口过程: -// - 在父窗口为无标题栏(即 pinned / 无边框)时, -// 将除右上角一小块区域外的所有区域视为「拖动区域」。 -// - 用户在这些区域按下左键时,模拟对父窗口标题栏的点击,触发系统拖动。 +// 在 pinned 模式下,对 WM_NCHITTEST 返回 HTTRANSPARENT, +// 让父窗口处理命中测试,从而实现流畅的窗口拖动。 LRESULT CALLBACK FlutterViewWindowProc(HWND hwnd, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) { + UINT const message, + WPARAM const wparam, + LPARAM const lparam) { switch (message) { - case WM_LBUTTONDOWN: { - HWND parent = GetAncestor(hwnd, GA_ROOT); - if (parent != nullptr) { - const LONG style = - static_cast(GetWindowLongPtr(parent, GWL_STYLE)); - const bool has_caption = (style & WS_CAPTION) != 0; - - // 仅当父窗口是无标题栏(即自绘无边框场景,例如 pinned 小窗)时, - // 才把点击视为拖动操作。 - if (!has_caption) { - // 客户区坐标(对于 WM_LBUTTONDOWN,lParam 已经是客户端坐标)。 - POINT client_pos{GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)}; - - RECT client_rect{}; - GetClientRect(hwnd, &client_rect); - - // 在右上角预留一块区域给 Flutter 内部的 pin 按钮点击, - // 避免把 pin 按钮点击也拦截成拖动。 - constexpr int kPinSafeWidth = 80; - constexpr int kPinSafeHeight = 80; - const bool in_pin_safe_region = - client_pos.x >= client_rect.right - kPinSafeWidth && - client_pos.x <= client_rect.right && - client_pos.y >= client_rect.top && - client_pos.y <= client_rect.top + kPinSafeHeight; - - if (!in_pin_safe_region) { - // 将客户端坐标转换为屏幕坐标,用于构造 WM_NCLBUTTONDOWN 的 lParam。 - POINT screen_pos = client_pos; - ClientToScreen(hwnd, &screen_pos); - const LPARAM screen_lparam = - MAKELPARAM(static_cast(screen_pos.x), - static_cast(screen_pos.y)); - - // 释放当前捕获,并在父窗口上模拟一次对标题栏的点击, - // 让系统进入窗口拖动模式。 - ReleaseCapture(); - SendMessage(parent, WM_NCLBUTTONDOWN, HTCAPTION, screen_lparam); - - // 不再将该事件传递给 Flutter,避免产生多余的点击反馈。 - return 0; - } + case WM_NCHITTEST: { + if (rt_is_pinned()) { + // 获取鼠标屏幕坐标 + POINT screen_pos{GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)}; + + // 转换为客户区坐标 + POINT client_pos = screen_pos; + ScreenToClient(hwnd, &client_pos); + + RECT client_rect{}; + GetClientRect(hwnd, &client_rect); + + // 在右上角预留一块区域给 Flutter 内部的 pin 按钮点击 + constexpr int kPinSafeWidth = 80; + constexpr int kPinSafeHeight = 80; + const bool in_pin_safe_region = + client_pos.x >= client_rect.right - kPinSafeWidth && + client_pos.x <= client_rect.right && + client_pos.y >= client_rect.top && + client_pos.y <= client_rect.top + kPinSafeHeight; + + if (!in_pin_safe_region) { + // 返回 HTTRANSPARENT,让系统将命中测试传递给父窗口, + // 父窗口会返回 HTCAPTION,从而触发系统原生拖动。 + return HTTRANSPARENT; } } break; @@ -108,8 +93,8 @@ bool FlutterWindow::OnCreate() { // window is shown. It is a no-op if the first frame hasn't completed yet. flutter_controller_->ForceRedraw(); - // 子类化 Flutter View 的窗口过程,以便在无边框模式下拦截鼠标按下事件, - // 实现「全窗口可拖动」的小窗效果。 + // 子类化 Flutter View 的窗口过程,以便在 pinned 模式下 + // 对 WM_NCHITTEST 返回 HTTRANSPARENT,让父窗口处理拖动。 HWND flutter_view_hwnd = flutter_controller_->view()->GetNativeWindow(); g_flutter_view_wndproc = reinterpret_cast( SetWindowLongPtr(flutter_view_hwnd, GWLP_WNDPROC, diff --git a/windows/runner/foreground_tracker_win.cpp b/windows/runner/foreground_tracker_win.cpp index b108769..fe3687b 100644 --- a/windows/runner/foreground_tracker_win.cpp +++ b/windows/runner/foreground_tracker_win.cpp @@ -432,6 +432,12 @@ __declspec(dllexport) std::int32_t rt_enter_pinned_mode() { return 1; } +// 查询当前是否处于 pinned 模式。 +// 返回值:1 表示处于 pinned 模式,0 表示非 pinned 模式。 +__declspec(dllexport) std::int32_t rt_is_pinned() { + return g_is_pinned.load(std::memory_order_acquire) ? 1 : 0; +} + // 退出置顶小窗模式,恢复窗口原有位置和大小。 // 返回值:非 0 表示成功,0 表示失败。 __declspec(dllexport) std::int32_t rt_exit_pinned_mode() { @@ -508,4 +514,10 @@ __declspec(dllexport) std::int32_t rt_reset_glass_tint() { return EnableGlassWithColor(rgb, kAlpha) ? 1 : 0; } +// 完全禁用毛玻璃效果(将 AccentState 设置为 DISABLED)。 +// 返回值:非 0 表示成功,0 表示失败。 +__declspec(dllexport) std::int32_t rt_disable_glass() { + return DisableGlass() ? 1 : 0; +} + } // extern "C" diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index ba830a4..d8750c5 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -10,6 +10,9 @@ // 这里声明为 C 接口,方便在窗口关闭前做一次 cleanup,恢复正常窗口尺寸。 extern "C" int rt_exit_pinned_mode(); +// 来自 foreground_tracker_win.cpp:查询当前是否处于 pinned 模式。 +extern "C" int rt_is_pinned(); + namespace { /// Window attribute that enables dark mode window decorations. @@ -184,6 +187,46 @@ Win32Window::MessageHandler(HWND hwnd, WPARAM const wparam, LPARAM const lparam) noexcept { switch (message) { + case WM_NCHITTEST: { + // 在 pinned 小窗模式下(无标题栏),让整个窗口(除右上角安全区域) + // 都被系统识别为「标题栏」,这样系统会自动处理窗口拖动,非常流畅跟手。 + if (rt_is_pinned()) { + // 先调用默认处理获取标准结果 + LRESULT default_result = DefWindowProc(hwnd, message, wparam, lparam); + + // 如果在客户区,则判断是否需要视为标题栏 + if (default_result == HTCLIENT) { + // 获取鼠标在屏幕上的坐标 + POINT screen_pos{GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)}; + + // 转换为窗口客户区坐标 + POINT client_pos = screen_pos; + ScreenToClient(hwnd, &client_pos); + + RECT client_rect{}; + GetClientRect(hwnd, &client_rect); + + // 在右上角预留一块区域给 Flutter 内部的 pin 按钮点击, + // 避免把 pin 按钮点击也拦截成拖动。 + constexpr int kPinSafeWidth = 80; + constexpr int kPinSafeHeight = 80; + const bool in_pin_safe_region = + client_pos.x >= client_rect.right - kPinSafeWidth && + client_pos.x <= client_rect.right && + client_pos.y >= client_rect.top && + client_pos.y <= client_rect.top + kPinSafeHeight; + + if (!in_pin_safe_region) { + // 告诉系统这是标题栏,系统会自动处理拖动 + return HTCAPTION; + } + } + + return default_result; + } + break; + } + case WM_CLOSE: // 如果当前处于 pinned 小窗模式,先恢复为原始窗口尺寸和样式, // 避免系统在关闭时记住的是小窗大小。