I'm attempting to to add both a MouseMove and a Click (or MouseClick) to a button. The end user needs the ability to click the button to add an element, but also the ability to drag the button to a specific location to add an element as well. I have both functions working independently. However, when I add both Handlers, the MouseMove takes precedence, and doesn't allow the Click to happen (attempting to click shows the DragDropEffects.None effect).
Button:
Dim Button As New Button()
'Button Attributes
AddHandler Button.Click, AddressOf Button_Click
AddHandler Button.MouseMove, AddressOf Button_MouseMove
Handlers:
Private Sub Button_MouseMove(sender As Object, e As MouseEventArgs)
Button.DoDragDrop("Button", DragDropEffects.Move)
End Sub
Private Sub Button_Click(sender As Object, e As EventArgs)
'Add Element Function
End Sub
I've also tried it with the MouseClick handler, with the same results:
AddHandler Button.MouseClick, AddressOf Button_MouseClick
Private Sub Button_MouseClick(sender As Object, e As MouseEventArgs)
'Add Element Function
End Sub
1.) What is the reasoning behind the Click/MouseClick not able to fire when a MouseMove is implemented as well?
2.) What is the proper workaround to get both functions usable? Do I need to do MouseDown and MouseUp handlers, and track the distance that the mouse has moved to determine if I clicked or if I am dragging?
Related
I am trying to show some hidden columns in a telerik RadGridView when the Form Window is Maximized.
I am aware of Resize Event but since Resize event is fired even before the Form is loaded, I am not using it.
I found that ResizeEnd suits my need but it is not reacting to Maximize button.
Is it possible to fire it with Maximize button.
Thanks.
since Resize event is fired even before the Form is loaded
Then add the handler in FormLoad instead of the designer
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
AddHandler Control.ResizeBegin, AddressOf controlResizeBegin
End Sub
Private Sub controlResizeBegin(sender As Object, e As EventArgs)
End Sub
Is there any way to catch all keydown event from any controls like textboxes inside a groupbox using one event handler.?
I try groupbox_keydown, but it's not triggered. I try to make some research in msdn and they say groupbox cannot get focus, so the keydown event will never raised. Is there any workaround for it.?
KeyPreview already set to True.
Edit:
i have some textboxes inside a groupbox. most of them have default or predefined value. what i want is when user have filled the required data and want to skip some textboxes, he just need to press some key like ctrl+enter to excecuting a click on a button in that groupbox or calling a procedure.
This seems to work ok It iterates through the controls collection in the groupbox and adds the .KeyDown event to the example handler.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each ctl As Control In GroupBox1.Controls
AddHandler ctl.KeyDown, AddressOf GroupBox1Controls_KeyDown
Next
End Sub
Private Sub GroupBox1Controls_KeyDown(sender As Object, e As KeyEventArgs)
MessageBox.Show(DirectCast(sender, Control).Name)
End Sub
It may be that there are controls that don't have a .KeyDown event, so you might want to add an empty Try..Catch..End Try block into the code like this, but I wouldn't recommend it as it could hide other problems with the code.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each ctl As Control In GroupBox1.Controls
Try
AddHandler ctl.KeyDown, AddressOf GroupBox1Controls_KeyDown
Catch
End Try
Next
End Sub
In VB.net form, I have 20 buttons. They are named from btnLoc1 ~ btnLoc20. I do not want to code each button click event.
How to loop through each button to check which was clicked?
Do I need to implement timer tick to listen for button click event?
You can create a single event handler for all the Buttons. Select all the buttons in the designer, open the Properties window, click the Events button and then double-click the Click event. That will generate a Click event handler, just like when you double-click a Button in the designer, except this one will have multiple items in the Handles clause. You can then use the sender parameter to acces the Button that was clicked, e.g.
Private Sub Buttons_Click(sender As Object, e As EventArgs) Handles Button1.Click,
Button2.Click,
Button3.Click
Dim btn = DirectCast(sender, Button)
'Use btn here.
End Sub
The question then is, what do you want to do with that Button? If you want to do something different for each Button then you really should be creating separate event handlers. Alternatively, you might have a list of data and you want to use the item in that list that corresponds to the Button that was clicked. There are numerous ways to do that. One is to put the data in the Tag property of the Button itself and retrieve it from there. Another is to use concurrent indexes, e.g.
Dim buttons = Controls.OfType(Of Button)().ToArray()
Dim data = {"First", "Second", "Third"}
MessageBox.Show(data(buttons.IndexOf(btn)))
Obviously you need to ensure that the Button array and the data array do line up.
For being noticed if button was clicked - eventhandler is best choice.
But you can create only one eventhandler for all buttons
Private Sub Button_Click(sender As Object, e As EventArgs)
Dim button As Button = DirectCast(sender, Button)
MessageBox($"Button '{button.Name}' was clicked")
End Sub
Then in constructor
Public Sub New()
InitializeComponennts()
AddHandler Button1.Click, AddressOf Me.Button_Click
AddHandler Button2.Click, AddressOf Me.Button_Click
AddHandler Button3.Click, AddressOf Me.Button_Click
' and so on
End Sub
If you want to get information about how much each button was clicked, simply create dictionary and add click amount in one eventhandler
Private ButtonsClickAmount As New Dictionary(Of String, Integer)()
Private Sub Button_Click(sender As Object, e As EventArgs)
Dim button As Button = DirectCast(sender, Button)
If ButtonsClickAmount.ContainKey(button.Name) = True Then
ButtonsClickAmount(button.Name) += 1
Else
ButtonsClickAmount.Add(button.Name, 1)
End If
End Sub
I am making a version of the Microsoft game 'Minesweeper'. I make the buttons and labels programmatically and add two handlers for the buttons and one handler for the labels as follows.
AddHandler Newbtn.MouseDown, AddressOf Button_MouseDown
AddHandler Newbtn.MouseUp, AddressOf Button_MouseUp
AddHandler Newlbl.MouseDown, AddressOf Label_MouseDown
then I have three procedures:
Private Sub Button_MouseUp(sender As Button, e As MouseEventArgs) Handles Me.MouseUp
Private Sub Button_MouseDown(sender As Button, e As MouseEventArgs) Handles Me.MouseDown
Private Sub Label_MouseDown(sender As Label, e As MouseEventArgs) Handles Me.MouseClick
Everything works fine until I click outside of the grid of buttons on the form itself, when I get a 'invalidcastexception'. VS2015 goes into a break state. At the top it says:
"Your Application has entered a break state, but there is no code to show because all threads were executing external code(typically system or framework code)."
Additional information: Unable to cast object of type 'Mines.MineSweeperPJS' to type 'System.Windows.Forms.Button'.
Mines is the Namespace.
MineSweeperPJS is the form.
Any suggestions as to the cause of this issue would be greatly appreciated!
The problem is in this part of your event handlers
..... Handles Me.MouseUp
^^^
this means that every mouseup, or mousedown event on your form (Me) are passed to the event handler specified.
I think that you have written this event handler manually changing the parameter sender from Object to Button because if you let the Form Designer use its own template you end up with something like this
Private Sub Button_MouseUp(sender As Object, e As MouseEventArgs) Handles Newbtn.MouseUp
When the form engine calls these event handlers, in response to a Form mousedown or mouseup it passes the reference to the Form itself (Me) and not the reference to a Button. And this is the reason of the invalid cast.
You could remove the ...Handles Me.MouseUp because you have already set up the event handlers using the AddHandler and also restore the sender parameter to be As Object
I have more than 30 picture box in a windows form named
PictureBox1
PictureBox2
PictureBox3
.....so on
I am having to write the same procedure for click function for every single one of them.
I just want to be able to write a single handler that would handle the click events for all the PictureBox and call the same function.
For a rough technical example.. Sorry for the JavaScript Format
picturebox.onclick(){
var a=get_index(this); //gets address of the clicked picturebox
somefunction(a);
}
If you are using the Handles keyword, which is the default, typical way to handle events from controls, you can add multiple event names to the Handles clause, for instance:
Private Sub OnClick(sender As Object, e As EventArgs) Handles PictureBox1.Click, PictureBox2.Click, PictureBox3.Click
' Handles click events from PictureBox1, PictureBox2, and PictureBox3
End Sub
Alternatively, you can declare the event handler method without the Handles clause, and then manually attach it to the events yourself, like this:
Private Sub OnClick(sender As Object, e As EventArgs)
' ...
End Sub
' ...
AddHandler PictureBox1.Click, AddressOf OnClick
AddHandler PictureBox2.Click, AddressOf OnClick
AddHandler PictureBox3.Click, AddressOf OnClick
Or, if you have list of picture box controls, you could add the event handlers in a loop, like this:
Dim myPictureBoxes() As PictureBox = {PictureBox1, PictureBox2, PictureBox3}
For Each i As PictureBox in myPictureBoxes
AddHandler i.Click, AddressOf OnClick
Next
Or, you could access them from your form's Controls collection by name:
For i As Integer = 1 to 30
Dim c As Control = Me.Controls("PictureBox" & i.ToString())
AddHandler c.Click, AddressOf OnClick
Next
Bear in mind, however, if you do manually call AddHandler, you need to also call RemoveHandler to later detach the event handler.
It seems odd, on the surface, to have so many picture boxes like that, though. You may want to consider custom-drawing your content in a single control or look into dynamically loading the controls at run-time.