VB winforms自定义控件缩放和平移功能?
VB winforms custom control zoom and pan functionality?
我目前正在为 Winforms 制作一个节点图控件,该控件包含的节点基本上只是一个具有属性的 "empty" class,因此节点是在控件和控件中绘制的处理它们。
我的控件需要支持缩放和平移。目前我正在使用 Graphics.ScaleTransform 方法进行缩放,并使用 AutoScroll 进行平移。
两者单独使用效果很好,但一起使用时效果不佳。
为了进行平移 "better",我隐藏了滚动条,将 AutoScrollMinSize 设置为 9000 并将 AutoScrollPosition (4500) 居中。希望您感觉自己有一个 canvas 可以继续努力,这样您就可以朝着自己喜欢的任何方向前进。
效果很好,但是在缩放 (ScaleTransform) 时,节点将移动 x 到表单的左上角(如果缩小)或右下角(如果放大)。
问题的 Youtube 视频:https://www.youtube.com/watch?v=uJBAHtNhung
所以由于 Whosebug 上的文本长度问题,我不太能够 post 所有代码,所以我将尝试 post 相关的东西(我猜无论如何我都应该这样做)。
自定义控件 OnPaint:
G.TranslateTransform(AutoScrollPosition.X, AutoScrollPosition.Y)
G.ScaleTransform(Zoom, Zoom)
'Draw grid
If ShowGrid Then
Using Pen As New Pen(GridColor.ToBrush())
For row As Integer = 0 To viewportRect.Right Step GridSize.Width
G.DrawLine(Pen, New Point(row, 0), New Point(row, 0 + viewportRect.Bottom))
Next
For col As Integer = 0 To viewportRect.Bottom Step GridSize.Height
G.DrawLine(Pen, New Point(0, col), New Point(0 + viewportRect.Right, col))
Next
End Using
End If
'Draw connections
For Each Connection As Connection In Connections
Connection.Draw(G)
Next
'Draw all the nodes
For Each Node As Node In Nodes
Node.Draw(G)
Next
'Draw the active tool (Multi select or NodeLinker)
If ActiveTool IsNot Nothing Then
ActiveTool.OnDraw(G)
End If
缩放:
If e.Delta < 0 Then
NodeContainer.Zoom -= 0.1F
Else
NodeContainer.Zoom += 0.1F
End If
潘:
If Panning Then
Delta = New Point(StartPoint.X - e.X, StartPoint.Y - e.Y)
NodeContainer.AutoScrollPosition = New Point(Delta.X - NodeContainer.AutoScrollPosition.X, Delta.Y - NodeContainer.AutoScrollPosition.Y)
End If
我将如何解决这个问题,或者我应该以不同的方式解决这个问题(也许改为绘制图像,然后重新定位该图像等)?
答案是删除自动滚动,然后在发生缩放或平移时重新定位所有节点。
缩放:
oldZoom = NodeContainer.Zoom
If e.Delta < 0 Then
NodeContainer.Zoom = Math.Max(NodeContainer.Zoom - 0.1F, 0.01F)
Else
NodeContainer.Zoom = Math.Min(NodeContainer.Zoom + 0.1F, 10.0F)
End If
For Each Node As Node In NodeContainer.Nodes
oldZoomLocation = New Point(e.X / oldZoom, e.Y / oldZoom)
newZoomLocation = New Point(e.X / NodeContainer.Zoom, e.Y / NodeContainer.Zoom)
Node.Location = New Point(newZoomLocation.X - oldZoomLocation.X + Node.Location.X, newZoomLocation.Y - oldZoomLocation.Y + Node.Location.Y)
Next
潘:
Delta = New Point(e.X - StartPoint.X, e.Y - StartPoint.Y)
For Each Node As Node In NodeContainer.Nodes
Node.Location = New Point(Node.Location.X + (Delta.X / NodeContainer.Zoom), Node.Location.Y + (Delta.Y / NodeContainer.Zoom))
Next
StartPoint = New Point(e.X, e.Y)
我目前正在为 Winforms 制作一个节点图控件,该控件包含的节点基本上只是一个具有属性的 "empty" class,因此节点是在控件和控件中绘制的处理它们。
我的控件需要支持缩放和平移。目前我正在使用 Graphics.ScaleTransform 方法进行缩放,并使用 AutoScroll 进行平移。
两者单独使用效果很好,但一起使用时效果不佳。
为了进行平移 "better",我隐藏了滚动条,将 AutoScrollMinSize 设置为 9000 并将 AutoScrollPosition (4500) 居中。希望您感觉自己有一个 canvas 可以继续努力,这样您就可以朝着自己喜欢的任何方向前进。
效果很好,但是在缩放 (ScaleTransform) 时,节点将移动 x 到表单的左上角(如果缩小)或右下角(如果放大)。
问题的 Youtube 视频:https://www.youtube.com/watch?v=uJBAHtNhung
所以由于 Whosebug 上的文本长度问题,我不太能够 post 所有代码,所以我将尝试 post 相关的东西(我猜无论如何我都应该这样做)。
自定义控件 OnPaint:
G.TranslateTransform(AutoScrollPosition.X, AutoScrollPosition.Y)
G.ScaleTransform(Zoom, Zoom)
'Draw grid
If ShowGrid Then
Using Pen As New Pen(GridColor.ToBrush())
For row As Integer = 0 To viewportRect.Right Step GridSize.Width
G.DrawLine(Pen, New Point(row, 0), New Point(row, 0 + viewportRect.Bottom))
Next
For col As Integer = 0 To viewportRect.Bottom Step GridSize.Height
G.DrawLine(Pen, New Point(0, col), New Point(0 + viewportRect.Right, col))
Next
End Using
End If
'Draw connections
For Each Connection As Connection In Connections
Connection.Draw(G)
Next
'Draw all the nodes
For Each Node As Node In Nodes
Node.Draw(G)
Next
'Draw the active tool (Multi select or NodeLinker)
If ActiveTool IsNot Nothing Then
ActiveTool.OnDraw(G)
End If
缩放:
If e.Delta < 0 Then
NodeContainer.Zoom -= 0.1F
Else
NodeContainer.Zoom += 0.1F
End If
潘:
If Panning Then
Delta = New Point(StartPoint.X - e.X, StartPoint.Y - e.Y)
NodeContainer.AutoScrollPosition = New Point(Delta.X - NodeContainer.AutoScrollPosition.X, Delta.Y - NodeContainer.AutoScrollPosition.Y)
End If
我将如何解决这个问题,或者我应该以不同的方式解决这个问题(也许改为绘制图像,然后重新定位该图像等)?
答案是删除自动滚动,然后在发生缩放或平移时重新定位所有节点。
缩放:
oldZoom = NodeContainer.Zoom
If e.Delta < 0 Then
NodeContainer.Zoom = Math.Max(NodeContainer.Zoom - 0.1F, 0.01F)
Else
NodeContainer.Zoom = Math.Min(NodeContainer.Zoom + 0.1F, 10.0F)
End If
For Each Node As Node In NodeContainer.Nodes
oldZoomLocation = New Point(e.X / oldZoom, e.Y / oldZoom)
newZoomLocation = New Point(e.X / NodeContainer.Zoom, e.Y / NodeContainer.Zoom)
Node.Location = New Point(newZoomLocation.X - oldZoomLocation.X + Node.Location.X, newZoomLocation.Y - oldZoomLocation.Y + Node.Location.Y)
Next
潘:
Delta = New Point(e.X - StartPoint.X, e.Y - StartPoint.Y)
For Each Node As Node In NodeContainer.Nodes
Node.Location = New Point(Node.Location.X + (Delta.X / NodeContainer.Zoom), Node.Location.Y + (Delta.Y / NodeContainer.Zoom))
Next
StartPoint = New Point(e.X, e.Y)