【问题标题】:Panel Flickering with Pictureboxes面板闪烁与图片框
【发布时间】:2013-05-27 18:36:14
【问题描述】:

我需要一种方法来避免面板上的闪烁,我在这里和世界各地提出了很多类似的问题,试图向专家提问,我尝试了很多技巧,扩展面板,createparams,controlstyles ,浪费了很多时间,浪费了时间去学习那些行不通的东西......我在这一点上被困了几个月。

...没有什么能真正按预期工作,我发现最好的“Flicker-Reducer”是“Createparams”覆盖子,但该方法使任何表单/应用程序的任何表单操作都慢 20 倍,我如果闪烁也意味着应用程序性能下降(至少如果与 CreateParams 的性能相同的负面影响点则不会)。

在此视频中,您可以看到我的测试表单,其中有一个 50% 透明面板,其中包含背景图像设置为“缩放”分层的图片框,当我向上或向下滚动时,我得到很多闪烁。

http://www.youtube.com/watch?v=zIBDTMjrDd4&feature=youtu.be

我使用“CreateParams”方法,如果我不使用“CreateParams”,真的你不会看到我的面板闪烁会发生什么,真的很可怕。

这是不闪烁时的面板:

这是面板在闪烁的时刻:

这是完整的类:

It is a Windows Form proyect
VS2012
Framework 3.5
On Windows 7 x64
Application Visual Styles is ON
Double Buffer is ON
Panel and pictureboxes are default controls

(我想不用说我已经尝试了人们说我永远忘记闪烁的所有可能的视觉和环境配置。)

Public Class Form1

    Dim Scroll_Position As Int32 = 0
    Dim Button_Down_Is_Pressed As Boolean = False
    Dim Button_Up_Is_Pressed As Boolean = False
    Dim WithEvents Progressive_Scroll_Timer As New Timer
    Dim SmallChange As Int32 = 5
    Dim Largechange As Int32 = 10

    ' Sub which reduces the Flickering, but this sub makes x20 times slower any operation of any Form/Application.
    Protected Overrides ReadOnly Property CreateParams() As CreateParams
        Get
            Dim cp As CreateParams = MyBase.CreateParams
            cp.ExStyle = cp.ExStyle Or &H2000000
            Return cp
        End Get
    End Property 'CreateParams

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ' Me.BackColor = Color.FromArgb(255, 0, 0, 0)
        ' Me.TransparencyKey = Color.FromArgb(255, 0, 0, 0)
        Panel1.VerticalScroll.Maximum = 999999999
        Progressive_Scroll_Timer.Interval = 50
        Panel1.BackColor = Color.FromArgb(150, 0, 0, 0)
    End Sub

    Private Sub Panel_MouseHover(sender As Object, e As EventArgs) Handles Panel1.MouseHover
        sender.focus()
    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Progressive_Scroll_Timer.Tick
        If Button_Down_Is_Pressed Then
            Scroll_Down(SmallChange)
        ElseIf Button_Up_Is_Pressed Then
            Scroll_Up(SmallChange)
        Else
            sender.stop()
        End If
    End Sub

    Private Sub Scroll_Up(ByVal Change As Int32)
        Scroll_Position -= Change
        Panel1.SuspendLayout()
        Try : Panel1.VerticalScroll.Value = Scroll_Position : Catch : Scroll_Position += Change : End Try
        Panel1.ResumeLayout()
    End Sub

    Private Sub Scroll_Down(ByVal Change As Int32)
        Scroll_Position += Change
        Try : Panel1.VerticalScroll.Value = Scroll_Position : Catch : Scroll_Position -= Change : End Try
    End Sub

    Private Sub Button_Down_MouseDown(sender As Object, e As MouseEventArgs) Handles Button2.MouseDown
        If e.Button = Windows.Forms.MouseButtons.Left Then
            Button_Down_Is_Pressed = True
            Progressive_Scroll_Timer.Start()
        End If
    End Sub

    Private Sub Button_Up_MouseDown(sender As Object, e As MouseEventArgs) Handles Button1.MouseDown
        If e.Button = Windows.Forms.MouseButtons.Left Then
            Button_Up_Is_Pressed = True
            Progressive_Scroll_Timer.Start()
        End If
    End Sub

    Private Sub Button_Down_MouseUp(sender As Object, e As MouseEventArgs) Handles Button2.MouseUp
        Button_Down_Is_Pressed = False
    End Sub

    Private Sub Button_Up_MouseUp(sender As Object, e As MouseEventArgs) Handles Button1.MouseUp
        Button_Up_Is_Pressed = False
    End Sub

    Private Sub Form_MouseWheel(ByVal sender As Object, ByVal e As MouseEventArgs) Handles Panel1.MouseWheel
        If Panel1.Focused Then
            Select Case Math.Sign(e.Delta)
                Case Is > 0 : Scroll_Up(Largechange)
                Case Is < 0 : Scroll_Down(Largechange)
            End Select
        End If
    End Sub

End Class

【问题讨论】:

标签: .net vb.net visual-studio panel flicker


【解决方案1】:

把它放到你的表单加载中

' to remove flick
Dim aProp As PropertyInfo = GetType(Panel).GetProperty("DoubleBuffered", BindingFlags.NonPublic Or BindingFlags.Instance)
        aProp.SetValue(Panel7, True, Nothing)

将 Panel7 替换为带有背景图像的控件名称。

【讨论】:

    【解决方案2】:

    您可以将 Form 的 DoubleBuffered 属性设置为 True

    编辑:

    我认为你不需要 Timer。 所以,你修改后的代码有点像这样:

    Public Class Form1
    
        Dim Scroll_Position As Int32 = 0
        Dim SmallChange As Int32 = 5
        Dim Largechange As Int32 = 10
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ' Me.BackColor = Color.FromArgb(255, 0, 0, 0)
            ' Me.TransparencyKey = Color.FromArgb(255, 0, 0, 0)
            Panel1.VerticalScroll.Maximum = 999999999
            Panel1.BackColor = Color.FromArgb(150, 0, 0, 0)
        End Sub
    
        Private Sub Panel_MouseHover(sender As Object, e As EventArgs) Handles Panel1.MouseHover
            sender.focus()
        End Sub
    
        Private Sub Scroll_Up(ByVal Change As Int32)
            Try
                Scroll_Position -= Change
                Panel1.VerticalScroll.Value = Scroll_Position 
            End Try
        End Sub
    
        Private Sub Scroll_Down(ByVal Change As Int32)
            Try
                Scroll_Position += Change
                Panel1.VerticalScroll.Value = Scroll_Position 
            End Try
        End Sub
    
        Private Sub Button_Down_MouseDown(sender As Object, e As MouseEventArgs) Handles Button2.MouseDown
            If e.Button = Windows.Forms.MouseButtons.Left Then
                scrollDown(smallChange)
            End If
        End Sub
    
        Private Sub Button_Up_MouseDown(sender As Object, e As MouseEventArgs) Handles Button1.MouseDown
            If e.Button = Windows.Forms.MouseButtons.Left Then
                scrollUp(SmallChange)
            End If
        End Sub
    
        Private Sub Form_MouseWheel(ByVal sender As Object, ByVal e As MouseEventArgs) Handles Panel1.MouseWheel
            If Panel1.Focused Then
                Select Case Math.Sign(e.Delta)
                    Case Is > 0 : Scroll_Up(Largechange)
                    Case Is < 0 : Scroll_Down(Largechange)
                End Select
            End If
        End Sub
    
    End Class
    

    这可能不是解决方案,但这是我方面的努力。

    【讨论】:

    • 谢谢,但它充满了错误/异常,您尝试编辑后使用它吗?无论如何,谢谢。
    • 对不起,我忘了删除一些行。现在它应该可以工作了。并且代码没有经过测试。只需尝试清理错误,如果您有任何其他问题,请随时提出。
    【解决方案3】:

    将Panel 的AutoScroll 属性设置为true。没有这个,滚动似乎不起作用。 添加继承自Panel 类的DoubleBufferedPanel 类并将.DoubleBuffered 属性设置为true:

    Public Class DoubleBufferedPanel
        Inherits Panel
    
        Public Sub New()
            DoubleBuffered = True
        End Sub
    End Class
    

    现在转到隐藏的InitializeComponent 子(右键单击Panel1 变量并单击Go To Definition)。在需要的地方(两个地方)用DoubleBufferedPanel替换Panel类型:

    Me.Panel1 = New WindowsApplication4.DoubleBufferedPanel()
    ....
    Friend WithEvents Panel1 As WindowsApplication4.DoubleBufferedPanel
    

    闪烁应该停止(尽管还有一些其他效果)。 删除CreateParams 以提高速度。

    附:总的来说,这不是一个很好的主意(移动复杂的半透明图像)。为什么不使用ListView 之类的东西?为什么不使用Panel 自己移动图像?如果您想获得最佳速度,只需使用 Bitmap 和 Graphics 类在表单 (.BackgroundImage) 上绘制图像。

    附言使用.AutoScroll = true 以编程方式滚动Panel 似乎存在一些严重的错误。我必须双重分配滚动值以防止严重抖动。我已隔离此案例,并将向 Microsoft 提交错误报告。

    【讨论】:

    • 谢谢,但对我来说这不是一个切实可行的解决方案,就像我第一次说的那样,我尝试了很多“boublebuffered panel”和其他实际上什么都不做的“技巧”,使用 crateparams只是我要展示的一个示例,createparams 的使用对我无效,因为在应用程序中导致性能减速(我在几个月内进行了很多速度测试)
    • 而我不能使用 GDI 的原因是因为我需要在面板内插入带有事件的控件,例如我需要在 PictureBox 中单击然后调用“单击”事件处理程序...如果我编写 bmp 图像,我将无法做到这一点。但感谢您的回答!
    • 哦...我忘了一件事:我不知道你为什么提到 Listview,你能解释一下吗?如果我使用面板是因为是控件的容器,而 Liistview 不是,我也使用面板,因为“AutoScroll”垂直条很容易管理,而不是编写自定义滚动条。 PS:对不起,因为我的英语和小垃圾邮件
    • 我自己编写并测试了代码,它工作 - 闪烁消失了。你试过我的代码了吗?
    • 当然我试过了,不管有没有createparams,没有createparams闪烁很吓人,也许你没有像我一样在相同的情况下测试它(带有图片框的面板和图片框内的每个有背景图片)
    【解决方案4】:

    使用表示panel 及其内容的复合class,然后将其绘制到Picturebox 上会很好地呈现。我做过几个这样的项目。

    【讨论】:

    • 感谢您的回答,但您能解释一下您所说的所有内容吗?真的,我在 VBNET 编程方面并没有很先进,没有举个例子就可以完成所有这些工作,但是你说过“我已经完成了几个这样的项目”也许你可以从你的一个项目中发布一个代码示例?,无论如何再次感谢。
    • 一个class 只是另一个object,这次你定义它是properties。然后,在您的情况下,您将需要该类的集合 - List(Of T)。在您的表单中,您在绘制事件中迭代集合。至于滚动部分,您甚至可以检查类对象的 Location.y,如果它太高或太低,则不要绘制它。 Rectangles 是用于绘制边框或封装图像的绝佳结构。哎呀,我什至在使用GDI+ 时绘制滚动条。很难在一篇文章中告诉您所需的一切。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-09
    • 2014-03-19
    • 1970-01-01
    • 2017-09-08
    • 1970-01-01
    • 2015-06-27
    相关资源
    最近更新 更多