Fragensteller
Eigenartige Reaktion eines Splash-Screens

Frage
-
Hallo zusammen,
ich beginne meine Applications mit einem Splash-Screen. Dieser läuft in einem eigenen Thread. Die Form wird am Anfang mit einem FadeIn-Effekt angezeigt und soll dann mit Opacity 50% zu sehen sein, bis die eigentliche Startform angezeigt wird. Dann wird Splash mit FadeOut-Effekt beendet.
Das Problem ist:
Die Splashform hat die Eigenschaft ShowInTaskbar = False. Wenn ich mein Programm in der IDE debugge, läuft alles großartig. Starte ich es als EXE, passiert Folgendes. Die Splashform wird mittels FadeIn sozusagen aufgeblendet und dann angezeigt mit 50% Opacity. Nach ca. 5 sec verschwindet die Opacity und wird zu 100% und gleichzeitig wird ein undefiniertes Icon (der Splashform) in der Taskbar angezeigt und zwar solange, bis die eigentliche Startform angezeigt wird, die allerdings gewollt in der Taskbar zu sehen sein soll.
Wie gesagt, nur bei Ausführung der EXE passiert geschilderter Effekt. Nun habe ich keine Idee mehr, woran das liegen könnte. Kann leider keinen Code beifügen, weil recht umfangreich...
Kann jemand Tipps geben, bitte?
Grüße-
Dietrich
Alle Antworten
-
Hallo Dietrich,
Kann leider keinen Code beifügen, weil recht umfangreich...
dann musst Du den wohl in einem Beispielprojekt aufs absolut notwendigste reduzieren. Ohne Code können wir dir auch nicht sagen, wo dein Fehler liegt.
Generell dürfte man wohl annehmen, dass die Aktualisierung der Oberfläche durch den separaten Thread nicht sauber läuft. Woran das liegt, kann man aber ohne Code nicht sagen.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport -
OK, ich sende mal den Code der SplashForm.
Imports System.Threading, System.ComponentModel Imports System.Math ''' <summary> ''' Description of Splash. ''' </summary> Friend NotInheritable Class dhOwnSplash Inherits Form #Region "initialisation" Public Sub New() MyBase.New() 'The InitializeComponent() call is required for Windows Forms designer support InitializeComponent() With Me 'Initialise a timer to do the fade out If .components Is Nothing Then .components = New Container() .fadeTimer = New Windows.Forms.Timer(components) End With End Sub Private fadeTimer As Windows.Forms.Timer Public Shared Property k As Single = 0.05 #End Region #Region "Static Methods" Friend Shared Instance As dhOwnSplash = Nothing Friend Shared splashThread As Thread = Nothing Public Shared Sub ShowSplash() 'Show Splash with no fading ShowSplash(0) End Sub Public Shared Sub ShowSplash(fadeinTime As Integer) Dim op As Double, i As Integer = 0 'Only show if not showing already If Instance Is Nothing Then Instance = New dhOwnSplash() With Instance op = .Opacity 'Hide initially so as to avoid a nasty pre paint flicker .Opacity = 0 .Show() 'Process the initial paint events Application.DoEvents() 'Perform the fade in If fadeinTime > 0 Then 'Set the timer interval so that we fade out at the same speed Dim fadeStep As Integer = Round(fadeinTime / (1 / k)) .fadeTimer.Interval = fadeStep While i <= fadeinTime Thread.Sleep(fadeStep) If .Opacity < op Then .Opacity += k Else k = 0 Exit While End If i += fadeStep End While Else 'Set the timer interval so that we fade out instantly .fadeTimer.Interval = 1 End If .Opacity = op End With End If End Sub Public Shared Sub Fadeout() 'Only fadeout if we are currently visible If Instance IsNot Nothing Then Instance.BeginInvoke(New MethodInvoker(AddressOf Instance.Close)) 'Process the Close Message on the Splash Thread Application.DoEvents() End If End Sub #End Region #Region "Close Splash Methods" Protected Overloads Overrides Sub OnClick(ByVal e As System.EventArgs) 'If we are displaying as a about dialog we need to provide a way out Close() End Sub Protected Overloads Overrides Sub OnClosing(e As CancelEventArgs) MyBase.OnClosing(e) With Me 'Close immediatly if the timer interval is set to 1 indicating no fade If .fadeTimer.Interval = 1 Then e.Cancel = False Return End If 'Only use the timer to fade out if we have a mainform running 'otherwise there will be no message pump If Application.OpenForms.Count > 1 Then If .Opacity > 0 Then e.Cancel = True .Opacity -= 0.05 RemoveHandler .fadeTimer.Tick, AddressOf FadeoutTick AddHandler .fadeTimer.Tick, AddressOf FadeoutTick 'use the timer to iteratively call the close method 'thereby keeping the GUI thread available for other processes .fadeTimer.Start() Else e.Cancel = False .fadeTimer.Stop() 'Clear the instance variable so we can reshow the splash 'and ensure that we don't try to close it twice Instance = Nothing End If Else If .Opacity > 0 Then 'Sleep on this thread to slow down the fade as there is no message pump running Thread.Sleep(.fadeTimer.Interval) Instance.Opacity -= k 'iteratively call the close method .Close() Else e.Cancel = False 'Clear the instance variable so we can reshow the splash 'and ensure that we don't try to close it twice Instance = Nothing End If End If End With End Sub Private Sub FadeoutTick(sender As Object, e As System.EventArgs) Close() End Sub #End Region #Region "Designer stuff" ''' <summary> ''' Designer variable used to keep track of non-visual components. ''' </summary> Private components As IContainer = Nothing ''' <summary> ''' Disposes resources used by the form. ''' </summary> ''' <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) If disposing Then If components IsNot Nothing Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub ''' <summary> ''' This method is required for Windows Forms designer support. ''' Do not change the method contents inside the source code editor. The Forms designer might ''' not be able to load this method if it was changed manually. ''' </summary> Private Sub InitializeComponent() SuspendLayout() ' 'dhOwnSplash ' BackColor = Color.Black BackgroundImageLayout = ImageLayout.None ClientSize = New System.Drawing.Size(200, 100) FormBorderStyle = FormBorderStyle.None MaximizeBox = False MinimizeBox = False Name = "dhOwnSplash" Opacity = 0.5R ShowInTaskbar = False StartPosition = FormStartPosition.CenterScreen TransparencyKey = Color.Transparent ResumeLayout(False) End Sub #End Region End Class
In einer SubMain starte ich:
''' <summary> ''' Description of Start. ''' </summary> Public Class Start <MTAThread> Public Shared Sub Main(ByVal args As String()) Application.EnableVisualStyles() Application.SetCompatibleTextRenderingDefault(False) dhOwnSplash.ShowSplash(1000) Application.Run(New frmListing()) End Sub End Class
Mit dhOwnSplash.. die SplashForm und frmListing.. meine Startform dr Application.
Grüße-
Dietrich
-
Hallo, ich muss noch was ergänzen:
Während der SplashScreen läuft, wird ja die StartForm der Application geladen und da läuft gleich zu Anfang der folgende Code:
Using New PleaseWait(dhClockForm) ..... End Using ' dhClockForm ist eine Stoppuhr ' und bei ..... werden bspw. SQL-Tabellen geladen
PleaseWait ist folgender Code:
Imports System.Threading Public Class PleaseWait Implements IDisposable Private waitSplash As Form Public Sub New(ByVal theWaitingForm As Form) If IsNothing(theWaitingForm) Then Exit Sub waitSplash = theWaitingForm Dim thr As Thread = New Thread(New ThreadStart(AddressOf workerThread)) thr.Start() End Sub Private Sub workerThread() Application.Run(waitSplash) End Sub Public Sub Dispose() Implements IDisposable.Dispose If waitSplash Is Nothing Then Exit Sub waitSplash.Invoke(New MethodInvoker(AddressOf stopThread)) End Sub Private Sub stopThread() waitSplash.Close() End Sub End Class
Möglicherweise löst PleaseWait (anderer Thread als SplashForm) dieses Verhalten wie im 1. Post beschrieben aus...?
Grüße-
Dietrich