我正在尝试在Windows窗体顶部使用加载叠加层,在窗体顶部添加50%不透明图层并加载GIF,同时它在后台线程中执行它需要做的事情。叠加层是我在onPaint事件中绘制的窗体。
加载叠加层在多个不同的表单加载时工作正常,但在召唤时无法正常工作以确保在30秒上载过程中耐心(将Word文档打印到PDF,然后将该PDF上载到SQL Server)。此上载从表单收集一些数据,将其放入Object,然后完全在后台线程上运行。加载覆盖图将出现,显示第一帧加载GIF,然后只是冻结。 onPaint被触发并且图像框架正在更新,但它不可见
构造函数将表单设置为UserPainted:
Sub New()
InitializeComponent()
SetStyle(ControlStyles.UserPaint Or ControlStyles.Opaque, True)
End Sub
然后,在Form.Shown事件中调用ImageAnimator.Animate方法:
Private Sub LoadingOverlay_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
If Not currentlyAnimating Then
ImageAnimator.Animate(animatedImage, AddressOf Me.OnFrameChanged)
currentlyAnimating = True
End If
End Sub
onFrameChanged事件处理程序只是使表单无效:
Private Sub OnFrameChanged(ByVal sender As Object, ByVal e As System.EventArgs)
'Force a call to onPaint
Me.Invalidate()
End Sub
然后重写onPaint并完成绘图:
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
MyBase.OnPaint(e)
'Get the next frame ready for rendering
ImageAnimator.UpdateFrames()
'Draw the next frame in the animation.
e.Graphics.DrawImage(Me.animatedImage, GetCenter(Me.animatedImage.Size))
TextRenderer.DrawText(e.Graphics, strStatus, Me.Font, GetTextLocation(Me.animatedImage.Size), Color.White, Color.Black)
End Sub
最后,在Form Closing事件中调用ImageAnimator.StopAnimate方法:
Private Sub LoadingOverlay_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
If currentlyAnimating Then
ImageAnimator.StopAnimate(animatedImage, AddressOf Me.OnFrameChanged)
currentlyAnimating = False
End If
End Sub
以下是如何调用和关闭加载叠加层:
Private Sub ShowLoadingOverlay()
If Not blnLoadingOverlayVisible Then
Me.Enabled = False
patience = New LoadingOverlay()
patience.Location = Point.Add(parent.PointToScreen(Me.Location), New Size(0, parent.ToolStrip.Height + parent.MenuStrip.Height))
patience.Size = Me.Size
patience.Show()
patience.BringToFront()
blnLoadingOverlayVisible = True
End If
End Sub
Private Sub HideLoadingOverlay()
If blnLoadingOverlayVisible Then
'Close loading overlay'
patience.Close()
patience.Dispose()
patience = Nothing
Me.Enabled = True
blnLoadingOverlayVisible = False
End If
End Sub
答案 0 :(得分:1)
“某些COM”是相关的。你会点击COM的公寓线程规则。必须在STA线程上创建类似Word的COM对象。您的主UI线程符合条件,它从Main()开始,并具有[STAThread]属性。您在另一个线程上调用的任何方法都会被COM自动封送到STA线程。搞砸你的动画。
这不容易修复。你需要一个必须是STA线程的后台线程,使用Thread.SetApartmentState()。并且泵出一个消息循环,使用Application.Run()。启动代码并退出循环是很尴尬的,尝试使用覆盖SetVisibleCore()的表单,这样就可以避免使其可见。
答案 1 :(得分:0)
最初一切都发生在一个后台线程中。总共运行3种方法。当我将上传线程(大约工作量的1/2)移动到另一个后台线程时,一切都“正常”(不完美,GIF在开始时仍会跳跃一点)。
移入第二个后台线程的上传方法根本不与GUI线程交互,它只是做一些COM(单词)和SQL的东西。长话短说,它有效,但我仍然不知道为什么。任何见解将不胜感激!