如何将两个表单锁定在一起并将它们作为一个单独的表单移动?

How to lock two forms together and moving them as a single one?

我在 运行 时间创建了一个表单,并向其中添加了一个控件。我选择使用 New Point(Form1.Location.X + Form1.Width, Form1.Location.Y) 将 form2 定位在靠近 form1 的位置,并且两种表单边框样式都设置为“None”,因此我使用了 3 个鼠标事件以使它们“可拖动”(在 form1 和 form2 中)。我正在使用来自

的好代码

一切正常。所以当 form2 打开时问题就开始了。 我创建了一个 gif Imgur gif 以便更好地解释。 Form 1 单独 id 可移动,form2 单独 id 可移动。 Form2 移动 form1 而本身不移动。 我在 form1(usercontrol1) 中使用的代码调用 form2(qrcode):

    Dim qrForm = New SchermataCode()

    qrForm.ShowForm()
    Form1.TopMost = True
    qrform.dispose()

我在 control2(qrcode) 中使用的内容:

    Private Sub qrcode_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
    If e.Button = MouseButtons.Left Then
        startPosition = e.Location
    End If
End Sub
Private Sub qrcode_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
    If e.Button = MouseButtons.Left Then
        Form1.Location = New Point(
            Form1.Left + (e.X - startPosition.X),
            Form1.Top + (e.Y - startPosition.Y))
    End If
End Sub
Private Sub PictureBox10_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox10.MouseMove
    If e.Button = MouseButtons.Left Then
        Form1.Location = New Point(
            Form1.Left + (e.X - startPosition.X),
            Form1.Top + (e.Y - startPosition.Y))
    End If
End Sub

Private Sub PictureBox10_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox10.MouseDown
    If e.Button = MouseButtons.Left Then
        startPosition = e.Location
    End If
End Sub

这就是我生成新表单并添加 control2(二维码)的方式

    Option Strict On

Public Class SchermataCode
    Implements IDisposable

    Private qrForm As Form = Nothing
    Private qr As qrcode = Nothing
    Private startPosition As Point = Point.Empty
    ' Dim qrcode As New qrcode
    Public Sub New()
        qrForm = New Form() With {
            .FormBorderStyle = FormBorderStyle.None,
            .StartPosition = FormStartPosition.Manual,
            .Location = New Point(Form1.Location.X + Form1.Width, Form1.Location.Y),
            .AutoScaleMode = AutoScaleMode.None,
            .Icon = DirectCast(My.Resources.ResourceManager.GetObject("_" & My.Settings.icona), Icon),
            .Dock = DockStyle.Fill,
            .TopMost = True
        }

        qr = New qrcode()
        AddHandler qr.MouseDown, AddressOf qrCode_MouseDown
        AddHandler qr.MouseMove, AddressOf qrCode_MouseMove
        AddHandler qr.DoubleClick, AddressOf qrCode_OnDoubleClick
        qrForm.Controls.Add(qr)
    End Sub

    Public Function ShowForm() As Image
        qrForm.ClientSize = qr.Size
        qrForm.Showdialog
        Form1.TopMost = True
    End Function


    Private Sub qrCode_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
        If e.Button = MouseButtons.Left Then
            startPosition = e.Location
        End If
    End Sub

    Private Sub qrCode_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
        If e.Button = MouseButtons.Left Then
            qrForm.Location = New Point(
                qrForm.Left + (e.X - startPosition.X),
                qrForm.Top + (e.Y - startPosition.Y))
        End If
    End Sub

    Private Sub qrCode_OnDoubleClick(ByVal sender As Object, ByVal e As EventArgs)
        qrForm.Close()
    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub

    Protected Overridable Sub Dispose(disposing As Boolean)
        If disposing Then
            If qrForm IsNot Nothing Then
                RemoveHandler qr.DoubleClick, AddressOf qrCode_OnDoubleClick
                RemoveHandler qr.MouseDown, AddressOf qrCode_MouseDown
                RemoveHandler qr.MouseMove, AddressOf qrCode_MouseMove
            End If
            qr?.Dispose()
            qrForm?.Dispose()
        End If
    End Sub
End Class

有人知道吗?我想打开靠近 form1 的 form2,将两者拖在一起,如果双击 form2,则关闭它,只打开 form1。 Form1 在一起时不拖 form2。

谢谢

对于阅读这篇文章的任何人 question/answer,很多都是通过 CHAT 完成的,这不是最终的解决方案。

So my question is: I can't declare again "Dim qrForm = New SchermataCode()" in form1(usercontrol)Mouse_move as I'm already calling it In a button , so how can I make it public ? I tried to insert that under Public Class UserControl1 but it goes on Whosebug.. Thanks

这是涉及 Scope 的设计问题。

将“qrForm”的声明移动到 UserControl 级别,因此它不在 Button 处理程序中:

' ... code in UserControl (that is housed by the Main Form) ...

Private qrForm As SchermataCode

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    If IsNothing(qrForm) Then
        qrForm = New SchermataCode()
    End If
    qrForm.ShowForm()
    Form1.TopMost = True
End Sub

并不是说我正在检查“qrForm”是否为空(null)或者它在创建之前是否已被处理(关闭)。

在您要移动辅助表单的处理程序中,您需要在尝试使用它之前执行类似的操作:

' ... code in UserControl (that is housed by the Main Form) ...

' The Foo() below could be any handler (like a MouseMove)
Private Sub Foo() 
    If (Not IsNothing(qrForm)) AndAlso (Not qrForm.IsDisposed) Then

        ' ... do something with "qrForm" in here (like move it) ...

    End If
End Sub

-----看完评论下方发的GIF-----

天哪……我明白现在发生了什么。 您的变量名还有很多不足之处。 在 UserControl1 中,您有一个类型为 SchermataCode 的名为 qrForm 的变量。然后,在 class SchermataCode 中,您有另一个名为 qrForm 的变量,它是您要操作的实际形式!我们很接近!

首先,在classSchermataCode中,将qrForm的声明从Private改为Public

Public Class SchermataCode
    Implements IDisposable

    Public qrForm As Form = Nothing

    ' ... the rest of the existing code ...

End Class

现在,在 UserControl1 中,我们想要访问上面的“内部”qrForm。这看起来很奇怪,因为您将变量命名为相同的名称:

' ... inside the PictureBox5_MouseMove() method of UserControl1 ...

If Not IsNothing(qrForm) Then   
   ' Let's make a variable that points directly to the secondary Form:
    Dim frm As Form = qrForm.qrForm ' <--- use better names next time!  =)

    ' Now let's move it:
    frm.Location = New Point(
        frm.Left + (e.X - startPosition.X),
        frm.Top + (e.Y - startPosition.Y))
End If

希望现在问题已经解决了。