优化控件调整大小

时间:2011-05-17 10:07:30

标签: .net winforms user-controls

我有一个具有StatusStrip的自定义UserControl。因此,当用户拖动此状态条的一角时,我会调整此控件的大小。但是,调整大小并不是很好:在调整大小期间可以在父控件上观察到临时白色区域,有时如果调整大小太快,用户“丢失”控件(停止调整大小)。

enter image description here

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

我认为这种行为可能是由父母的无效引起的。有没有办法只使用BeginInvalidate而不是等到父母使所有区域无效?

1 个答案:

答案 0 :(得分:1)

BeginInvoke与绘画无关,与实施延迟无关。这都是关于跨线程访问的,你在这里没有做。这不是正确的解决方案。

调用Invalidate并没有错。它只是标志着该地区需要绘画。它实际上并不会导致该区域重新涂漆多次。如果您失效的区域已经失效,那么它就是无操作,因此它不负责减慢此处的任何速度。如果您希望立即重新绘制 ,则需要调用类似Refresh的内容。

您可以做的一件事是阻止父控件尝试调整自身大小并更改其子控件的布局以适应StatusStrip的新位置。为此,请在开始调整大小时调用SuspendLayout method,并在完成后调用ResumeLayout method

当然,这并不能保证解决您的问题。您仍然很可能会看到滞后,并且尚未绘制的区域中会出现白色或黑色区域。在其他应用程序中甚至在调整窗口大小时也会发生这种情况唯一的解决方案是双缓冲,将所有内容绘制到临时背景缓冲区中,然后将整个完成的图像绘制到屏幕上。