
Signature
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
Jeffrey,
This is very close to what I need. My problem now is when I call the Invoke
my program stops. This becomes a block. I think it is becuase my form is
not displayed yet. I am trying to make my splash screen a little more
interactive where it display the status while it is loading, and I think
this is causing the problem.
I actually call and display the splash screen before my main application has
run, as I do a lot of checking and validation. Every thing seems great
until I try to close the splash screen. I try to close it from my
application to make sure that everything has completed. Is there an event
on a Windows Form that tells you when it is displayed?
Basically here is how I call it.
In my class PreLoader.cs, which has my "static void Main()" I call,
DOTTime.Splash.SplashScreen.Display with the proper paramaters. I call
DOTTime.Splash.SplashScreen.UpdateStep to move the progress bar.
When I finally do Application.Run on my Main form I set the property
SetFormToBrinToFront = this, which is my main application form, and in the
Load event for that form I call the last UpdateStep which should close the
splash screen form. When that form closes it seems to take my main form to
the background. I even tried to put a this.BringToFront() in the Load event
for the main form, but that didn't work either.
Any more suggestions?
Eric Renken
Here is the code to my splash screen:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Threading;
namespace DOTTime.Splash
{
/// <summary>
/// Summary description for SplashScreen.
/// </summary>
public class SplashScreen : System.Windows.Forms.Form
{
private delegate void SetStepHandler( string step );
private static SplashScreen _SplashScreen = null;
private Form _FormToFront = null;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label lblVersion;
private System.Windows.Forms.ProgressBar progress;
private System.Windows.Forms.Label lblStep;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public SplashScreen( string title, Image background, string version, int
totalSteps )
{
InitializeComponent();
this.BackgroundImage = background;
this.Size = background.Size;
this.Text = title;
lblVersion.Text = "Version: " + version;
progress.Maximum = totalSteps;
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
public void SetStep( string step )
{
if ( lblStep.Text != step )
progress.Value ++;
lblStep.Text = step;
lblStep.Refresh();
if ( progress.Value == progress.Maximum )
{
Thread.Sleep( 1000 );
this.Close();
}
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.Resources.ResourceManager resources = new
System.Resources.ResourceManager(typeof(SplashScreen));
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.lblVersion = new System.Windows.Forms.Label();
this.progress = new System.Windows.Forms.ProgressBar();
this.lblStep = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label2
//
this.label2.Anchor =
((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom
| System.Windows.Forms.AnchorStyles.Left)));
this.label2.BackColor = System.Drawing.Color.Transparent;
this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
((System.Byte)(0)));
this.label2.Location = new System.Drawing.Point(8, 158);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(336, 16);
this.label2.TabIndex = 5;
this.label2.Text = "Copyright ? 2004 Exaktime, Inc. All rights
reserved";
//
// label3
//
this.label3.Anchor =
((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom
| System.Windows.Forms.AnchorStyles.Left)));
this.label3.BackColor = System.Drawing.Color.Transparent;
this.label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
((System.Byte)(0)));
this.label3.Location = new System.Drawing.Point(8, 174);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(336, 16);
this.label3.TabIndex = 4;
this.label3.Text = "Using the .TimeT framework created by Exaktime,
Inc.";
//
// lblVersion
//
this.lblVersion.Anchor =
((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom
| System.Windows.Forms.AnchorStyles.Left)));
this.lblVersion.BackColor = System.Drawing.Color.Transparent;
this.lblVersion.Font = new System.Drawing.Font("Microsoft Sans Serif",
8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
((System.Byte)(0)));
this.lblVersion.Location = new System.Drawing.Point(8, 142);
this.lblVersion.Name = "lblVersion";
this.lblVersion.Size = new System.Drawing.Size(336, 16);
this.lblVersion.TabIndex = 6;
this.lblVersion.Text = "Version:";
//
// progress
//
this.progress.Anchor =
((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom
| System.Windows.Forms.AnchorStyles.Left)));
this.progress.Location = new System.Drawing.Point(8, 78);
this.progress.Name = "progress";
this.progress.Size = new System.Drawing.Size(376, 16);
this.progress.TabIndex = 7;
//
// lblStep
//
this.lblStep.Anchor =
((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom
| System.Windows.Forms.AnchorStyles.Left)));
this.lblStep.BackColor = System.Drawing.Color.Transparent;
this.lblStep.Font = new System.Drawing.Font("Microsoft Sans Serif",
8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
((System.Byte)(0)));
this.lblStep.Location = new System.Drawing.Point(8, 62);
this.lblStep.Name = "lblStep";
this.lblStep.Size = new System.Drawing.Size(376, 16);
this.lblStep.TabIndex = 8;
this.lblStep.Text = "Initializing...";
//
// SplashScreen
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 13);
this.ClientSize = new System.Drawing.Size(400, 200);
this.Controls.Add(this.lblStep);
this.Controls.Add(this.progress);
this.Controls.Add(this.lblVersion);
this.Controls.Add(this.label2);
this.Controls.Add(this.label3);
this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F,
System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point,
((System.Byte)(0)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "SplashScreen";
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "SplashScreen";
this.Closing += new
System.ComponentModel.CancelEventHandler(this.SplashScreen_Closing);
this.ResumeLayout(false);
}
#endregion
public static void Display( string title, Image background, string
version, int totalSteps )
{
if ( _SplashScreen != null )
{
_SplashScreen.Dispose();
_SplashScreen = null;
}
_SplashScreen = new SplashScreen( title, background, version,
totalSteps );
Thread splash = new System.Threading.Thread( new ThreadStart(
SplashScreen.ShowSplashScreen ) );
splash.Name = "Start Splash Screen";
splash.Priority = System.Threading.ThreadPriority.Normal;
splash.Start();
}
internal Form FormToBringToFront
{
set { _FormToFront = value; }
}
public static Form SetFormToBringToFront
{
set { _SplashScreen.FormToBringToFront = value; }
}
public static Form SplashForm
{
get { return _SplashScreen; }
}
private static void ShowSplashScreen()
{
Application.Run( _SplashScreen );
}
public static void CloseSplash()
{
if ( _SplashScreen != null )
{
_SplashScreen.Close();
}
}
public static void UpdateStep( string step )
{
int worker = 0;
int port = 0;
while ( worker < 5 )
{
ThreadPool.GetAvailableThreads( out worker, out port );
Thread.Sleep( 1 );
}
ThreadPool.QueueUserWorkItem( new WaitCallback( UpdateStepWorker ),
(object)step );
}
private static void UpdateStepWorker( object step )
{
SetStepHandler ssh = new SetStepHandler( _SplashScreen.SetStep );
_SplashScreen.Invoke( ssh, new object [] { step } );
ssh = null;
}
private void SplashScreen_Closing(object sender,
System.ComponentModel.CancelEventArgs e)
{
if ( _FormToFront != null )
{
MethodInvoker mi = new MethodInvoker( _FormToFront.BringToFront );
_FormToFront.Invoke( mi );
}
}
}
}

Signature
Eric Renken
www.demiurge.us
> Hi Eric,
>
[quoted text clipped - 62 lines]
> Get Secure! - www.microsoft.com/security
> This posting is provided "as is" with no warranties and confers no rights.
"Jeffrey Tan[MSFT]" - 21 Mar 2005 04:07 GMT
Hi Eric,
Thanks for your feedback.
I have tried your code like this:
[STAThread]
static void Main()
{
Image img=Image.FromFile("D:\\temp\\Sunset.jpg");
//Application.Run(new DOTTime.Splash.SplashScreen("Test Title", img, "Test
version", 10));
DOTTime.Splash.SplashScreen.Display("Test Title", img, "Test version",
100);
DOTTime.Splash.SplashScreen.UpdateStep("step");
}
But I got a unhandled exception at _SplashScreen.Invoke( ssh, new object []
{ step } ); in UpdateStepWorker() method:
An unhandled exception of type 'System.InvalidOperationException' occurred
in system.windows.forms.dll
Additional information: Cannot call Invoke or InvokeAsync on a control
until the window handle has been created.
I think I did something wrong in the void Main method. I suggest you attach
a sample project for me in another reply, then I can reproduce out your
issue well and help you better. Thanks for your understanding.
Additionally, in your code, I found that you used thread very strange:
In main thread(main method), first in Display method, you create out the
SplashScreen form in a second thread, which is the current UI thread. Then
in main thread, you invoked UpdateStep method, which uses threadpool to
create out a third thread, which executes UpdateStepWorker method(then
SetStep method). Now it is the key point: in the third thread(SetStep
method), you manipulate lblStep label control(which is on the second
thread) directly. However, we should always invoke the UI thread's method
with Control.Invoke method or BeginInvoke, EndInvoke methods. This is the
only safe way for other threads to manipulate the UI thread. This is
documented in Control.Invoke Method, you may refer to it.
For more information about how to do safe multithreading, please refer to
Chris Sells' articles:
"Safe, Simple Multithreading in Windows Forms, Part 1"
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnforms/htm
l/winforms06112002.asp
============================================================================
========================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.
Best regards,
Jeffrey Tan
Microsoft Online Partner Support

Signature
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
Eric Renken - 22 Mar 2005 17:45 GMT
I will create a sample project. Do just want me to attach it here in the
newsgroups? I can.
I was only trying that ThreadPool because I was getting blocking on that
thread when the main program would call it for completion.

Signature
Eric Renken
www.demiurge.us
> Hi Eric,
>
[quoted text clipped - 53 lines]
> Get Secure! - www.microsoft.com/security
> This posting is provided "as is" with no warranties and confers no rights.
"Jeffrey Tan[MSFT]" - 23 Mar 2005 07:40 GMT
Hi Eric,
Thanks for your feedback!
Yes, to benefit the entire newsgroup, we suggest you attach the sample
project in the reply, then I will refer and download it to have a test. I
will want for your further reply. Thanks
Best regards,
Jeffrey Tan
Microsoft Online Partner Support

Signature
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
Eric Renken - 24 Mar 2005 20:15 GMT
Jeffery,
Well I tried to attach the project but 74K is to big to upload to these
newsgroups, so I posted the zip on my website. I could split the message
but this just seems easier. Anyone can download it from:
http://www.demiurge.us/SplashTest.zip
I was able to reproduce that error that you had
in the Invoke and I think that is a timing issue, as adding some sleeps to
the process worked. That isn't the solution that I want to stay with
either. Is there a way to tell when the screen has been painted on the
screen? I would like the UpdateStep to block until the Splash Screen has
been painted.
Thanks for all the help.

Signature
Eric Renken
www.demiurge.us
> Hi Eric,
>
[quoted text clipped - 9 lines]
> Get Secure! - www.microsoft.com/security
> This posting is provided "as is" with no warranties and confers no rights.
"Jeffrey Tan[MSFT]" - 29 Mar 2005 03:07 GMT
Hi Eric,
Have you seen my last reply? Does it make sense to you? Please feel free to
tell me, thanks.
Best regards,
Jeffrey Tan
Microsoft Online Partner Support

Signature
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
Eric Renken - 29 Mar 2005 04:25 GMT
I only see this reply and the one where you wanted me to post a sample.

Signature
Eric Renken
www.demiurge.us
> Hi Eric,
>
[quoted text clipped - 7 lines]
> Get Secure! - www.microsoft.com/security
> This posting is provided "as is" with no warranties and confers no rights.
"Jeffrey Tan[MSFT]" - 30 Mar 2005 06:50 GMT
Hi Eric,
Oh, I think there must be some problem with your newsgroup explorer.
Anyway, can you provide a valid email address for me? Then I will send the
modified project to you directly(You may also contact me directly with
removing the word "online" from my email address in this reply). Thanks
Best regards,
Jeffrey Tan
Microsoft Online Partner Support

Signature
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
"Jeffrey Tan[MSFT]" - 01 Apr 2005 02:55 GMT
Hi Eric,
Have you succesfully got my sample project? Is your problem resolved?
Please feel free to tell me, thanks
Best regards,
Jeffrey Tan
Microsoft Online Partner Support

Signature
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
Eric Renken - 01 Apr 2005 04:39 GMT
I just sent you an email.

Signature
Eric Renken
www.demiurge.us
> Hi Eric,
>
[quoted text clipped - 6 lines]
> Get Secure! - www.microsoft.com/security
> This posting is provided "as is" with no warranties and confers no rights.
Alex Singuin - 17 Apr 2005 23:46 GMT
I run it to the same problem and solve it by using
this.Activate();
Hope this will help.