.net 优化控件大小调整
我有一个自定义UserControl,它有一个StatusStrip。因此,当用户拖动此状态条的角时,我会调整此控件的大小。但是,调整大小不是很好:在调整大小期间,可以在父控件上观察到临时白色区域,有时如果调整太快,用户会“丢失”控件(停止调整大小).net 优化控件大小调整,.net,winforms,user-controls,.net,Winforms,User Controls,我有一个自定义UserControl,它有一个StatusStrip。因此,当用户拖动此状态条的角时,我会调整此控件的大小。但是,调整大小不是很好:在调整大小期间,可以在父控件上观察到临时白色区域,有时如果调整太快,用户会“丢失”控件(停止调整大小) 选项推断打开 公共类浮动网格 继承System.Windows.Forms.UserControl 将鼠标向下位置调暗为可为空(点的) 私有子StatusStrip1\u MouseMove(ByVal sender作为System.Object
选项推断打开
公共类浮动网格
继承System.Windows.Forms.UserControl
将鼠标向下位置调暗为可为空(点的)
私有子StatusStrip1\u MouseMove(ByVal sender作为System.Object,ByVal e作为System.Windows.Forms.MouseEventArgs)处理StatusStrip1.MouseMove
如果mouseDownLocation.HasValue,则
Dim newPosition=光标位置
Dim dx=newPosition.X-mouseDownLocation.Value.X
Dim dy=newPosition.Y-mouseDownLocation.Value.Y
'Dim oldRect=新矩形(Me.Location,Me.Size)'
Me.Size=新尺寸(Me.Width+dx,Me.Height+dy)
mouseDownLocation=newPosition
如果我,父母不是什么都不是
'Me.Parent.Invalidate(oldRect)'
Me.Parent.Refresh()
如果结束
其他的
如果e.X>Me.Width-20,则
如果游标Cursors.SizeNWSE,则游标=Cursors.SizeNWSE
其他的
如果Cursor=Cursors.SizeNWSE,则Cursor=Cursors.Default
如果结束
如果结束
端接头
私有子statusStrip1u MouseLeave(ByVal sender作为System.Object,ByVal e作为System.EventArgs)处理StatusStrip1.MouseLeave
游标=游标。默认值
mouseDownLocation=无
“Me.resumeloayout()”
端接头
私有子StatusStrip1\u MouseDown(ByVal sender作为System.Object,ByVal e作为System.Windows.Forms.MouseEventArgs)处理StatusStrip1.MouseDown
如果Cursor=Cursors.SizeNWSE,则
'Me.SuspendLayout()'
mouseDownLocation=光标位置
如果结束
端接头
私有子状态条带1u MouseUp(ByVal sender作为System.Object,ByVal e作为System.Windows.Forms.MouseEventArgs)处理状态条带1.MouseUp
mouseDownLocation=无
“Me.resumeloayout()”
端接头
'Private Sub floatinggrid_MouseMove(ByVal sender作为对象,ByVal e作为System.Windows.Forms.MouseEventArgs)处理Me.MouseMove'
“末端接头”
私有子floatingGrid_Load(ByVal sender作为System.Object,ByVal e作为System.EventArgs)处理MyBase.Load
Me.ResizeRedraw=真
端接头
末级
我认为这种行为可能是由父母的行为引起的。有没有一种方法可以直接开始验证,而不是等到父级使所有区域无效?与绘制无关,也与实现延迟无关。所有这些都是关于跨线程访问的,而您在这里没有这样做。这不是正确的解决方案
打电话也没什么错。它只是将该区域标记为需要喷漆的区域。实际上,这并不会导致该区域多次重新喷漆。如果你使之失效的区域已经失效,它是一个不可操作的区域,因此它不负责减慢任何速度。如果希望立即重新绘制,则需要调用类似于Refresh
的函数
您可以做的一件事是防止父控件尝试调整自身大小并更改其子控件的布局,以适应StatusStrip
的新位置。为此,请在开始调整大小时调用,在完成时调用
当然,这并不能保证解决你的问题。您仍然很可能会看到延迟,在尚未绘制的区域中会出现白色或黑色区域。在其他应用程序中,甚至在调整窗口大小时,也会发生这种情况。唯一的解决方案是双缓冲,将所有内容都绘制到临时背景缓冲区中,然后将整个完成的图像绘制到屏幕上。有效地,在调用parent.Refresh()而不是parent.Invalidate(oldRect)后,白色区域消失。然而,当我移动得更快时,我总是失去控制。我没有调整StatusStrip的大小,我直接调整UserControl的大小(StatusStrip停靠在底部)@serhio:是的,调用
刷新可以立即重新绘制。这就是白色区域消失的原因。它们只是白色的,因为窗户上还没有油漆。这样做的副作用是,计算机开始滞后,因为它不能同时跟上所有这些。这就是为什么它通常不会绘制这些区域,以及为什么当你强制它绘制时,当你开始快速移动时,它似乎失去了控制。这是一种权衡,你必须选择你更能接受的,或者使用双缓冲(这只是一个技巧,不是真正的解决办法)之类的替代策略。一个原因可能是我只在StatusStrip\u MouseMove上跟踪移动,如果调整大小比鼠标移动慢,鼠标将离开StatusStip区域,不再调用任何移动。。。另一件事是Refresh()似乎重新绘制了所有父对象,而不仅仅是控制区域-这也需要时间…@serhio:这是可能的,但它仍然无法解决绘制问题。你的代码很奇怪。当无法将值设置为null
时,为什么要使用null
类型?尝试在调整大小事件期间捕获鼠标。是您需要的属性。+1关于捕获。我在MouseDown执行StatusStrip1.Capture=true,在mouseUp执行StatusStrip1.Capture=False。现在工作很酷!
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