locked
How do I simulate a mouse click at a certain position without having to move/click the mouse?

    Question

  • OK, although it's not the "recommended" method, I know I can use the following to move the mouse pointer and simulate a click:

    Private Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Cursor.Position = New Point(500, 500)
        mouse_event(&H2, 0, 0, 0, 0)
        mouse_event(&H4, 0, 0, 0, 0)
    End
    Sub

    But suppose I have lots of mouse clicks to make with my app, and I want to be able to continue to use the pc for other things while the app is running. Is there a way I can simulate a mouse click at say 500,500 without actually having to move the mouse pointer and simulate a physical click?

    I wonder if SendInput might be the answer, but after much searching I am so far unable to find a clear and working example, maybe someone here can help?

    Many thanks!
    Thursday, January 07, 2010 12:04 PM

Answers

  • Thank you Esteban All for your friendly help.


    Hi Rich,

    Welcome to MSDN forums!

    Question: "How do I simulate a mouse click at a certain position without having to move-click the mouse?"

    ->

    To simulate mouse click on where you expect, you can P/Invoke the WindowFromPoint and SendMessage APIs to send BM_CLICK message.

    Prerequisites: Drag&drop Timer1 onto Form1.

    Imports System.Runtime.InteropServices

     

    Public Class Form1

     

        <DllImport("user32.dll")> _

    Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByRef lParam As IntPtr) As IntPtr

    End Function

     

        <DllImport("user32.dll")> _

    Shared Function WindowFromPoint(ByVal pnt As Point) As IntPtr

        End Function

     

        Const BM_CLICK As Integer = &HF5&

     

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

            Timer1.Enabled = True

            Timer1.Interval = 1000

        End Sub

     

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

            ' Dim pnt As Point = Me.PointToScreen(Button1.Location)

            Dim pnt As Point = New Point(10, 10) ' Specify the location where you want to click.

            Dim hWnd As IntPtr = WindowFromPoint(pnt)

            If hWnd <> IntPtr.Zero Then

                SendMessage(hWnd, BM_CLICK, 0, IntPtr.Zero)

                ' SendMessage(Me.Button1.Handle, BM_CLICK, 0, IntPtr.Zero)

            End If

     

        End Sub

    End Class

    Best regards,
    Martin Xie


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Thursday, January 14, 2010 6:13 AM

All replies

  • Hi,

    Here is a SendInput example: http://www.pinvoke.net/default.aspx/user32.SendInput
    And here is a .net usage: http://www.xtremedotnettalk.com/showthread.php?t=93471

    Code is on C#, but you can convert it here: http://www.developerfusion.com/tools/convert/csharp-to-vb/

    Hope it helps.

    Regards.
    -

    Esteban Murchio.

    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Blog
    Thursday, January 07, 2010 12:33 PM
  • The codes in those links don't seem to work and I haven't been able to make them work to do what I want.

    So to recap, if at all possible I would like some code which can simulate a mouseclick at a given location on screen without having to actually move the mouse there and simulate a physical click.

    Anybody know if it's possible?

    Many thanks if you can help!
    Saturday, January 09, 2010 8:26 PM
  • Thank you Esteban All for your friendly help.


    Hi Rich,

    Welcome to MSDN forums!

    Question: "How do I simulate a mouse click at a certain position without having to move-click the mouse?"

    ->

    To simulate mouse click on where you expect, you can P/Invoke the WindowFromPoint and SendMessage APIs to send BM_CLICK message.

    Prerequisites: Drag&drop Timer1 onto Form1.

    Imports System.Runtime.InteropServices

     

    Public Class Form1

     

        <DllImport("user32.dll")> _

    Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByRef lParam As IntPtr) As IntPtr

    End Function

     

        <DllImport("user32.dll")> _

    Shared Function WindowFromPoint(ByVal pnt As Point) As IntPtr

        End Function

     

        Const BM_CLICK As Integer = &HF5&

     

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

            Timer1.Enabled = True

            Timer1.Interval = 1000

        End Sub

     

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

            ' Dim pnt As Point = Me.PointToScreen(Button1.Location)

            Dim pnt As Point = New Point(10, 10) ' Specify the location where you want to click.

            Dim hWnd As IntPtr = WindowFromPoint(pnt)

            If hWnd <> IntPtr.Zero Then

                SendMessage(hWnd, BM_CLICK, 0, IntPtr.Zero)

                ' SendMessage(Me.Button1.Handle, BM_CLICK, 0, IntPtr.Zero)

            End If

     

        End Sub

    End Class

    Best regards,
    Martin Xie


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Thursday, January 14, 2010 6:13 AM
  • Additionally,

    Code sample: Via P/Invoke APIs, get current point coordinate (display on Form caption bar) no matter where you point Cursor to.

    Prerequisites: Create a form named Form1 and copy all code to Form1.vb.


    Imports System.Runtime.InteropServices

     

    Public Class Form1

     

        Private Structure MSLLHOOKSTRUCT

            Public pt As Point

            Public mouseData As Int32

            Public flags As Int32

            Public time As Int32

            Public extra As IntPtr

        End Structure

     

        Private _mouseHook As IntPtr

        Private Const WH_MOUSE_LL As Int32 = 14

        Private Delegate Function CallBack(ByVal nCode As Int32, ByVal wParam As IntPtr, ByRef lParam As MSLLHOOKSTRUCT) As Int32

        <MarshalAs(UnmanagedType.FunctionPtr)> Private _mouseProc As CallBack

        Private Declare Function SetWindowsHookExW Lib "user32.dll" (ByVal idHook As Int32, ByVal HookProc As CallBack, ByVal hInstance As IntPtr, ByVal wParam As Int32) As IntPtr

        Private Declare Function UnhookWindowsHookEx Lib "user32.dll" (ByVal hook As IntPtr) As Boolean

        Private Declare Function CallNextHookEx Lib "user32.dll" (ByVal idHook As Int32, ByVal nCode As Int32, ByVal wParam As IntPtr, ByRef lParam As MSLLHOOKSTRUCT) As Int32

        Private Declare Function GetCurrentThreadId Lib "kernel32.dll" () As Integer

        Private Declare Function GetModuleHandleW Lib "kernel32.dll" (ByVal fakezero As IntPtr) As IntPtr

     

        Public Function InstallHook() As Boolean

            If _mouseHook = IntPtr.Zero Then

                _mouseProc = New CallBack(AddressOf MouseHookProc)

                _mouseHook = SetWindowsHookExW(WH_MOUSE_LL, _mouseProc, GetModuleHandleW(IntPtr.Zero), 0)

            End If

            Return _mouseHook <> IntPtr.Zero

        End Function

     

        Public Sub RemoveHook()

            If _mouseHook = IntPtr.Zero Then Return

            UnhookWindowsHookEx(_mouseHook)

            _mouseHook = IntPtr.Zero

        End Sub

     

        Private Shared Function MouseHookProc(ByVal nCode As Int32, ByVal wParam As IntPtr, ByRef lParam As MSLLHOOKSTRUCT) As Int32

            Debug.Print("Message = {0}, x={1}, y={2}", wParam.ToInt32, lParam.pt.X, lParam.pt.Y)

            ' Get the current cursor coordinate

            Form1.Text = "Current Point: " & lParam.pt.X & " " & lParam.pt.Y          

            Return CallNextHookEx(WH_MOUSE_LL, nCode, wParam, lParam)

        End Function

     

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

            InstallHook()

        End Sub

     

        Private Sub Form1_FormClosed(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed

            RemoveHook()

        End Sub

     

    End Class


    Trackback: http://social.msdn.microsoft.com/forums/en-US/Vsexpressvb/thread/02e33bbf-1668-42e2-bef3-f03ad8792b23/


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Thursday, January 14, 2010 6:15 AM
  • Wow, thanks Martin, brilliant code and you also inadvertently answered another question I had been pondering!

    Sorry I didn't reply sooner, I had stopped checking the thread for responses!
    Saturday, January 23, 2010 1:27 PM
  • Hi Rich,

    Glad to hear that :)
    You're welcome.
    Thank you for your active participation in MSDN community!


    Best regards,
    Martin Xie

    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Monday, January 25, 2010 4:14 AM
  • Hello,

     

    That code worked well.

     

    But there is one problem I am facing around.

     

    When the control in on form the code works well but suppose I want to click a button on the webpage opened in webbrowser its not working.

     

    The button don't have any id or tagname so I can't click it the normal way of Webbrowser1.Document.GetElementByID method.

     

    Sunday, August 08, 2010 12:17 PM
  • Hi Love_Cats,

    "The button don't have any id or tagname so I can't click it the normal way of Webbrowser1.Document.GetElementByID method"

    -> You can use the value attribute to locate and click a Button element as below.

    <input value = "This is Button1"/>

            Dim elementList As HtmlElementCollection

            Dim curElement As HtmlElement

            elementList = WebBrowser1.Document.GetElementsByTagName("input")

            For Each curElement In elementList

                'You can use the value attribute to locate the Button

                If curElement.GetAttribute("value").Equals("This is Button1") Then

                    curElement.InvokeMember("click")

                End If

             Next


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Monday, August 16, 2010 8:54 AM
  • Hi Martin,

    Thank you for the great code.

    My question will be about the first code example you pasted on this topic.
    How can you do the same job without seeing the window or location of the point at all ?
    I can find the hWnd of the window i would like to click on, that's not a problem. and the point is an x,y
    on that background window and i know there is a button at that location. The background window is a different program
    i don't have access programatically.

    Thank you,
    Netduk

    Monday, June 13, 2011 4:06 AM