Re: Splash Screen - My Nemesis
"Eames, Andrew" <[email protected]> Wed, 25 Jul 2007 15:52:25 -0400
| Newsgroups | gmane.comp.windows.devel.dotnet.winforms |
|---|---|
| Message-ID | <[email protected]> |
I too found a lot of incorrect ways to implement a splash screen. Many
of the public domain implementations I looked at had subtle bugs and/or
race conditions in them too. I ended up writing the following code which
you are welcome to borrow
Andrew
------------------------------------------------------------------------
---------------------------------------------------------------
/// <summary>
/// Class that manages a splash screen
/// </summary>
public class SplashScreen
{
SplashScreen(Form parentForm, Type splashType, TimeSpan timeSpan)
{
parentForm_ = parentForm;
splashType_ = splashType;
timeSpan_ = timeSpan;
culture_ = CultureInfo.CurrentCulture;
parentForm.Shown += new EventHandler(OnParentShown);
Thread t = new Thread(new ThreadStart(SplashThread));
t.Start();
}
// This is the entry point for the thread that the splash screen
runs on
void SplashThread()
{
Thread.CurrentThread.CurrentCulture =
Thread.CurrentThread.CurrentUICulture = culture_;
splashForm_ = (Form)Activator.CreateInstance(splashType_);
splashForm_.TopMost = true;
splashForm_.ShowInTaskbar = false;
splashForm_.FormBorderStyle = FormBorderStyle.FixedToolWindow; //
prevents appearing in alt-TAB
splashForm_.StartPosition = FormStartPosition.CenterScreen;
splashForm_.HandleCreated += delegate {
splashHandleCreated_.Set(); };
using (System.Windows.Forms.Timer timer = new
System.Windows.Forms.Timer())
{
timer.Interval = (int)timeSpan_.TotalMilliseconds;
timer.Tick += delegate { timerExpired_ = true; MaybeClose(); };
timer.Start();
Application.Run(splashForm_);
}
}
void MaybeClose()
{
// We don't close the splash screen until both the timer has
expired and the main form has shown itself
if (timerExpired_ && shown_)
{
// Note: We activate the parent form *before* closing the splash
form, otherwise the windows paint
// in a distracting way
try
{
parentForm_.Invoke(new foo(delegate { parentForm_.Activate();
}));
}
catch (InvalidOperationException)
{
// In case the parent has closed already!!
}
splashForm_.Close();
splashHandleCreated_.Close();
}
}
/// <summary>
/// Executed on the splash form thread
/// </summary>
void OnParentShown()
{
shown_ = true;
MaybeClose();
}
/// <summary>
/// Raised on the thread of the main form
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void OnParentShown(object sender, EventArgs e)
{
parentForm_.Shown -= new EventHandler(OnParentShown);
// If the parent shows itself really quickly, its possible that
the splash screen has
// not yet created its window, which is why we use this event
splashHandleCreated_.WaitOne();
// Note we need to use BeginInvoke to avoid a potential deadlock
since
// the splash form may Invoke an activate right back at us
splashForm_.BeginInvoke(new foo(OnParentShown));
}
/// <summary>
///
/// </summary>
/// <param name="parentForm"></param>
/// <param name="splashType"></param>
/// <param name="time"></param>
public static void Show(Form parentForm, Type splashType, TimeSpan
time)
{
new SplashScreen(parentForm, splashType, time);
}
TimeSpan timeSpan_;
Type splashType_;
Form parentForm_;
Form splashForm_;
CultureInfo culture_;
ManualResetEvent splashHandleCreated_ = new ManualResetEvent(false);
bool shown_;
bool timerExpired_;
}
delegate void foo();
-----Original Message-----
From: Discussion forum for developers using Windows Forms to build apps
and controls [mailto:[email protected]] On Behalf Of
Brady Kelly
Sent: Wednesday, July 25, 2007 3:39 PM
To: [email protected]
Subject: [DOTNET-WINFORMS] Splash Screen - My Nemesis
Yes, I've just spent hours trying various examples that don't work, and
I've
just realised why people Callout actually _sell_ splash screen products.
My
biggest grip so far is that in the compiled app, not in the IDE, my main
window, from which I display my splash screen, always appears in the
background.
My code is outrageously simple, with no status updates or anything:
public SearchGridForm()
{
InitializeComponent();
splashScreen = new SplashScreen();
splashThread = new Thread(new ThreadStart(ShowSplash));
splashThread.Start();
}
private void ShowSplash()
{
splashScreen.ShowDialog();
}
private void SearchGrid_Load(object sender, EventArgs e)
{
try
{
Cursor = Cursors.WaitCursor;
InitControls();
}
finally
{
Cursor = Cursors.Default;
splashThread.Abort();
}
}
--
BEGIN-ANTISPAM-VOTING-LINKS
------------------------------------------------------
NOTE: This message was trained as non-spam. If this is wrong,
please correct the training as soon as possible.
Teach CanIt if this mail (ID 9056513) is spam:
Spam:
http://mail-gw.cognex.com/canit/b.php?c=s&i=9056513&m=08b08c6e418b
Not spam:
http://mail-gw.cognex.com/canit/b.php?c=n&i=9056513&m=08b08c6e418b
Forget vote:
http://mail-gw.cognex.com/canit/b.php?c=f&i=9056513&m=08b08c6e418b
------------------------------------------------------
END-ANTISPAM-VOTING-LINKS