Reputation: 137682
My WinForms app's main window is slow to load (up to 20 seconds, depending on arguments), so it needs a splash screen.
The main window constructor is slow because it exercises thousands of lines of code (some of it beyond my influence). Sometimes this code pops up message boxes.
I've tried two splash screen designs, they each have problems. Any better ideas?
static void Main(string[] args)
{
var splash = !args.Contains("--no-splash");
if (splash)
{
var bw = new BackgroundWorker();
bw.DoWork += (sender, eventArgs) => ShowSplash();
bw.RunWorkerAsync();
}
var app = new FormMain(args); // slow. sometimes opens blocking message boxes.
Application.Run(app);
}
private static void ShowSplash()
{
using (var splash = new FormSplash())
{
splash.Show();
splash.Refresh();
Thread.Sleep(TimeSpan.FromSeconds(2));
}
}
Problems:
sealed class App : WindowsFormsApplicationBase
{
protected override void OnCreateSplashScreen()
{
this.SplashScreen = new FormSplash();
}
protected override void OnCreateMainForm()
{
// slow. sometimes opens blocking message boxes.
this.MainForm = new FormMain(this.CommandLineArgs);
}
}
Problems:
Upvotes: 0
Views: 3561
Reputation: 137682
In the end, moved the slow code from the constructor to a handler for the OnShown event.
Used WindowsFormsApplicationBase
for splash screen as Hans Passant suggested, carefully checked the remaining constructor code to make sure it'll never open an message boxes.
Upvotes: -1
Reputation: 4221
I agree with Hans Passant in that the code needs to be re-evaluated as the design seems incorrect.
As for the problem at hand, you should be able to resolve this by creating your own instance of a messageBox.
I tested using this code;
public DialogResult TopMostMessageBox(string message, string title, MessageBoxButtons button, MessageBoxIcon icon)
{
return DisplayMessageBox(message, title, button, icon);
}
public DialogResult DisplayMessageBox(string message, string title, MessageBoxButtons buttons, MessageBoxIcon icon)
{
DialogResult result;
using (var topmostForm = new Form {Size = new System.Drawing.Size(1, 1), StartPosition = FormStartPosition.Manual})
{
var rect = SystemInformation.VirtualScreen;
topmostForm.Location = new System.Drawing.Point(rect.Bottom + 10, rect.Right + 10);
topmostForm.Show();
topmostForm.Focus();
topmostForm.BringToFront();
topmostForm.TopMost = true;
result = MessageBox.Show(topmostForm, message, title, buttons, icon);
topmostForm.Dispose();
}
//You might not need all these properties...
return result;
}
//Usage
TopMostMessageBox("Message","Title" MessageBoxButtons.YesNo, MessageBoxIcon.Question)
Again, I need to stress that I agree that the original code needs to be re-factored and am only providing a possible solution to the question.
Hope this helps?
Upvotes: 3
Reputation: 2448
You can implement our own message box and use TopMost
property, with TopMost
you will get message in-front of splash screen loader.
More about topmost: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.topmost.aspx
Upvotes: 0