3

我需要一种方法来避免面板上的闪烁,我在这里和世界各地都提出了很多类似的问题,试图向专家提问,我尝试了很多技巧,扩展面板,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
4

4 回答 4

5

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

Public Class DoubleBufferedPanel
    Inherits Panel

    Public Sub New()
        DoubleBuffered = True
    End Sub
End Class

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

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

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

PS 总的来说,这不是一个很好的主意(移动复杂的半透明图像)。你为什么不使用类似的东西ListView?你为什么不自己移动图像而不使用Panel?如果您想要最好的速度,只需.BackgroundImage使用BitmapGraphics类在您的表单 ( ) 上绘制图像。

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

于 2013-06-04T03:59:19.537 回答
3

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

编辑 :

我认为您不需要计时器。因此,您修改后的代码会有点像这样:

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

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

于 2013-06-09T06:04:05.633 回答
3

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

于 2013-05-31T20:57:14.883 回答
1

把它放在你的表单加载中

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

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

于 2014-03-19T17:28:03.823 回答