Check createHandler() before closing form() vb.net - vb.net

I'm currently running into a problem with a windows form application Closing.
I have multiple forms inside a main form. If I close the main form while one of the forms inside the main form is stil initializing the application crashes on Close() because createHandler() still running.
I already solved this inside one of the sub forms to add a boolean to Load() and check if the boolean is true. Example:
Private Sub frm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ini = True
// loading components etc.
ini = False
End Sub
Private Sub frm_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
If e.KeyData = Keys.Escape Then
If (not ini)
Close()
End If
End If
Now I have simulair issue in the main form.
Dim Childs = (From rec In Me.MdiChildren).ToList
For Each Child In Childs
Child.Close()
Next
Is there anyway to verify if the childForm has been initialize before I close it?
something like: Child.IsInit()

Related

Why does a form move trigger ResizeEnd?

I use the following code in my form:
Public Class Form1
Private Sub Form1_ResizeEnd(sender As Object, e As EventArgs) Handles MyBase.ResizeEnd
MsgBox("Resized")
End Sub
End Class
When I move my form, it also seems to trigger MyBase.ResizeEnd. Why is that? A move of the panel doesn't change the size, so I don't understand why.
Why does a form move trigger ResizeEnd?
Because this is the documented behavior. From the documentation:
The ResizeEnd event is also generated after the user moves a form, typically by clicking and dragging on the caption bar.
If you want an event that doesn't get triggered when the form is moved, you should use either Resize or SizeChanged. The problem with those two events is that they will be triggered while the form is being resized by the user. To work around that, you may use it with both ResizeBegin and ResizeEnd with a couple of flags to signal when the user actually finishes resizing the form.
Here's a complete example:
Private _resizeBegin As Boolean
Private _sizeChanged As Boolean
Private Sub Form1_ResizeBegin(sender As Object, e As EventArgs) Handles MyBase.ResizeBegin
_resizeBegin = True
End Sub
Private Sub Form1_SizeChanged(sender As Object, e As EventArgs) Handles MyBase.SizeChanged
' This is to avoid registering this as a resize event if it was triggered
' by another action (e.g., when the form is first initialized).
If Not _resizeBegin Then Exit Sub
_sizeChanged = True
End Sub
Private Sub Form1_ResizeEnd(sender As Object, e As EventArgs) Handles MyBase.ResizeEnd
_resizeBegin = False
If _sizeChanged Then
_sizeChanged = False
MessageBox.Show("The form has been resized.")
End If
End Sub
One thing to note is that both ResizeBegin and ResizeEnd are only triggered when the user manually resizes* the form. It does not, however, handle other situations like when the form is resized via code, when the form is maximized, or restored.
* or moves the form, which is the part that we're trying to avoid here.

Cross-thread operation not valid: problem

I am working in Visual Studio 2019 and writing in Visual Basic. I get this error: Cross-thread operation not valid: Control 'lblTesting' accessed from a thread other than the thread it was created on.' (lblTesting is just a label for testing purposes).
I call the FrmContacts like this:
Private Sub ContactsToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ContactsToolStripMenuItem.Click
Me.Enabled = False
FrmContacts.Show()
End Sub
and return from the form like this:
Private Sub FrmContacts_Closed(sender As Object, e As EventArgs) Handles Me.Closed
Me.Close()
FrmMain.Enabled = True
End Sub
The error pops up when I exit FrmContacts.
I tried deleting the form and recreating it but the error is there as soon as I add any control. I am dumbfounded. Searching has not revealed any hints.
I had to take out the Me.Close() because I was closing a closed form. The new code works fine. It is:
Private Sub FrmContacts_Closed(sender As Object, e As EventArgs) Handles Me.Closed
FrmMain.Enabled = True
End Sub
Also, if your intention is to make the "main" form inaccessible until the "child" form is closed, then simply use ShowDialog() instead:
You can use this method to display a modal dialog box in your
application. When this method is called, the code following it is not
executed until after the dialog box is closed.
Private Sub ContactsToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ContactsToolStripMenuItem.Click
FrmContacts.ShowDialog()
End Sub

Improve UI responsiveness on windows form application

I am currently working on a project and decided to create a user interface for it using visual studio with a windows forms application(Visual Basic).
The problem I'm facing is that the user interface doesn't respond as quickly and smoothly as I'd like it to.
Mainly, I am using pictures as buttons to make the user form look more modern.
However, when I hover my mouse over a "button" it takes a while until the "highlighted button" appears.
P1 is the picture of the "normal button" and P2 is the picture of the "highlighted button".
Here is the short code I have for now:
Public Class Main
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub PictureBox1_MouseHover(sender As Object, e As EventArgs) Handles P1.MouseHover
P1.Visible = False
P2.Visible = True
End Sub
Private Sub P2_MouseClick(sender As Object, e As MouseEventArgs) Handles P2.MouseClick
'Call cmdInit()
'Call cmdConnectRobot()
'Call cmdUnlock()
End Sub
Private Sub Main_MouseHover(sender As Object, e As EventArgs) Handles Me.MouseHover
If P2.Visible = True Then
P2.Visible = False
P1.Visible = True
End If
End Sub
Private Sub P4_Click(sender As Object, e As EventArgs) Handles P4.Click
End Sub
End Class
Another problem I'm facing is that when I call other subs, the user form becomes unresponsive while the sub is running.
I researched and found that I could implement multi threading or async tasks but I'm a bit lost and would be extremely grateful if someone could guide me or point me in the right direction.
Thanks in advance!!
In this case your UI is responsive, however the MouseHover event is only raised once the mouse cursor has hovered over the control for a certain amount of time (default is 400 ms), which is what is causing the delay.
What you are looking for is the MouseEnter event, which is raised as soon as the cursor enters ("touches") the control:
Private Sub P1_MouseEnter(sender As Object, e As EventArgs) Handles P1.MouseEnter
P1.Visible = False
P2.Visible = True
End Sub
You can then use that together with the MouseLeave event on the second picture box to switch back to the non-highlighted image:
Private Sub P2_MouseLeave(sender As Object, e As EventArgs) Handles P2.MouseLeave
P1.Visible = True
P2.Visible = False
End Sub
However switching picture boxes like this is not optimal. I recommend you to look into how you can use Application Resources, then modify your code to only switch the image that one picture box displays.
Here are the basic steps:
Right-click your project in the Solution Explorer and press Properties.
Select the Resources tab.
To add an image either:
a. Drag and drop the image onto the resource pane.
b. Click the arrow next to the Add Resource... button and press Add Existing File....
Now, in your code add this right below Public Class Form1:
Dim ButtonNormal As Image = My.Resources.<first image name>
Dim ButtonHighlighted As Image = My.Resources.<second image name>
Replace <first image name> and <second image name> with the names of your button images.
Now you only need one picture box for the button:
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
P1.Image = ButtonNormal
End Sub
Private Sub P1_MouseEnter(sender As System.Object, e As System.EventArgs) Handles P1.MouseEnter
P1.Image = ButtonHighlighted
End Sub
Private Sub P1_MouseLeave(sender As System.Object, e As System.EventArgs) Handles P1.MouseLeave
P1.Image = ButtonNormal
End Sub
I'll start by saying i'm not a programmer by trade, and i'm sure someone will point out better ways of doing these things, but in regards to the threading question it's fairly simple to implement.
Imports System.Threading
Public Class Form1
Dim WorkerThread As New Thread(AddressOf DoWork)
'WorkerThread' can be any name you like, and 'DoWork' is the name of the sub you want to run in the new thread, and is launched by calling:
WorkerThread.start()
However there is a catch, the new thread is not able to interact directly with the GUI, so you cannot change textbox text etc... I find the easiest way to get changes made to the GUI is to drag a timer onto your form, and have the new thread change variables (pre-defined just below Public Class Form1), then use the Timer1 Tick event to monitor the variables and update the GUI if there are any changes.

Reopening a Disposed form declared with events. VB.net

I have a dialog form which is a bar code scanner handler form that has events on the form it was called from, done like this:
Public Class FRMCheckout
Dim WithEvents Batch_Scanner_Dialog As New CheckoutBatchScanner
Private Sub Recieve_Scaned_Object(Scan_Object As tructures.ScanDetails) Handles Batch_Scanner_Dialog.Scanned_Item
'.....Do Stuff'
End Sub
Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
Batch_Scanner_Dialog.Show()
End Sub
End Class
The Batch_Scanner_Dialog is closed with just the regular old Close.Me which opbviously disposes itself.
The problem being if you wish to open the dialog again, an accessing a disposed object exception is thrown.
Locally Declaring the Dialog will not work, because it has events, so how could I fix this issue? Calling a new instance of the dialog is fine, just the original Events should be on the calling form. (They vary depending on the form the dialog is called form)
(Note: I need to use .show not .showdialog to continue to run code on the original form.)
OK the problem was solved with:
Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
If Batch_Scanner_Dialog.IsDisposed Then
Dim Batch_Scanner_Dialog As New CheckoutBatchScanner
AddHandler Batch_Scanner_Dialog.Scanned_Item, AddressOf Recieve_Scaned_Object
Batch_Scanner_Dialog.Show()
Else
Batch_Scanner_Dialog.Show()
End If
End Sub

combobox not being populated

I have a windows form project with a main form. There is a textbox leave event that opens a new form. In that new forms load event i have a combobox item loop that populates the combobox items. It works perfectly fine if run on the main form but doesnt work on the second form. Why doesn't the comboboxes on the secondary form populate when that form is opened via a textbox_leave event from the main form?
this is the leave event
Private Sub tbChartTitle_Leave(sender As Object, e As System.EventArgs) Handles tbChartTitle.Leave
If Not tbChartTitle.Text = Nothing Then
frmTitleAttributes.Show()
End If
End Sub
This is the code that populates one of the comboboxes on the second form (it works if run on a combobox on the main form)
Private Sub frmTitleAttributes_Load(sender As Object, e As System.EventArgs) Handles Me.Load
InitializeComponent()
AddFonts()
End Sub
Private Sub AddFonts()
' Get the installed fonts collection.
Dim allFonts As New Drawing.Text.InstalledFontCollection
' Get an array of the system's font familiies.
Dim fontFamilies() As FontFamily = allFonts.Families
' Display the font families.
For i As Integer = 0 To fontFamilies.Length - 1
cbxTitleFonts.Items.Add(fontFamilies(i).Name)
Next
End Sub
make sure that the Load handler is hit after you show your form (use break point)
also you can try to call it in the Shown event
Private Sub frmTitleAttributes_Shown(sender as Object, e as EventArgs) _
Handles frmTitleAttributes.Shown
AddFonts()
End Sub