none
Eigenartige Reaktion eines Splash-Screens RRS feed

  • 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

    Dienstag, 16. Juni 2020 08:25

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

    Dienstag, 16. Juni 2020 08:45
    Moderator
  • 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

    Dienstag, 16. Juni 2020 09:45
  • 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

    Montag, 22. Juni 2020 09:02