sgaggerj
asked on
VB.Net Ensure a form is displayed before continuing
Hi Experts,
I am creating an app that will have a splash screen (a dialog) that displays loading information to the user while the rest of the app is loading in the background.
When the rest of the app is done loading, the splash screen will close and the main form will be displayed.
I'm having trouble getting that working....
I have set the startup form to my splash dialog, and shutdown mode to when last form closes.
Problem: The splash screen is never 'visible' until AFTER the main window is displayed. It should be visible from the moment the app executes, displaying the animation of 1 image fading to another (and later progress bar animation and status text updates)
Any suggestions?
Here is the code for my splash dialog
and the code for my main form
I am creating an app that will have a splash screen (a dialog) that displays loading information to the user while the rest of the app is loading in the background.
When the rest of the app is done loading, the splash screen will close and the main form will be displayed.
I'm having trouble getting that working....
I have set the startup form to my splash dialog, and shutdown mode to when last form closes.
Problem: The splash screen is never 'visible' until AFTER the main window is displayed. It should be visible from the moment the app executes, displaying the animation of 1 image fading to another (and later progress bar animation and status text updates)
Any suggestions?
Here is the code for my splash dialog
Option Strict On
Option Explicit On
Imports System.Drawing.Imaging
Public Class Splash
#Region "Delegates "
Private Delegate Sub CloseWindowDelegate()
#End Region
#Region "Variables "
Private m_Alpha As Single = 0 ' Alpha on a 0-1 scale.
Private m_DAlpha As Single = 0.05
Private image1 As Bitmap = My.Resources.image_1
Private image2 As Bitmap = My.Resources.image_2
Private animating As Boolean
#End Region
Public Sub New()
InitializeComponent()
' Start the animation
tmrDisplayFrame.Enabled = True
tmrDisplayFrame.Start()
Dim MainWindow As New MainForm(AddressOf CloseWindow)
Dim t As New System.Threading.Thread(AddressOf MainWindow.Initialize)
t.Start()
While t.IsAlive
System.Windows.Forms.Application.DoEvents()
End While
tmrDisplayFrame.Enabled = False
tmrDisplayFrame.Stop()
tmrDisplayFrame = Nothing
While animating
System.Windows.Forms.Application.DoEvents()
End While
MainWindow.Show()
End Sub
#Region "Subs "
Private Sub CloseWindow()
If Me.InvokeRequired Then
Dim shd As New CloseWindowDelegate(AddressOf CloseWindow)
Me.Invoke(shd)
Else
Me.Close()
End If
End Sub
#End Region
#Region "Handlers "
Private Sub tmrDisplayFrame_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrDisplayFrame.Tick
animating = True
System.Windows.Forms.Application.DoEvents()
Dim image_attr As New ImageAttributes
Dim cm As ColorMatrix
Dim bm As New Bitmap(image1.Width, image1.Height)
Dim gr As Graphics = Graphics.FromImage(bm)
Dim rect As Rectangle = Rectangle.Round(image1.GetBounds(GraphicsUnit.Pixel))
cm = New ColorMatrix(New Single()() { _
New Single() {1.0, 0.0, 0.0, 0.0, 0.0}, _
New Single() {0.0, 1.0, 0.0, 0.0, 0.0}, _
New Single() {0.0, 0.0, 1.0, 0.0, 0.0}, _
New Single() {0.0, 0.0, 0.0, 0.0, 0.0}, _
New Single() {0.0, 0.0, 0.0, m_Alpha, 1.0}})
image_attr.SetColorMatrix(cm)
gr.DrawImage(image1, rect, 0, 0, image1.Width, image2.Width, GraphicsUnit.Pixel, image_attr)
cm = New ColorMatrix(New Single()() { _
New Single() {1.0, 0.0, 0.0, 0.0, 0.0}, _
New Single() {0.0, 1.0, 0.0, 0.0, 0.0}, _
New Single() {0.0, 0.0, 1.0, 0.0, 0.0}, _
New Single() {0.0, 0.0, 0.0, 0.0, 0.0}, _
New Single() {0.0, 0.0, 0.0, 1 - m_Alpha, 1.0}})
image_attr.SetColorMatrix(cm)
gr.DrawImage(image2, rect, 0, 0, image1.Width, image2.Width, GraphicsUnit.Pixel, image_attr)
picResult.Width = image1.Width
picResult.Height = image1.Height
picResult.BackgroundImage = bm
picResult.Refresh()
m_Alpha += m_DAlpha
If m_Alpha > 1 Then
m_Alpha = 1
m_DAlpha *= -1
ElseIf m_Alpha < 0 Then
m_Alpha = 0
m_DAlpha *= -1
End If
System.Windows.Forms.Application.DoEvents()
animating = False
End Sub
#End Region
End Class
and the code for my main form
Option Strict On
Option Explicit On
Public Class MainForm
#Region "Delegates "
Public Delegate Sub CloseSplashWindowDelegate()
#End Region
#Region "Variables "
Private CloseSplashWindow As CloseSplashWindowDelegate
Private WithEvents CloseSplashTimer As Timers.Timer
#End Region
Public Sub New(ByVal _csw As CloseSplashWindowDelegate)
InitializeComponent()
CloseSplashWindow = _csw
End Sub
#Region "Public Subs "
Public Sub Initialize()
Dim s As DateTime = Now.AddSeconds(15)
While Now < s
System.Windows.Forms.Application.DoEvents()
End While
CloseSplashTimer = New Timers.Timer
With CloseSplashTimer
.AutoReset = False
.Interval = 1000
.Start()
End With
End Sub
#End Region
#Region "Private Subs "
Private Sub LoadExistingServers()
End Sub
#End Region
#Region "Handlers "
Private Sub AddNewServerToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles AddNewServerToolStripMenuItem.Click
End Sub
Private Sub RemoveCurrentServerToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles RemoveCurrentServerToolStripMenuItem.Click
End Sub
Private Sub ExitToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles ExitToolStripMenuItem.Click
Application.Exit()
End Sub
Private Sub CloseSplashTimer_Elapsed(sender As Object, e As System.Timers.ElapsedEventArgs) Handles CloseSplashTimer.Elapsed
CloseSplashWindow.Invoke()
End Sub
#End Region
End Class
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
"I have set the startup form to my splash dialog, and shutdown mode to when last form closes."
You've over complicated this in a big way!...
This bit of code:
Get rid of all that manual threading code.
In Project --> Properties, leave your main form as the "startup object/form", and set your splash dialog as the "splash screen".
Now, to control how long your splash is displayed, override the MinimumSplashScreenDisplay Time property:
http://msdn.microsoft.com/en-us/library/ms234874(VS.80).aspx
"Determines the minimum length of time, in milliseconds, for which the splash screen is displayed."
To do this, click on Project --> Properties, then click on the "View Application Events" button in the bottom right. You should see this code:
Inside the "MyApplication" class portion is where you'd place the sample overrided from the MSDN link:
This will cause the splash screen to automatically close after the minimum time and your main startup form will then be loaded for you.
If your main form is doing actual work, and you want it to communicate with your splash screen, then see my article here:
https://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/A_3671-Updating-a-Splash-Screen-with-Loading-Progress-in-a-VB-Net-WinForms-Application.html
You've over complicated this in a big way!...
This bit of code:
Dim s As DateTime = Now.AddSeconds(15)
While Now < s
System.Windows.Forms.Application.DoEvents()
End While
*implies that you have no "real work" in the loading of your main form. You simply want your splash form to appear for 15 seconds?! That's a long time to wait for nothing...Get rid of all that manual threading code.
In Project --> Properties, leave your main form as the "startup object/form", and set your splash dialog as the "splash screen".
Now, to control how long your splash is displayed, override the MinimumSplashScreenDisplay
http://msdn.microsoft.com/en-us/library/ms234874(VS.80).aspx
"Determines the minimum length of time, in milliseconds, for which the splash screen is displayed."
To do this, click on Project --> Properties, then click on the "View Application Events" button in the bottom right. You should see this code:
Namespace My
' The following events are available for MyApplication:
'
' Startup: Raised when the application starts, before the startup form is created.
' Shutdown: Raised after all application forms are closed. This event is not raised if the application terminates abnormally.
' UnhandledException: Raised if the application encounters an unhandled exception.
' StartupNextInstance: Raised when launching a single-instance application and the application is already active.
' NetworkAvailabilityChanged: Raised when the network connection is connected or disconnected.
Partial Friend Class MyApplication
End Class
End Namespace
Inside the "MyApplication" class portion is where you'd place the sample overrided from the MSDN link:
Namespace My
' The following events are available for MyApplication:
'
' Startup: Raised when the application starts, before the startup form is created.
' Shutdown: Raised after all application forms are closed. This event is not raised if the application terminates abnormally.
' UnhandledException: Raised if the application encounters an unhandled exception.
' StartupNextInstance: Raised when launching a single-instance application and the application is already active.
' NetworkAvailabilityChanged: Raised when the network connection is connected or disconnected.
Partial Friend Class MyApplication
Protected Overrides Function OnInitialize( _
ByVal commandLineArgs As _
System.Collections.ObjectModel.ReadOnlyCollection(Of String) _
) As Boolean
' Set the display time to 15 seconds:
Me.MinimumSplashScreenDisplayTime = TimeSpan.FromSeconds(15).TotalMilliseconds
Return MyBase.OnInitialize(commandLineArgs)
End Function
End Class
End Namespace
This will cause the splash screen to automatically close after the minimum time and your main startup form will then be loaded for you.
If your main form is doing actual work, and you want it to communicate with your splash screen, then see my article here:
https://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/A_3671-Updating-a-Splash-Screen-with-Loading-Progress-in-a-VB-Net-WinForms-Application.html
ASKER
The reason I set the 15 sec delay there was to simulate work being done in the main form that I haven't added yet. The main form will be loading several tables that are 28k and 92k rows in length as well as using that data to populate combo boxes etc.
The 15 sec was to get a good idea of how the splash screen was working, but as you said a long time.
I'll look at your post tomorrow and see what I can do with it. The main form will be communicating with the splash screen to report progress.
I'm not sure I could calculate how long the loading process would take as every pc is slower/faster than another and not all users will have the db local to the app. This is why I was figuring to do the loading the way I did so that as soon as it was done it would display, whether it took 5 sec or 5 min to load everything.
I'll give those posts a read and see what I can learn.
Thanks!
The 15 sec was to get a good idea of how the splash screen was working, but as you said a long time.
I'll look at your post tomorrow and see what I can do with it. The main form will be communicating with the splash screen to report progress.
I'm not sure I could calculate how long the loading process would take as every pc is slower/faster than another and not all users will have the db local to the app. This is why I was figuring to do the loading the way I did so that as soon as it was done it would display, whether it took 5 sec or 5 min to load everything.
I'll give those posts a read and see what I can learn.
Thanks!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
That's exactly what I was needing!
Just needed to make the calls to the picturebox (picResult) thread friendly and it's working like I wanted!
Just needed to make the calls to the picturebox (picResult) thread friendly and it's working like I wanted!
ASKER