VB winforms自定义控件缩放和平移功能

本文关键字:功能 缩放 winforms 自定义控件 VB | 更新日期: 2023-09-27 18:26:33

我目前正在为Winforms制作一个节点图控件,该控件包含的节点基本上只是一个具有属性的"空"类,因此节点绘制在控件中,控件处理它们。

我的控件需要支持缩放和平移。目前,我使用Graphics.ScaleTransform方法进行缩放,并使用AutoScroll进行平移。

这两个单独使用效果很好,但将它们一起使用是行不通的。

为了使平移"更好",我隐藏了滚动条,将AutoScrollMinSize设置为9000,并将AutoScroll Position(4500)居中。因此,希望你有一块画布可以工作,这样你就可以朝着你想要的任何方向前进。

这非常有效,但是当缩放(ScaleTransform)时,节点将移动x到表单的左上角(如果缩小)或右下角(如果放大)。

Youtube问题视频:https://www.youtube.com/watch?v=uJBAHtNhung

因此,由于stackoverflow上的文本长度问题,我无法发布所有代码,所以我将尝试发布相关内容(我想我无论如何都应该这样做)。

自定义控件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

我该如何解决这个问题,或者我应该以不同的方式来解决这个问题(也许画一个图像,然后重新定位该图像,等等)?

VB winforms自定义控件缩放和平移功能

答案是删除自动滚动,然后在进行缩放或平移时重新定位所有节点。

缩放:

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)