的WinForms进度需要时间来渲染 [英] Winforms ProgressBar Takes time to Render

查看:164
本文介绍了的WinForms进度需要时间来渲染的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用PorgressBar时noticied的。如果我将该值设置为X,显示的数值并不会立即更新,这需要花费少量的时间来绘制它作为酒吧从当前值到新值的动画。

I have noticied that when using the PorgressBar. If I set the value to x, the value displayed is not immediately updated, it takes a small amount of time to draw it as the bar is animated from its current value to the new value.

这是很容易看到下面的code:

This is easy to see in the following code:

Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Label1.Text = ""
    Dim progressHandler = New Progress(Of Integer)(Sub(value) ProgressBar1.Value = value)
    Dim progress = CType(progressHandler, IProgress(Of Integer))
    Await Task.Run(Sub()
                       For i = 1 To 100
                           progress.Report(i)
                           Thread.Sleep(10)
                       Next
                   End Sub)
    Label1.Text = "Value Now at 100%"
    Await Task.Delay(650) 'it takes this long for the bar to be rendered
    Label1.Text += " - Finished drawing"
End Sub

你会发现运行此的值现在为100%出现很长时间才酒吧实际上已经达到了100%code。

You will notice running this code that the Value Now at 100% appears a long time before the bar has actually reached 100%.

有没有什么办法,我可以检测到酒吧已经完成渲染?

Is there any way that I can detect when the bar has finished rendering?

推荐答案

我只是想这一点,并能清楚地看到你的意思。花一点时间看,如果在进度条的DrawToBitmap功能可能有助于以后不幸的是,我已经短上来了。

I just tried this out and can see exactly what you mean. Unfortunately after spending a little while seeing if the DrawToBitmap functions on the progress bar might help, I've come up short.

下一步将是创建一个自定义进度栏公开事件当渲染完成的。

The next step would be to create a custom progress bar that exposes events for when rendering has completed.

有关如何创建一个自定义的进度条合理的例子,试一下: <一href="http://msdn.microsoft.com/en-us/library/system.windows.forms.progressbarrenderer(v=VS.100).aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/system.windows.forms.progressbarrenderer(v=VS.100).aspx

For a reasonable example on how to create a custom progress bar, try here: http://msdn.microsoft.com/en-us/library/system.windows.forms.progressbarrenderer(v=VS.100).aspx

在code快速扫描的样子,你应该能够在OnRendered事件插头或上或周围的呼叫'DrawHorizo​​ntalChunks(或DrawVerticalChunks)相似。

A quick scan over the code looks like you should be able to plug in an 'OnRendered' event or similar on or around the calls to 'DrawHorizontalChunks' (or 'DrawVerticalChunks').

也许得不到答案,你是以后,但至少给了你,你需要的控制,如果你追求的吗?

Probably not the answer you was after, but at least gives you the control you need if you pursue it?

注:我没有尝试这样做我自己,所以请不要给我发仇恨邮件,如果你整天在此找到你得到相同的结果...

Note: I haven't tried this myself, so please don't send me hate mail if you spend all day on this to find you get the same results...

祝您好运!

编辑:

是不是满意我的回答,显得有点懒......下面使用我描述一个自定义的进度条。它设置最大/最小值,执行步骤,并直接将其值设置几个基本属性。我已经通过改变睡眠间隔不同量测试此,在所有情况下关闭之前的形式显示的进度条满。注意新OnRendered事件。

Wasn't happy with my response, seemed a bit lazy... The following uses a custom progress bar as I described. It has a couple basic properties for setting Max/Min values, Performing steps, and setting the value directly. I've tested this by changing the sleep interval to various amounts, in all cases the form displayed the progress bar as full before closing. Note the new OnRendered event.

Imports System
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Windows.Forms.VisualStyles

Public Class Form1
    Inherits Form
    Private WithEvents bar1 As ProgressBarWithRender = New ProgressBarWithRender()


    Public Sub New()
        InitializeComponent()
        Me.Size = New Size(500, 500)
        bar1.Location = New Point(100, 100)
        bar1.Width = 300
        bar1.Height = 50
        bar1.Maximum = 30
        bar1.Step = 1
        Controls.Add(bar1)
    End Sub

    Public Sub OnRendered(ByVal valueRendered As Integer) Handles bar1.OnRendered
        If valueRendered = bar1.Maximum Then
            ' We know everything has been drawn
            Me.Close()
        End If
    End Sub


    <STAThread()> _
    Public Shared Sub Main()
        ' The call to EnableVisualStyles below does not affect
        ' whether ProgressBarRenderer.IsSupported is true; as 
        ' long as visual styles are enabled by the operating system, 
        ' IsSupported is true.
        Application.EnableVisualStyles()
        Application.Run(New Form1())

    End Sub 'Main

    Private Sub Form1_Click(sender As Object, e As System.EventArgs) Handles Me.Click
        For i = 1 To 30
            bar1.PerformStep()
            Threading.Thread.Sleep(10)
        Next
    End Sub

End Class 'Form1

Public Class ProgressBarWithRender
    Inherits Control

    Public Delegate Sub RenderedEventArgs(ByVal valueRendered As Integer)
    Public Event OnRendered As RenderedEventArgs

    Private ProgressBarRectangles() As Rectangle

    Public Property [Step] As Integer

    Public Property InnerPadding As Integer = 3

    Private _Maximum As Integer
    Public Property Maximum As Integer
        Get
            Return _Maximum
        End Get
        Set(value As Integer)
            _Maximum = value
            CalculateTickSizes()
        End Set
    End Property

    Private _Minimum As Integer
    Public Property Minimum As Integer
        Get
            Return _Minimum
        End Get
        Set(value As Integer)
            _Minimum = value
            CalculateTickSizes()
        End Set
    End Property

    Private _Value As Integer
    Public Property Value As Integer
        Get
            Return _Value
        End Get
        Set(newValue As Integer)
            If newValue < Me.Value AndAlso newValue > 0 Then
                Throw New NotImplementedException("ProgressBarWithRender does not support decrementing the value")
            End If
            Me._Value = newValue
        End Set
    End Property

    Public Sub PerformStep()
        ' Ensure step doesn't exceed boundaries
        If Value + [Step] > Maximum Then
            Value = Maximum
        ElseIf Value + [Step] < Minimum Then
            Value = Minimum
        Else
            Value += [Step]
        End If

        ' We are limited by the Renderers Chunk Width, so we possibly can't draw every step if there is a high maximum
        Dim g As Graphics = Me.CreateGraphics
        ProgressBarRenderer.DrawHorizontalChunks(g, ProgressBarRectangles(Value - Minimum))
        RaiseEvent OnRendered(Value)

    End Sub

    Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
        If Not ProgressBarRenderer.IsSupported Then
            Throw New NotImplementedException("Progress Bar Rendering is not supported")
        End If
        ProgressBarRenderer.DrawHorizontalBar(e.Graphics, ClientRectangle)
    End Sub

    Private Sub CalculateTickSizes()
        ' Changing the Maximum will change the tick rectangle size
        ProgressBarRectangles = New Rectangle(Maximum) {}
        Dim chunkThickness As Integer = ProgressBarRenderer.ChunkThickness + (ProgressBarRenderer.ChunkSpaceThickness * 2)
        Dim tickThickness As Double = ((ClientRectangle.Width - (InnerPadding * 2)) - (ProgressBarRenderer.ChunkSpaceThickness * 2)) / (Maximum - Minimum)
        If tickThickness < chunkThickness Then
            Debug.Print("This will go wrong because we can't draw small enough chunks...")
        End If
        For i As Integer = 0 To Maximum
            Dim filledRectangle As Integer = CInt(tickThickness * i)
            ProgressBarRectangles(i) = New Rectangle(ClientRectangle.X + InnerPadding,
                                                     ClientRectangle.Y + InnerPadding,
                                                     filledRectangle,
                                                     ClientRectangle.Height - (InnerPadding * 2))
        Next
    End Sub

End Class

这篇关于的WinForms进度需要时间来渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆