Reputation: 258
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.
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.
This is what I wrote so far:
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
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'.
Upvotes: 1
Views: 277
Reputation: 32223
Problems in the current code:
Option Strict is Off
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
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.
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.
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
.
Here's something you can do:
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.
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()
.
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.
► 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.
► 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.
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()
The QRImageSize
public Property allow to change the Size of the QR Control before showing a new Dialog. The default Size is (500, 500)
.
Modified SchermataCode
class:
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
The null conditional operator is used here to avoid checking for null when disposing of some objects (e.g, qrForm?.Dispose()
).
If your VB.Net version doesn't allow it, change it in, e.g:
If qrForm IsNot Nothing Then qrForm.Dispose()
Upvotes: 1