diff --git a/MoneyShot/App.xaml b/MoneyShot/App.xaml index cbc54fe..9e93348 100644 --- a/MoneyShot/App.xaml +++ b/MoneyShot/App.xaml @@ -2,7 +2,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:MoneyShot" - StartupUri="MainWindow.xaml"> + ShutdownMode="OnExplicitShutdown"> diff --git a/MoneyShot/App.xaml.cs b/MoneyShot/App.xaml.cs index fb8a38c..47981f1 100644 --- a/MoneyShot/App.xaml.cs +++ b/MoneyShot/App.xaml.cs @@ -32,6 +32,14 @@ protected override void OnStartup(StartupEventArgs e) } base.OnStartup(e); + + // StartupUri is intentionally not used. It calls Show() during startup, which paints an + // unrendered (black) frame before the Loaded handler can hide it when StartInTray is set. + // Instead we create the window here and let InitializeApplication decide whether to show + // it or just realize its handle for hotkeys — see MainWindow.InitializeApplication. + var mainWindow = new MainWindow(); + MainWindow = mainWindow; + mainWindow.InitializeApplication(); } protected override void OnExit(ExitEventArgs e) diff --git a/MoneyShot/MainWindow.xaml.cs b/MoneyShot/MainWindow.xaml.cs index 32b8c66..dfcb21c 100644 --- a/MoneyShot/MainWindow.xaml.cs +++ b/MoneyShot/MainWindow.xaml.cs @@ -3,6 +3,7 @@ using System.Windows.Controls; using System.Windows.Forms; using System.Windows.Input; +using System.Windows.Interop; using System.Windows.Media; using MoneyShot.Services; using MoneyShot.Views; @@ -37,27 +38,40 @@ public MainWindow() _historyService = new HistoryService(); SetupSystemTray(); - Loaded += MainWindow_Loaded; } - private async void MainWindow_Loaded(object sender, RoutedEventArgs e) + /// + /// Performs post-construction startup: realizes the native handle, binds global hotkeys, and + /// shows the window only when the user hasn't opted to start in the tray. Called once from + /// . When is set the + /// window is never shown — creates the HWND that + /// hotkey registration needs without painting anything, which avoids the black-frame flash that + /// Show()-then-Hide() produced. + /// + public void InitializeApplication() { try { - _hotKeyService.Initialize(this); - RegisterHotKeys(); - PopulateMonitorButtons(); - - // Check if app should start in tray var settings = _settingsService.LoadSettings(); + if (settings.StartInTray) { - Hide(); + // Realize the Win32 handle without making the window visible. + new WindowInteropHelper(this).EnsureHandle(); + } + else + { + ShowMainWindow(); } + // The HWND now exists (via EnsureHandle or Show), so global hotkeys can bind to it. + _hotKeyService.Initialize(this); + RegisterHotKeys(); + PopulateMonitorButtons(); + if (settings.CheckForUpdatesOnStartup) { - await CheckForUpdatesOnStartupAsync(); + _ = CheckForUpdatesOnStartupAsync(); } } catch (Exception ex)