Lachlan Court Lachlan Court - 5 months ago 31
Vb.net Question

How do I detect a mouse click anywhere on a form in vb.net?

Ok so I know how to check if the user has clicked on a specific object, however I really don't care if where the user clicks, I just need to know if they've clicked (Whether on the actual form or on an object or whatever). My code is this:

Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick

If GetAsyncKeyState(1) Then
Label1.Text = "Left"
Else
Label1.Text = "Right"
End If
End Sub


When I run the code, I get an error:

PInvokeStackImbalance was detected

"A call to PInvoke function 'Mouse click!Mouse_click.Form1::GetAsyncKeyState' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature."

I'm very new to vb.net so the documentation really doesn't help me.
Any help would be awesome :)

Answer

There are several ways really to do this and it depends on what exactly you are trying to accomplish. One way would be to have a specific place that you route all click events:

Public Sub ClickHandler(sender As Object, e As MouseEventArgs) Handles Me.MouseClick, PictureBox1.MouseClick, Label1.MouseClick, Button1.MouseClick
    Label1.Text = String.Format("Clicked ""{0}"" with the {1} mouse button.", sender.name, e.Button.ToString.ToLower)
End Sub

Notice all the Events that this Sub handles? And if you want to determine what button was pushed, you might be able to do something like this:

Select Case e.Button
    Case MouseButtons.Left
        Label1.Text = "Left"
    Case MouseButtons.Right
        Label1.Text = "Right"
    Case MouseButtons.Middle
        Label1.Text = "Middle"
    Case Else
        Label1.Text = "Some other button"
End Select

Again, this is just one way and not very practical for large apps full of controls or working across any application. Something like that would be more involved and might require a system wide hook.

[EDIT]:
Along the lines of what Robin commented (excellent suggestion, by the way) is that you can alternatively add the handler in a separate line of code to avoid having to include every control up front. In fact, if you did follow this method, which I really like, you could do this with each control on the form with a loop:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    For Each c As Control In Controls
        AddHandler c.MouseClick, AddressOf ClickHandler
    Next
End Sub

Private Sub ClickHandler(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
    Label1.Text = String.Format("Clicked ""{0}"" with the {1} mouse button.", sender.name, e.Button.ToString.ToLower)

    Select Case e.Button
        Case MouseButtons.Left
            Label2.Text = "Left"
        Case MouseButtons.Right
            Label2.Text = "Right"
        Case MouseButtons.Middle
            Label2.Text = "Middle"
        Case Else
            Label2.Text = "Some other button"
    End Select
End Sub

Thanks for that, Robin! Completely escaped my mind...

Comments