创建一个新的窗体并在运行时添加事件处理程序 [英] Create a new Form and add event handlers at Run Time

查看:114
本文介绍了创建一个新的窗体并在运行时添加事件处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在运行时创建一个新的无边界表单,并且需要事件处理程序来移动不带标题的表单。

I'm trying to create a new border-less Form at Run-Time and the Event Handlers required to move the Form without its Caption.

该表单应为对话框可以使用专门的控件显示呈现的QR码。

表单还应该调整自身大小以适合不同大小的QR码。

The Form is meant to be a Dialog that can show rendered QR Codes, using a specialized Control.
The Form should also resize itself to fit different sizes of QR Codes.

到目前为止写道:

Imports System.Drawing
Imports System.Windows.Forms

Public Class Form1

    Dim schermataqrcode As New Form

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        schermataqrcode.FormBorderStyle = FormBorderStyle.None
        AddHandler schermataqrcode.MouseDown, AddressOf schermataqrcode.MouseDown
        AddHandler schermataqrcode.MouseUp, AddressOf schermataqrcode.MouseUp
        AddHandler schermataqrcode.MouseMove, AddressOf schermataqrcode.MouseMove

        Dim qrcode As New qrcode
        qrcode.Dock = DockStyle.Fill
        schermataqrcode.Controls.Add(qrcode)
        schermataqrcode.StartPosition = FormStartPosition.CenterScreen
        schermataqrcode.Show()
    End Sub

    Public Class schermatacode
        Private IsDraggingForm As Boolean = False
        Private MousePos As New System.Drawing.Point(0, 0)

        Private Sub schermataqrcode_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
            If e.Button = MouseButtons.Left Then
                IsDraggingForm = True
                MousePos = e.Location
            End If
        End Sub

        Private Sub schermataqrcode_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs)
            If e.Button = MouseButtons.Left Then IsDraggingForm = False
        End Sub

        Private Sub schermataqrcode_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
            If IsDraggingForm Then
                Dim temp As Point = New Point(Me.Location + (e.Location - MousePos))
                Me.Location = temp
                temp = Nothing
            End If
        End Sub
    End Class
End Class

我不确定这是VS错误:

I'm not sure about that as VS errors:

 BC30577    'AddressOf' operand must be the name of a method (without parentheses).
 BC30577    'AddressOf' operand must be the name of a method (without parentheses).
 BC30577    'AddressOf' operand must be the name of a method (without parentheses).
 BC30456    'Location' is not a member of 'Form1.schermatacode'.
 BC30456    'Location' is not a member of 'Form1.schermatacode'.


推荐答案

当前代码中的问题


  • 选项严格为 Off

schermataqrcode 表单的事件应该由 schermatacode 处理类对象,但赋值根本不指向 schermatacode 类:

The schermataqrcode Form's events are supposed to be handled by the schermatacode class object, but the assignment doesn't point to the schermatacode class at all:

AddHandler schermataqrcode.MouseDown, AddressOf schermataqrcode.MouseDown 
' should be:
AddHandler schermataqrcode.MouseDown, AddressOf schermatacode.schermataqrcode_MouseDown

,但是您没有创建此类的实例(该实例不是静态的并且不能是),并且在任何情况下都将事件处理程序声明为 Private ,因此您仍然无法到达它们。

but you did not create an instance of this class (which is not static and cannot be) and in any case the event handlers are declared Private, so you cannot reach them anyway.

即使正确设置了事件处理程序,窗体的ClientArea也完全被停靠的控件填充,因此它赢得了胜利。没有收到鼠标事件。

Even if the event handlers were setup correctly, the Form's ClientArea is completely filled with a docked Control, so it won't receive mouse events.

此: Dim temp As Point = New Point(Me.Location +(e.Location-MousePos))不能使用:
- Me 不是Form,它是 schermatacode 类,没有 Location 属性。

-选项严格关闭对您隐藏了 Me.Location +(e.Location-MousePos)不返回可用的Point。设置 Option Strict On 时,看看 Point = Point +(Point-Point)的实际含义。

This: Dim temp As Point = New Point(Me.Location + (e.Location - MousePos)) cannot be used: - Me is not the Form, it's the schermatacode class, which doesn't have a Location property.
- Option Strict Off hides from you that Me.Location + (e.Location - MousePos) doesn't return a usable Point. See what Point = Point + (Point - Point) actually is when you set Option Strict On.

这是您可以做的事情


  • 移动SchermataCode类对象中的所有逻辑:您只是在创建一个包含单个Control的标准Form(基于描述,但是您可以添加所需的所有控件)。此类处理表单和QR控件的创建,并设置所需的所有事件处理程序。

  • Move all the logic in the SchermataCode class object: you're simply creating a standard Form that contains a single Control (based on the description, but you can add all the controls you want). This class handles the creation of the Form and the QR Control and also sets up all the event handlers needed.

使用单个类对象一切,您都可以初始化该类并在需要时使用它,只需使用它,例如, Dim qrForm = New SchermataCode()

Using a single class object for everything, you can just initialize the class and use it whenever you need it simply with, e.g., Dim qrForm = New SchermataCode().

然后, SchermataCode 对象可以公开公共方法和属性,从而只需调用方法或检查属性即可使用其功能

在示例代码中, SchermataCode 公开了一个 ShowForm( ) 公共方法,将窗体显示为对话框。您可以将字符串传递给此方法以呈现为QR图像。这样,您可以使用同一类显示多个Form,也可以在应用程序的生命期内使用同一类对象。

The SchermataCode object can then expose public methods and properties that allow to use its functionalities simply calling a method or inspecting a property, as usually happens with the .Net classes.
In the sample code, SchermataCode exposes a ShowForm() public method that shows the Form as a Dialog. You can pass to this method the string to render as a QR Image. This way, you can use the same class to show more than one Form, you can also use the same class object for the life of your Application.

►请注意, SchermataCode 还会公开 Dispose() 方法:此方法允许处理Form,QR控件并删除添加到这些控件的所有处理程序。非常重要的一点是,当不再需要 SchermataCode 时,调用此方法(与.Net一样)以释放这些对象分配的资源。

当然,如果需要,您可以在之后创建另一个实例。

► It's important to notice that SchermataCode also expose a Dispose() method: this method allows to dispose of the Form, the QR Control and remove all the handlers added to these controls. It's very important that you call this method - as usual in .Net - to release the resources that these objects are allocating when you don't need SchermataCode anymore.
Of course, you can create another instance after, if needed.

注意:自QR Control QR控件使用其 MouseDown MouseMove 事件,而不是表单事件(因为表单不会接收鼠标事件)。

我不确定QR Control是否具有与这些事件相关的某些特定功能(如果您

另外,双击QR控件,将导致窗体关闭。

NOTE: Since the QR Control occupies the whole ClientArea of the Form, the border-less Form movement is handled by the QR Code Control, using its MouseDown and MouseMove events instead of those of the Form (since the Form won't receive mouse events).
I'm not sure whether the QR Control has some specific functionality related to these events (if you click it, something happens. Let me know if that's the case).
Also, double clicking the QR Control, causes the Form to close.

例如,创建一个 SchermataCode 实例并依次显示两个窗体,并分配 ShowForm()返回lo在一种情况下,将cal变量转换为在另一种情况下,将其转换为PictureBox控件(我不确定QR控件是否返回渲染的Image,或者即使您需要它,也只是为了显示此类的工作原理。)

For example, create a SchermataCode instance and show two Forms in sequence, assigning the Images that ShowForm() returns to a local variable in one case and to a PictureBox control in the other (I'm not sure whether the QR Control returns the rendered Image, or even if you need it, it's meant to show how this class works).

Dim qrForm = New SchermataCode()

' Shown the Dialog using the default Size 
Dim result As Image = qrForm.ShowForm("<Some QR String>")

qrForm.QRImageSize = New Size(200, 200)
PictureBox1.Image = qrForm.ShowForm("<Some Other QR String>")
qrForm.Dispose()

QRImageSize 公共属性允许在显示新对话框之前更改QR控件的大小。默认大小为(500,500)

修改后的 SchermataCode 类:

Public Class SchermataCode
    Implements IDisposable

    Private qrForm As Form = Nothing
    Private qr As qrcode = Nothing
    Private startPosition As Point = Point.Empty

    Public Sub New()
        qrForm = New Form() With {
            .FormBorderStyle = FormBorderStyle.None,
            .StartPosition = FormStartPosition.CenterScreen
        }

        qr = New qrcode() With {.Size = QRImageSize}
        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 Property QRImageSize As Size = New Size(500, 500)

    Public Function ShowForm(qrString As String) As Image
        If QRImageSize <> qr.Size Then qr.Size = QRImageSize
        qrForm.ClientSize = qr.Size
        qr.Text = qrString
        qrForm.ShowDialog()
        Return qr.Image
    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 qr IsNot Nothing Then
                RemoveHandler qr.MouseDown, AddressOf qrCode_MouseDown
                RemoveHandler qr.MouseMove, AddressOf qrCode_MouseMove
                RemoveHandler qr.DoubleClick, AddressOf qrCode_OnDoubleClick
            End If
            qr?.Dispose()
            qrForm?.Dispose()
        End If
    End Sub
End Class




空条件运算符以避免在处置某些对象(例如 qrForm?.Dispose())时检查是否为null。


The null conditional operator is used here to avoid checking for null when disposing of some objects (e.g, qrForm?.Dispose()).

如果您的VB.Net版本不允许,请更改它,例如:

If your VB.Net version doesn't allow it, change it in, e.g:

If qrForm IsNot Nothing Then qrForm.Dispose()

这篇关于创建一个新的窗体并在运行时添加事件处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆