Reputation: 9518
When the SplashScreen closes (either manually or by AutoClose), it steals the focus of the MainWindow during the fade-out animation. This results in the caption of the main window switching from active to inactive (grey) to active. Is there any trick to keep the SplashScreen from stealing focus?
Upvotes: 4
Views: 1706
Reputation: 20394
Using ILSpy, I found that the SplashScreen.Close
method calls SetActiveWindow
at some point, causing the slpash screen window to become active in the moment it starts closing. (At least in .NET 4.0.) I added a call to my MainWindow.Focus
just after calling SplashScreen.Close
, and that resolves the issue.
Otherwise, I could see how the main window was inactive only during the time that the fadeout animation took. Additionally, I show a modal dialog window when the main window has loaded, and this remains active. But when that dialog is closed, the main window wouldn't focus anymore and instead I'll end up in the Visual Studio window or whatever started my application. Inserting the Focus
call from above also helps in this situation.
BTW, here's a good article that explained me how to use the SplashScreen
class manually instead of the project file option: http://tech.pro/tutorial/822/wpf-tutorial-using-splash-screens-in-sp1
This is some code from my application:
In App.xaml.cs:
/// <summary>
/// Application Entry Point.
/// </summary>
[STAThread]
public static void Main()
{
splashScreen = new SplashScreen("Splashscreen.png");
splashScreen.Show(false, true);
Thread.Sleep(2000); // For demonstration purposes only!
App app = new App();
app.InitializeComponent();
app.Run();
}
In my main window ViewModel's Init command (the main window is already completely visible):
private void OnInitCommand()
{
ConnectDatabase();
App.SplashScreen.Close(TimeSpan.FromMilliseconds(500));
MainWindow.Instance.Focus(); // This corrects the window focus
SomeDialog dlg = new SomeDialog();
dlg.Owner = MainWindow.Instance;
if (dlg.ShowDialog() == true)
{
// Do something with it
}
// Now the main window is focused again
}
Upvotes: 2
Reputation: 19612
Tell the SplashScreen that MainWindow is its parent window. When a child window loses focus, its parent gets the focus. If there is no parent, the window manager decides.
splashScreen.Show(mainWindow);
EDIT:
I just found out that there's a SplashScreen class. Looks like you use that class and not just a normal Form as I assumed.
So, I just made a simple WPF app with a SplashScreen and for me the mentioned effect didn't happen. The main window didn't lose focus.
I would suggest you to comment potions of your app's initalization code out until the flashing stops. Then you have a starting point for more research why the focus is lost.
EDIT2:
Without knowing your code I tried to reproduce the phenomenon and it wasn't too hard. Whatever I tried, the focus change always happened when the main window was already shown and had focus.
So the best solution I see is to manually show the main window after calling the splash screen's Close() method:
Remove the StartupUri from App.xaml
Show the SplashScreen after starting the app and initializing ressources. After a (currently fixed) delay close the SplashScreen and show the main window:
public partial class App : Application
{
const int FADEOUT_DELAY = 2000;
SplashScreen splash = new SplashScreen("splash.jpg");
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
splash.Show(false, true);
var worker = new BackgroundWorker();
worker.DoWork += (sender, ea) =>
{
Thread.Sleep(1000);
splash.Close(new TimeSpan(0, 0, 0, 0, FADEOUT_DELAY));
// you could reduce the delay and show the main window with a nice transition
Thread.Sleep(FADEOUT_DELAY);
Dispatcher.BeginInvoke(new Action(() => MainWindow.Show()));
};
worker.RunWorkerAsync();
MainWindow = new MainWindow();
// do more initialization
}
}
Upvotes: 5