Reputation: 199
I am working with Windows forms. I have set up a splash screen to appear when opening the program like this.
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.FormBorderStyle = FormBorderStyle.None;
}
private void timer1_Tick(object sender, EventArgs e)
{
progressBar1.Increment(15);
if (progressBar1.Value == 30) timer1.Stop();
}
It has a progress bar and a timer. I got the idea from another post here. This is working OK, the splash screen is appearing as it should. On the windows form to appear after this I have:
Thread t = new Thread(new ThreadStart(splash));
t.Start();
Thread.Sleep(2000);
InitializeComponent();
t.Abort();
The problem is as follows. When I open the exe, the splash screens appear for about 2 secs as it should, and then when it goes away, the next form appears a second and then goes behind every other window I have opened.
Do you know how can I fix it?
Update 1:
public void splash()
{
System.Windows.Forms.Application.Run(new Form2());
}
This is my splash screen
Final Update:
I got it to work this way.
Splash splash = new Splash();
Instalador instalador = new Instalador();
splash.Show();
Thread.Sleep(2 * 1000);
splash.Close();
Application.Run(instalador);
This on the main. I do not know how OK is this, but it works.
Upvotes: 2
Views: 2274
Reputation: 59
After long time struggle i got the solution. Use the code into Login Form (Form_Load) this.Activate(); Example:
private void login_Load(object sender, EventArgs e)
{
this.Activate();
}
Upvotes: 2
Reputation: 645
To answer your specific question, you might get away with just adding this.Activate()
after InitializeComponent
Thread t = new Thread(new ThreadStart(splash));
t.Start();
Thread.Sleep(2000);
InitializeComponent();
this.Activate();
t.Abort();
However, at the very least, implement handshaking that shuts down the splash screen nicely rather than just aborting the thread.
Also, depending on exactly what you're doing in your splash screen thread, there may be a multitude of subtle issues - e.g. the Z-ordering issue you're currently having.
Typically, I launch my splash screens from Main() before Application.Run({main form})
and also call Application.Run({splashScreen})
from it's thread handler. Application.Run has thread affinity so the splash screen will get its own ApplicationContext
which will properly hook Closing/Closed events to shutdown the thread and raise ThreadExit
just by invoking or beginInvoking SplashScreen.Close()
(typically from MainForm_Shown
event handler). It also has other minor benefits such as Application.OpenForms
containing the splash screen.
Taking this route has pretty much eliminated my bugs and frustrations with splash screens.
-Begin Edit-
A more thorough example:
Start up the second thread and ApplicationContext
in Main()
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Thread t = new Thread(new ThreadStart(splash));
t.IsBackground = true;
t.SetApartmentState(ApartmentState.STA);
t.Start();
Application.Run(new Form1());
}
private static void splash()
{
Application.Run(new Form2());
}
}
Splash screen with a SetProgress
method added so you can update it externally if you wish.
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
timer1.Start();
}
public void SetProgress()
{
if (this.InvokeRequired) //Should have been handled by SplashScreenHandler but check just in case.
this.BeginInvoke(new Action(SetProgress));
progressBar1.Increment(15);
}
private void timer1_Tick(object sender, EventArgs e)
{
progressBar1.Increment(15);
if (progressBar1.Value == 30) timer1.Stop();
}
}
Main form: Notice nothing in constructor and the Shown
event handler shuts down the splash screen(s) without having to carry in a reference (if you're going to instead rely on the timer for status updates.)
public partial class Form1 : Form
{
public Form1()
{
//Simulate a long init
Thread.Sleep(2000);
InitializeComponent();
}
private void Form1_Shown(object sender, EventArgs e)
{
foreach (var splashScreen in Application.OpenForms.OfType<Form2>())
{
splashScreen.BeginInvoke( (Action) delegate () { splashScreen.Close(); });
}
}
}
-End Edit-
Upvotes: 3
Reputation: 622
I had the same issue and after stuggling for a very long time I ended up doing the following in the Load event of the main form after closing the splash screen:
//Manually activate frmMain as it gets back in the Z-order by Windows when splash screen closes.
NativeMethods.SetForegroundWindow(this.Handle);
this.Activate();
Where "SetForegroundWindow" is defined as follows:
/// <summary>
/// Sets foreground window
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
[DllImport("user32.dll")]
internal static extern bool SetForegroundWindow(IntPtr hWnd);
That being said we probably need to see more of your code.
Upvotes: 0