【问题标题】:vb.net animating a notification form. Problem with threading and sizingvb.net 动画通知表单。螺纹和尺寸问题
【发布时间】:2020-11-19 11:47:44
【问题描述】:

我创建了一个类用作通知窗口(类似于 toast 通知,在我们的系统上已禁用)。 我使用一个计时器对象来超时关闭表单,并使用一个后台工作者来处理它从屏幕底部滑入的动画。出于调试目的,表单只输出它自己的大小和屏幕边界。

Imports System.ComponentModel

Public Class ASNotify

    Public Sub New(ByVal title As String, ByVal msg As String, ByVal Optional timeout As Integer = 5000)
        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        Me.Text = title
        Me.NotifyMessage.Text = $"{Me.Width}x{Me.Height}{vbCrLf}{My.Computer.Screen.WorkingArea.Size.Width}x{My.Computer.Screen.WorkingArea.Size.Height}"
        TimeoutTimer.Interval = timeout
        TimeoutTimer.Enabled = True
        AnimationWorker.RunWorkerAsync()
    End Sub

    Private Sub AnimationWorker_DoWork(sender As Object, e As DoWorkEventArgs) Handles AnimationWorker.DoWork
        Dim xloc As Integer = My.Computer.Screen.WorkingArea.Size.Width - Me.Width
        Dim yloc As Integer = My.Computer.Screen.WorkingArea.Size.Height

        For x As Integer = 0 To Me.Height
            MoveWindow(xloc, yloc - x)
            Threading.Thread.Sleep(2)
        Next
    End Sub

    Private Sub MoveWindow(xloc As Integer, yloc As Integer)
        If InvokeRequired Then
            Invoke(Sub() MoveWindow(xloc, yloc))
        Else
            Location = New Drawing.Point(xloc, yloc)
        End If
    End Sub

    Private Sub TimeoutTimer_Tick(sender As Object, e As EventArgs) Handles TimeoutTimer.Tick
        Me.Close()
    End Sub
    
End Class

我通过调用从另一个表单调用它

Private Sub NotifyUser(ByRef a As Alert.Alert)
    Dim notify As New ASNotify(a.Location, a.Comment, 5000)
    notify.Show()
End Sub

我通过按下表单上的一个按钮来调用那个 sub,它可以完美地工作.....有时。

反复触发通知窗口使其在屏幕上弹出为 2 种不同尺寸之一,尽管显示尺寸的内容始终为 264x81 且屏幕边界为 1920x1040

偶尔我会收到一个异常,即“Location = new Drawing.Point(xloc,yloc) 是从创建它的线程之外的线程调用的,尽管调用了 Invoke。

【问题讨论】:

  • 为什么不直接使用 Timer 来执行转换?无论如何,您都在调用(尝试)UI 线程。如果您真的想使用 BackgroundWorker,请使用其 DoWorkEventArgs 将表单的高度传递给 DoWork 处理程序,然后在其 ProgressChanged 处理程序中更新位置:该事件在 UI 线程中引发,因此无需担心调用(如果需要调用UI Thread,调用BeginInvoke(),不需要InvokeRequired)。
  • 并没有完全解决我的问题,但重写以使用 begininvoke,并阅读产生的错误导致我找到了解决方案。进行呼叫时,窗口并未完全实现。将动画和计时器移至 Load 方法,而不是 New 方法,现在可以使用了。

标签: vb.net multithreading forms


【解决方案1】:

将 timer-start 和 animationworker start 移至表单的 Load 方法,而不是 New。

Private Sub ASNotify_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    TimeoutTimer.Enabled = True
    AnimationWorker.RunWorkerAsync()
End Sub

【讨论】:

  • 你试过AnimateWindow功能吗?从here复制vb.net签名并试一试。
  • 嗯,谢谢。我一定会看看的。
猜你喜欢
  • 1970-01-01
  • 2021-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-21
  • 2017-12-15
  • 2015-05-21
相关资源
最近更新 更多