Optimizing control resizing
I have a custom UserControl that have a StatusStrip. So, I resize this control when user drags the corner of this status strip. However, the resizing is not pretty good: temporary white areas can be observed on the parent control during the resize, and sometimes if the resizing are too fast user "loses" the control(that stops resizing).
Option Infer On
Public Class FloattingGrid
Inherits System.Windows.Forms.UserControl
Dim mouseDownLocation As Nullable(Of Point)
Private Sub StatusStrip1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles StatusStrip1.MouseMove
If mouseDownLocation.HasValue Then
Dim newPosition = Cursor.Position
Dim dx = newPosition.X - mouseDownLocation.Value.X
Dim dy = newPosition.Y - mouseDownLocation.Value.Y
'Dim oldRect = New Rectangle(Me.Location, Me.Size)'
Me.Size = New Size(Me.Width + dx, Me.Height + dy)
mouseDownLocation = newPosition
If Me.Parent IsNot Nothing Then
'Me.Parent.Invalidate(oldRect) '
Me.Parent.Refresh()
End If
开发者_开发技巧 Else
If e.X > Me.Width - 20 Then
If Cursor <> Cursors.SizeNWSE Then Cursor = Cursors.SizeNWSE
Else
If Cursor = Cursors.SizeNWSE Then Cursor = Cursors.Default
End If
End If
End Sub
Private Sub StatusStrip1_MouseLeave(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StatusStrip1.MouseLeave
Cursor = Cursors.Default
mouseDownLocation = Nothing
'Me.ResumeLayout() '
End Sub
Private Sub StatusStrip1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles StatusStrip1.MouseDown
If Cursor = Cursors.SizeNWSE Then
'Me.SuspendLayout() '
mouseDownLocation = Cursor.Position
End If
End Sub
Private Sub StatusStrip1_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles StatusStrip1.MouseUp
mouseDownLocation = Nothing
'Me.ResumeLayout()'
End Sub
' Private Sub FloattingGrid_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove '
' End Sub '
Private Sub FloattingGrid_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.ResizeRedraw = True
End Sub
End Class
I think that behavior could be caused by the parent's Invalidate. Is there a way to just BeginInvalidate and not wait till parent invalidates all the region?
BeginInvoke
has nothing to do with painting and nothing to do with implementing a delay. It's all about cross-thread access, which you're not doing here. It's not the correct solution.
And there's nothing wrong with calling Invalidate
. It just marks the area as requiring painting. It doesn't actually cause that area to get repainted multiple times. If the area you invalidate has already been invalidated, it's a no-op, so it's not responsible for slowing anything down here. If you wanted it to be repainted immediately, you would need to call something like Refresh
instead.
One thing you could do is prevent the parent control from trying to resize itself and change the layout of its child controls to accommodate the new position of the StatusStrip
. To do that, call the SuspendLayout
method when you begin resizing and the ResumeLayout
method when you finish.
Of course, that's not guaranteed to solve your problem. You're still very likely to see a lag and white or black areas appear in the regions that haven't been painted yet. This happens in other applications and even when you resize windows. The only solution to that is double-buffering, drawing everything into a temporary background buffer, and then painting that entire completed image to the screen.
精彩评论