2013-05-31 369 views
3

我需要一種方法來避免閃爍在面板上,我在這裏做了很多類似的問題和世界上所有的試圖詢問專家身邊,我已經嘗試了很多花樣,擴展板,的CreateParams,的ControlStyles,失去了很多的時間,浪費時間學習的東西會不工作......我被困在這一點上幾個月。面板閃爍與Pictureboxes

...沒有什麼能像預期的那樣真正起作用,我發現的最好的「Flicker-Reducer」是「Createparams」重寫子,但是這種方法使Form/App x20的任何操作都變得更慢,我不想失去閃爍如果這意味着寬鬆的應用性能太(至少不是如果是的CreateParams相同的性能不利點)。

在這個視頻中,你可以看到我的測試表單有一個50%的透明面板,裏面有圖片框,背景圖像設置爲「縮放」分層,當我向上或向下滾動時,我得到很多閃爍。

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

我用「的CreateParams」的方法,真的是你不會看到我的面板的閃爍會發生什麼,如果我不使用「的CreateParams」,真正可怕的。

這是當不閃爍面板:

enter image description here

而且這是在某一時刻的面板,它閃爍:

enter image description here

下面是完整的類:

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 
+0

請填寫您在YouTube上展示的演示解決方案。 –

+0

您提供的代碼缺少重要部分。 –

+0

@ Ark-kun我已經發布了完整的類,解決方案中沒有更多的代碼(只有圖像資源和那個),反正這裏是完整的解決方案:http://elektrostudios.tk/WindowsApplication4.rar感謝你的評論。 – ElektroStudios

回答

5

PanelAutoScroll屬性設置爲true。沒有這個滾動似乎沒有工作。 添加DoubleBufferedPanel類從Panel類繼承並設置.DoubleBuffered屬性設置爲true:

Public Class DoubleBufferedPanel 
    Inherits Panel 

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

現在去隱藏InitializeComponent子(在Panel1可變單擊鼠標右鍵,然後單擊Go To Definition)。與DoubleBufferedPanel更換Panel類型需要的地方(兩處):

的閃爍應該停止(雖然還存在一些其他的效果)。 取出CreateParams來提高速度。

P.S.總體而言,這不是一個好主意(移動複雜的半透明圖像)。你爲什麼不使用類似ListView的東西?你爲什麼不自己移動的圖像,而不使用Panel?如果您想獲得最佳速度,請使用BitmapGraphics類在表單上繪製圖像(.BackgroundImage)。

P.P.S.編程式滾動Panel.AutoScroll = true似乎有一些嚴重的錯誤。我不得不重新分配滾動值以防止嚴重抖動。我已經隔離了這個情況,並會向微軟提交錯誤報告。

+0

謝謝,但對我來說這不是一個可靠的解決方案,就像我在第一次嘗試了很多「雙緩衝面板」和其他「真正什麼都不做」的「技巧」時所說的那樣,crateparams的使用僅僅是一個例子,顯示,createparams的用法對我來說是無效的,因爲在應用程序中導致的性能下降(我已經在幾個月內做了很多速度測試) – ElektroStudios

+0

而我無法使用GDI的原因是因爲我需要插入控件面板中的事件,我的意思是例如我需要點擊一個PictureBox然後調用「click」事件處理程序......如果我寫一個bmp圖像,我不能這樣做。但感謝您的回答! – ElektroStudios

+0

哦......我忘了一件事:我不知道你爲什麼提到ListView,請你解釋一下嗎?如果我使用的面板是'因爲是控件的容器,Liistview不是,我也使用Panel',因爲「AutoScroll」垂直條很容易管理,而不是寫一個自定義滾動條。 PS:對不起,因爲我的英文和一些垃圾郵件 – ElektroStudios

3

使用複合class表示panel和它的內容,然後油漆(01​​)即到Picturebox將很好地渲染。我做過幾個這樣的項目。

+0

感謝您的回答,但是您能否更詳細地解釋一下您所說的所有內容?真的,在VBNET編程中沒有太多先進的技術來做所有這些事情,而沒有舉一個例子,但是你已經說過「我已經完成了幾個這樣的項目」,也許你可以發佈一個項目的代碼示例嗎?再次感謝。 – ElektroStudios

+0

'class'只是另一個'object',這次你定義它是'properties'。那麼,就你而言,你將需要該類的集合 - 「List(Of T)」。在你的表單中,你在paint事件中迭代集合。至於滾動部分,你甚至可以檢查類對象的Location.y,如果它太高或太低,不要繪製它。 「矩形」是用於繪製邊框或包裹圖像的很好的結構。我甚至使用'GDI +'繪製滾動條。很難在一篇文章中告訴你需要的一切。 – OneFineDay

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 

這可能不是解決辦法,但是這是從我身旁的努力。

+0

檢查編輯的答案,可能會幫助你。 – Vishal

+0

謝謝,但它充滿錯誤/ exceptnions,你嘗試編輯後使用它?不管怎麼說,多謝拉。 – ElektroStudios

+0

對不起,我忘了刪除一些行。現在它應該工作。代碼未經測試。試着清理錯誤,如果你有任何其他問題隨時問。 – Vishal

1

把這個在您的形式負載

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

與背景圖像控件的名稱替換Panel7。