// 2025/6/23 by Zhe Fang using BetterLyrics.WinUI3.Enums; using BetterLyrics.WinUI3.Helper; using BetterLyrics.WinUI3.Services; using BetterLyrics.WinUI3.ViewModels; using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging.Messages; using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Input; using System; using System.Drawing; using System.Threading.Tasks; using System.Windows.Forms; using Vanara.PInvoke; using Windows.System; using WinUIEx.Messaging; namespace BetterLyrics.WinUI3.Views { public sealed partial class LyricsWindow : Window { private readonly ISettingsService _settingsService = Ioc.Default.GetRequiredService(); private readonly WindowMessageMonitor _wmm; public LyricsWindow() { this.InitializeComponent(); AppWindow.SetIcons(); AppWindow.Changed += AppWindow_Changed; ExtendsContentIntoTitleBar = true; AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Collapsed; Title = App.ResourceLoader!.GetString("LyricsPageTitle"); UpdateTitleBarArea(); _wmm = new WindowMessageMonitor(this); _wmm.WindowMessageReceived += Wmm_WindowMessageReceived; } public void UpdateTitleBarArea() { if (_settingsService.IsDragEverywhereEnabled) { SetTitleBar(RootGrid); } else { SetTitleBar(TopCommandGrid); } } private void Wmm_WindowMessageReceived(object? sender, WindowMessageEventArgs e) { if (e.Message.MessageId == (uint)User32.WindowMessage.WM_HOTKEY) { int id = (int)e.Message.WParam; GlobalHotKeyHelper.TryInvokeAction(id); } } public LyricsWindowViewModel ViewModel { get; private set; } = Ioc.Default.GetRequiredService(); public void AutoSelectLyricsMode(AutoStartWindowType? type = null, bool? autoLook = null) { type ??= _settingsService.AutoStartWindowType; switch (type!) { case AutoStartWindowType.StandardMode: if (_settingsService.StandardWindowLeft < 0 || _settingsService.StandardWindowTop < 0 || _settingsService.StandardWindowWidth <= 0 || _settingsService.StandardWindowHeight <= 0) { _settingsService.StandardWindowLeft = 200; _settingsService.StandardWindowTop = 200; _settingsService.StandardWindowWidth = 1600; _settingsService.StandardWindowHeight = 800; } AppWindow.MoveAndResize(new Windows.Graphics.RectInt32( _settingsService.StandardWindowLeft, _settingsService.StandardWindowTop, _settingsService.StandardWindowWidth, _settingsService.StandardWindowHeight )); break; case AutoStartWindowType.DockMode: DockFlyoutItem.IsChecked = true; ViewModel.ToggleDockModeCommand.Execute(null); break; case AutoStartWindowType.DesktopMode: DesktopFlyoutItem.IsChecked = true; ViewModel.ToggleDesktopModeCommand.Execute(null); if (autoLook == null && _settingsService.AutoLockOnDesktopMode) { ViewModel.ToggleLockWindowCommand.Execute(null); } break; default: break; } } private void AOTFlyoutItem_Click(object sender, RoutedEventArgs e) { var overlappedPresenter = (OverlappedPresenter)AppWindow.Presenter; overlappedPresenter.IsAlwaysOnTop = !overlappedPresenter.IsAlwaysOnTop; } private void AppWindow_Changed(AppWindow sender, AppWindowChangedEventArgs args) { if (args.DidPresenterChange) UpdateTitleBarWindowButtonsVisibility(); if (args.DidPositionChange || args.DidSizeChange) { var rect = AppWindow.Position; var size = AppWindow.Size; if (rect.X >= 0 && rect.Y >= 0 && size.Width > 0 && size.Height > 0) { if (ViewModel.IsDesktopMode) { _settingsService.DesktopWindowLeft = rect.X; _settingsService.DesktopWindowTop = rect.Y; _settingsService.DesktopWindowWidth = size.Width; _settingsService.DesktopWindowHeight = size.Height; } else if (ViewModel.IsDockMode) { } else { _settingsService.StandardWindowLeft = rect.X; _settingsService.StandardWindowTop = rect.Y; _settingsService.StandardWindowWidth = size.Width; _settingsService.StandardWindowHeight = size.Height; } } } } private void FullScreenFlyoutItem_Click(object sender, RoutedEventArgs e) { switch (AppWindow.Presenter.Kind) { case AppWindowPresenterKind.Default: break; case AppWindowPresenterKind.CompactOverlay: break; case AppWindowPresenterKind.FullScreen: AppWindow.SetPresenter(AppWindowPresenterKind.Overlapped); break; case AppWindowPresenterKind.Overlapped: AppWindow.SetPresenter(AppWindowPresenterKind.FullScreen); break; default: break; } } private void MiniFlyoutItem_Click(object sender, RoutedEventArgs e) { if (MiniFlyoutItem.IsChecked) { AppWindow.SetPresenter(AppWindowPresenterKind.CompactOverlay); } else { AppWindow.SetPresenter(AppWindowPresenterKind.Overlapped); } } private void SettingsMenuFlyoutItem_Click(object sender, RoutedEventArgs e) { WindowHelper.OpenWindow(); } private void UpdateTitleBarWindowButtonsVisibility() { switch (AppWindow.Presenter.Kind) { case AppWindowPresenterKind.Default: break; case AppWindowPresenterKind.CompactOverlay: MinimiseButton.Visibility = MaximiseButton.Visibility = RestoreButton.Visibility = AOTFlyoutItem.Visibility = DesktopFlyoutItem.Visibility = FullScreenFlyoutItem.Visibility = DockFlyoutItem.Visibility = ClickThroughButton.Visibility = Visibility.Collapsed; ViewModel.IsImmersiveMode = true; break; case AppWindowPresenterKind.FullScreen: MinimiseButton.Visibility = MaximiseButton.Visibility = RestoreButton.Visibility = AOTFlyoutItem.Visibility = ClickThroughButton.Visibility = DesktopFlyoutItem.Visibility = MiniFlyoutItem.Visibility = DockFlyoutItem.Visibility = Visibility.Collapsed; FullScreenFlyoutItem.IsChecked = true; break; case AppWindowPresenterKind.Overlapped: DockFlyoutItem.Visibility = Visibility.Visible; var overlappedPresenter = (OverlappedPresenter)AppWindow.Presenter; if (DockFlyoutItem.IsChecked) { overlappedPresenter.IsMinimizable = overlappedPresenter.IsMaximizable = false; MinimiseButton.Visibility = MaximiseButton.Visibility = RestoreButton.Visibility = AOTFlyoutItem.Visibility = DesktopFlyoutItem.Visibility = ClickThroughButton.Visibility = FullScreenFlyoutItem.Visibility = MiniFlyoutItem.Visibility = Visibility.Collapsed; ViewModel.IsImmersiveMode = true; } else if (DesktopFlyoutItem.IsChecked) { overlappedPresenter.IsMinimizable = overlappedPresenter.IsMaximizable = false; MinimiseButton.Visibility = MaximiseButton.Visibility = RestoreButton.Visibility = DockFlyoutItem.Visibility = AOTFlyoutItem.Visibility = FullScreenFlyoutItem.Visibility = MiniFlyoutItem.Visibility = Visibility.Collapsed; ClickThroughButton.Visibility = Visibility.Visible; } else { overlappedPresenter.IsMinimizable = overlappedPresenter.IsMaximizable = true; MinimiseButton.Visibility = AOTFlyoutItem.Visibility = DesktopFlyoutItem.Visibility = DockFlyoutItem.Visibility = MiniFlyoutItem.Visibility = FullScreenFlyoutItem.Visibility = Visibility.Visible; FullScreenFlyoutItem.IsChecked = false; ClickThroughButton.Visibility = Visibility.Collapsed; AOTFlyoutItem.IsChecked = overlappedPresenter.IsAlwaysOnTop; if (overlappedPresenter.State == OverlappedPresenterState.Maximized) { MaximiseButton.Visibility = Visibility.Collapsed; RestoreButton.Visibility = Visibility.Visible; } else if (overlappedPresenter.State == OverlappedPresenterState.Restored) { MaximiseButton.Visibility = Visibility.Visible; RestoreButton.Visibility = Visibility.Collapsed; } ViewModel.IsImmersiveMode = _settingsService.IsImmersiveMode; } break; default: break; } } private void CloseButton_Click(object sender, RoutedEventArgs e) { DockModeHelper.Disable(this); Environment.Exit(0); } private void MaximiseButton_Click(object sender, RoutedEventArgs e) { if (AppWindow.Presenter is OverlappedPresenter presenter) { presenter.Maximize(); } } private void MinimiseButton_Click(object sender, RoutedEventArgs e) { if (AppWindow.Presenter is OverlappedPresenter presenter) { presenter.Minimize(); } } private void RestoreButton_Click(object sender, RoutedEventArgs e) { if (AppWindow.Presenter is OverlappedPresenter presenter) { presenter.Restore(); } } private void TopCommandGrid_PointerEntered(object sender, PointerRoutedEventArgs e) { if (ViewModel.IsImmersiveMode) { ViewModel.TopCommandGridOpacity = 1f; } } private void TopCommandGrid_PointerExited(object sender, PointerRoutedEventArgs e) { if (ViewModel.IsImmersiveMode) { ViewModel.TopCommandGridOpacity = 0f; } } private void TipContainerCenter_Loaded(object sender, RoutedEventArgs e) { App.Current.LyricsWindowNotificationPanel = TipContainerCenter; } private void RootGrid_PointerEntered(object sender, PointerRoutedEventArgs e) { ViewModel.IsMouseWithinWindow = true; e.Handled = true; } private void RootGrid_PointerExited(object sender, PointerRoutedEventArgs e) { ViewModel.IsMouseWithinWindow = false; e.Handled = true; } private void RootGrid_SizeChanged(object sender, SizeChangedEventArgs e) { } private void MusicGalleryButton_Click(object sender, RoutedEventArgs e) { WindowHelper.OpenWindow(); } private void ClickThroughButton_Click(object sender, RoutedEventArgs e) { ViewModel.ToggleLockWindowCommand.Execute(null); } private void DockFlyoutItem_Click(object sender, RoutedEventArgs e) { ViewModel.ToggleDockModeCommand.Execute(null); } private void DesktopFlyoutItem_Click(object sender, RoutedEventArgs e) { ViewModel.ToggleDesktopModeCommand.Execute(null); UpdateTitleBarWindowButtonsVisibility(); } } }