创建一个新的窗体并在运行时添加事件处理程序 [英] Create a new Form and add event handlers at Run Time
问题描述
我正在尝试在运行时创建一个新的无边界表单,并且需要事件处理程序来移动不带标题的表单。
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 $ c来占据窗体的整个ClientArea,无边界的Form移动由QR Code Control处理。 $ c>事件,而不是表单事件(因为表单不会接收鼠标事件)。
我不确定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()$ c的图像$ c>返回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屋!