.Net WindowsForms MouseDown event not firing - vb.net

As a new user to VB, I am struggling to see why this code works in one project but not in another. This code works fine if I create a new project and 2 new forms but when I place in my project, it doesn't fire at all on either left or right click.
I have tried a try/catch statement, but no errors are being reported. How do I go about troubleshooting this to find out the error. I have tried to rem out code and run after each comment but still the same. I have even tried removing all other code on the form leaving just the 2 subs but no joy. Any help would be greatly appreciated.
frmMain
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'StorageDataSet1.Customers' table. You can move, or remove it, as needed.
Me.CustomersTableAdapter.Fill(Me.StorageDataSet1.Customers)
'TODO: This line of code loads data into the 'StorageDataSet.User' table. You can move, or remove it, as needed.
Me.UserTableAdapter.Fill(Me.StorageDataSet.User)
'Dim frmDepartmentsLive As New frmDepartment
'frmDepartmentsLive.Owner = Me
'frmDepartmentsLive.ShowDialog()
lblDate.Text = Now
Timer1.Start()
rdoCustomer.Enabled = False
rdoCustomer.Checked = True
rdoDepartment.Enabled = False
rdoDepartment.Checked = False
For Each ctrl In Me.Controls
If TypeOf ctrl Is Button Then
AddHandler CType(ctrl, Button).MouseDown, AddressOf btn_MouseDown
End If
Next
End Sub
Private Sub btn_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs)
If (e.Button = MouseButtons.Right) Then
Dim btn = CType(sender, Button)
frmRacks.buttonName = btn.Name.Replace("btn", "")
frmRacks.Show()
ElseIf (e.Button = MouseButtons.Left) Then
MessageBox.Show("To be coded")
End If
End Sub
frmRacks
Public Class frmRacks
Public buttonName As String
Private Sub racksfrm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
lblRacks.Text = buttonName
End Sub
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
Me.Close()
End Sub
End Class

Since the controls are on a panel, they are members of that panel's controls array, not the form's. This -- and other things -- are apparent if you look thru the form's designer (on solution explorer, click Show All, then open formXXX.designer.vb). DOnt change anything, but it shows how controls are created and added. So...
For Each ctrl In thepanelName.Controls
If TypeOf ctrl Is Button Then
AddHandler CType(ctrl, Button).MouseDown, AddressOf btn_MouseDown
End If
Next
If it is ONLY those buttons on the panel you can short cut it:
For Each btn As Button In thepanelName.Controls
AddHandler CType(ctrl, Button).MouseDown, AddressOf btn_MouseDown
Next

Related

Hiding Dynamically Created Buttons on click in Visual Basic Forms

Im currently trying to make dynamically created buttons disappear when clicked.
I have a Private Sub that handles when the button is clicked and increases the players score. However, i do not know how to make the specific object disappear as all the Objects are called the same name as they are created by the same subroutine set on a timer ( a new button made every 2 seconds).
I have tried adding every new button created to an array but am still struggling to make the program figure out which button has been clicked.
Any help would be greatly appreciated.
One of the parameters on your button click event handler should be sender As Object, which is a reference to the button that was clicked. You just need to cast it to a button object, the set the Visible property to false. Here is an example:
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim b As Button = CType(sender, Button)
b.Visible = False
End Sub
Further to #Icemanind's answer, you can actually do it in one line:
CType(sender, Button).Visible = False
This works without validation because you know that sender is of type Button.
If you have multiple buttons to handle, you can also add additional events to the handler so you don't end up with a zillion individual handlers:
Protected Sub Button_Click(s As Object, e As EventArgs) _
Handles _
Button1.Click, Button2.Click, Button3.Click
CType(s, Button).Visible = False
End Sub
Yet another option is to add the same handler to multiple buttons rather than adding buttons to the handler:
In Form instantiation (Sub New()):
AddHandler Button1.Click, AddressOf Button_Click
AddHandler Button2.Click, AddressOf Button_Click
AddHandler Button3.Click, AddressOf Button_Click
In Form class code:
Protected Sub Button_Click(s As Object, e As EventArgs)
CType(s, Button).Visible = False
End Sub
This last method works well with dynamic controls because you can add the handlers on the fly:
Dim button As Button
For i As Integer = 0 To 9
button = New Button With {.Name = $"Button{i}", .Text = $"Button{i}", .Left = 42, .Top = 50 + (i * 30)}
Me.Controls.Add(button)
AddHandler button.Click, AddressOf Button_Click
Next i

How to trigger a gotfocus datagrid combobox event while grid is readonly?

I have a datagridview and I'm trying to get the gotfocus event for my comboboxcells to still call despite the datagrid being on readonly.
This gotfocus event changes the colour of every combobox with a similar value (including itself) and I would like to it to still call while on readonly (the datagridview comboboxes can still be selected/highlighted while on readonly but it is not called(?))
Below is the basics of how I am currently handling the events (for some reason this shortened version makes multiple event calls at an exponential rate & also requires three clicks to trigger... I'm not sure why it does this but my full project works fine in this regard)
Public Class Form1
Private Sub cell_gotfocus(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
Dim CurrentCombo = TryCast(e.Control, ComboBox)
If Not CurrentCombo Is Nothing Then
RemoveHandler CurrentCombo.GotFocus, AddressOf Combo_Focus 'remove event handler so we don't accumulate multiples
AddHandler CurrentCombo.GotFocus, AddressOf Combo_Focus 'add eventhandler
End If
End Sub
Private Sub Combo_Focus()
Console.WriteLine("Got Focus")
Console.beep
End Sub
Private Sub Make_Readonly_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Make_Readonly.Click
DataGridView1.Rows(0).ReadOnly = True 'toggle readonly
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For y As Integer = 1 To 4 'add extra columns into datagrid
Dim cmb As New DataGridViewComboBoxColumn
cmb.HeaderText = "c" & DataGridView1.Columns.Count
cmb.Name = "c" & DataGridView1.Columns.Count
cmb.FlatStyle = FlatStyle.Flat
DataGridView1.Columns.Add(cmb)
Next
End Sub
End Class

How Do I Force An Action When A Dialog Box Closes In VB.Net?

I am wondering how to force my main gui to update when a dialog box such as a SaveFileDialog box closes. I have tried Main.LostFocus, Main.GotFocus, Main.Enter, Main.MouseEnter, Main.MouseLeave, and Main.MouseMove, but no matter what function I try I can never get the result I am looking for.
The dialog box is opened when a picture is clicked. The picture changes when it is clicked and again when the icon_new.MouseUp is called. The problem is that it acts correctly until the dialog is closed. At this point the picture changes back to the image it had when the mouse was over it.
Here is what the picture does regularly:
Private Sub icon_new_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles icon_new.MouseDown
icon_new.Image = My.Resources.NewMapClick
End Sub
Private Sub icon_new_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles icon_new.MouseUp
icon_new.Image = My.Resources.NewMapHover
End Sub
Private Sub icon_new_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles icon_new.MouseEnter
icon_new.Image = My.Resources.NewMapHover
End Sub
Private Sub icon_new_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles icon_new.MouseLeave
icon_new.Image = My.Resources.NewMapDefault
End Sub
This works until the dialog box is closed, at which point it the image becomes NewMapHover when it should be NewMapDefault, because the mouse is no longer within the bounds of the picture. In the calls such as Main.LostFocus, Main.GotFocus, or Main.Whatever I have icon_new.image = My.Resources.NewMapDefault, but even if this call triggers, the image ends up as NewMapHover. I'm not sure why this is happening or how to fix it. Any help is greatly appreciated.
EDIT: This is the click event that calls the dialog_box
Private Sub icon_new_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles icon_new.Click
If file_created = True Then
save()
Else 'file_created = false'
SaveWindow.FileName = txt_name.Text
If SaveWindow.ShowDialog() = DialogResult.OK Then
file_path = SaveWindow.FileName
End If
file_created = True
End If
save()
new_file()
End Sub
If the file hasn't been saved, then a dialog box opens, prompting the user to save the file. I've also toyed with a MsgBox() that has Yes, No, and Cancel, prompts, but for simplicity I took it out because the results were the same and one third of the time the SaveFile dialog will come up anyway.
Try doubleclicking your SaveFileDialog, which will open up the SaveFileDialog_FileOk event code, and then put the same code there as in the MouseLeave event.
This event will fire when the SaveFileDialog is about to close after you've pressed the "Save" button.
EDIT:
You can try doing this in your click event:
Dim DResult As DialogResult
DResult = SaveFileDialog1.ShowDialog()
If DResult = System.Windows.Forms.DialogResult.OK Then
'Code for when you press the save button, and when the image should change
ElseIf DResult = System.Windows.Forms.DialogResult.Cancel Then
'Code for image change...
End If
Try
Private Sub icon_new_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles icon_new.MouseUp
Dim pnt As Point
Dim rect As Rectangle
rect.X = icon_new.Location.X
rect.Y = icon_new.Location.Y
rect.Width = icon_new.Width
rect.Height = icon_new.Height
pnt = PointToClient(Cursor.Position)
If Not rect.Contains(pnt) Then
Return
End If
icon_new.Image = My.Resources.NewMapHover
End Sub
Valter
This is the code I originally had.
Private Sub icon_new_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles icon_new.MouseUp
icon_new.Image = My.Resources.NewMapHover
End Sub
I added the variable dialog_open as a boolean and set it to true whenever I called SaveFile.ShowDialog(). I then changed my MouseUp event to this:
Private Sub icon_new_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles icon_new.MouseUp
icon_new.Image = My.Resources.NewMapHover
If dialog_open = True Then
icon_new.Image = My.Resources.NewMapDefault
dialog_open = False
End If
End Sub
Thanks to #valter and #Kevin Hogg for suggesting I edit the MouseUp event.

How to select TextBox on Label Click

In Microsoft Access, when you click on a label, the textbox associated with that label gets the focus. As far as I can tell, VB.NET does not have this same functionality. I know I can always add something in to the click event of the label, like so...
TextBox1.Focus()
But I have dozens of fields on the form, and it would make it so much easier if I did not need to add this to the click event of each label.
I guess it would be possible to make an event for all labels that forces a tab to the next control, and assuming that I have the Tab indices set up correctly, then this would work. The problem would occur when adding new fields to the form, in which case all tab indices would need re-verified.
Private Sub Label1_Click(sender As Object, e As EventArgs) Handles Label1.Click, Label2.Click
'code to tab to next field...
End Sub
Is there any easier way?
First, set the controls' TabIndex orders on your form then use this code:
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For Each c As Control In Me.Controls
If TypeOf c Is Label Then AddHandler c.Click, AddressOf Label_Click
Next
End Sub
Private Sub Label_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Me.SelectNextControl(sender, True, True, True, True)
End Sub
End Class
Now whenever you click on a label, the following control in the order will be focused.
How about creating a dictionary where the label is the key and the control to focus is the value, then add a Click event handler to all of the label in the Dictionary. Everytime you add a label/control 'all' you need to do is add another KeyValuePair to the Dictionary
Simple Example:
Public Class Form1
Protected Friend DicLabelToControl As Dictionary(Of Label, Control)
Protected Friend Sub InitLabelDic()
DicLabelToControl = New Dictionary(Of Label, Control) From {{Label1, TextBox1}, {Label2, TextBox2}}
End Sub
Protected Friend Sub AddClickEventsToLabels()
For Each lb As Label In DicLabelToControl.Keys
AddHandler lb.Click, AddressOf HandleLabelClick
Next
End Sub
Private Sub HandleLabelClick(sender As Object, e As EventArgs)
DicLabelToControl(CType(sender, Label)).Focus()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
InitLabelDic()
AddClickEventsToLabels()
End Sub
End Class

Using handlers across multiple forms?

I have code that highlights the current textbox in focus in order to provide a visual cue to the user. My question is, if I had 10 forms with textboxes and I wanted to provide this same code to them all. Would I have to duplicate it or can I use a global method? If so, an example would be very helpful. Thanks.
The code is as follows.
Private Sub FocusChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim txt As TextBox = sender
If txt.Focused Then
txt.Tag = txt.BackColor
txt.BackColor = Color.AliceBlue
Else
txt.BackColor = txt.Tag
End If
End Sub
Private Sub CreateAccount_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For Each ctrl As TextBox In Me.Controls.OfType(Of TextBox)()
AddHandler ctrl.GotFocus, AddressOf FocusChanged
AddHandler ctrl.LostFocus, AddressOf FocusChanged
ctrl.Tag = ctrl.BackColor
Next
End Sub
If you want to add this behavior to all TextBox controls, you're better off deriving your own class from the TextBox class, and override the OnGotFocus and OnLostFocus methods to set the properties accordingly.
Here's how:
Public Class MyTextBox
Inherits TextBox
Protected Overrides Sub OnGotFocus(e As System.EventArgs)
MyBase.OnGotFocus(e)
Me.Tag = Me.BackColor
Me.BackColor = Color.Aqua
End Sub
Protected Overrides Sub OnLostFocus(e As System.EventArgs)
MyBase.OnLostFocus(e)
Me.BackColor = Me.Tag
End Sub
End Class
EDIT: forgot to mention that after adding that class to your project, rebuild the solution, and if it compiles without errors, then your new TextBox class show show up in the VS ToolBox. You can then simply drag & drop onto your form just as any control.
Cheers