Re: Splash Screen - My Nemesis

Greg Robinson <[email protected]> Thu, 26 Jul 2007 07:28:37 -0400
Newsgroups gmane.comp.windows.devel.dotnet.winforms
Message-ID <[email protected]>
Exception Handling is ignored in the Load.



-----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 4:49 PM
To: [email protected]
Subject: Re: [DOTNET-WINFORMS] Splash Screen - My Nemesis


Thank you so much Andrew!  This is the first code I've found tonight that
worked a anything like it should, and I all wanted to do was 'whip out a
splash screen quickly' for a small side project.  Whew!

However, I have one problem: I'm using the splash screen to show while I
query a database during the form load event handler.  If I get an error in
this method, the splash screen simply hangs.  I tried adding a static
Abort() method to the Splash class, which works but I still get different
behaviours in the IDE and compiled.

First, in the IDE, I get my desired MessageBox, but it the compiled app
there is none.  Here is my use of your code:

        private void SearchGrid_Load(object sender, EventArgs e)
        {
            try
            {
                SplashManager.Show(this, typeof(SplashScreen), new
TimeSpan(0, 0, 0, 0, 500));
                InitControls();
            }
            catch (Exception ex)
            {
                LogException(ex);
                SplashManager.Abort();
                MessageBox.Show(this, ex.Message, "Startup Error",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
                Close();
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }



> -----Original Message-----
> From: Discussion forum for developers using Windows Forms to build apps
> and controls [mailto:[email protected]] On Behalf Of
> Eames, Andrew
> Sent: 25 July 2007 21:52 PM
> To: [email protected]
> Subject: Re: [DOTNET-WINFORMS] Splash Screen - My Nemesis
>
> 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