Trouble with mouse click

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Morten Snedker

    #1

    Trouble with mouse click

    If I have a number of random applications open, move the mouse cursor
    to a given position and do a click, the application gets the focus.

    That is what this simple code should illustrate:

    Dim pt As Point
    Dim wnd As IntPtr

    Const WM_LBUTTONUP = &H202 '//LButton up
    Const WM_LBUTTONDOWN = &H201 '//LButton down

    pt.X = 450
    pt.Y = 200

    Windows.Forms.C ursor.Position = pt

    wnd = WindowFromPoint (pt.X, pt.Y)
    Call SendMessage(wnd , WM_LBUTTONDOWN, 0, 0&)
    Call SendMessage(wnd , WM_LBUTTONUP, 0, 0&)


    It moves the cursor, but the application beneith doesn't get focus, as
    it would had i clicked on that position manually. What am I missing
    out on?

    Regards /Snedker
  • Chris Dunaway

    #2
    Re: Trouble with mouse click

    Morten Snedker wrote:
    If I have a number of random applications open, move the mouse cursor
    to a given position and do a click, the application gets the focus.
    >
    That is what this simple code should illustrate:
    >
    Dim pt As Point
    Dim wnd As IntPtr
    >
    Const WM_LBUTTONUP = &H202 '//LButton up
    Const WM_LBUTTONDOWN = &H201 '//LButton down
    >
    pt.X = 450
    pt.Y = 200
    >
    Windows.Forms.C ursor.Position = pt
    >
    wnd = WindowFromPoint (pt.X, pt.Y)
    Call SendMessage(wnd , WM_LBUTTONDOWN, 0, 0&)
    Call SendMessage(wnd , WM_LBUTTONUP, 0, 0&)
    >
    >
    It moves the cursor, but the application beneith doesn't get focus, as
    it would had i clicked on that position manually. What am I missing
    out on?
    >
    I suggest you fire up Spy++ and then test your scenario again. When
    you click on an application, besides the mouse messages, there are
    other messages sent, such as WM_ACTIVATE.

    Comment

    • teslar91@hotmail.com

      #3
      Re: Trouble with mouse click

      If this is a continuation of our other thread - you didn't mention you
      wanted it to receive focus too, just that you wanted it clicked and
      without moving the mouse. :)

      Chris' reply is correct.

      But if the mouse pointer is in, or will be moved to, the proper
      location, this is much easier:

      Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Int32, ByVal dX
      As Int32, ByVal dy As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo
      As Int32)

      mouse_event MOUSEEVENTF_LEF TDOWN + MOUSEEVENTF_LEF TUP, 0, 0, 0, 0

      Comment

      • rvalstar@hotmail.com

        #4
        Re: Trouble with mouse click

        As Tesla... suggests indirectly, there are limited ways to simulate
        mouse events in Windows. We have both mouse_events (deprecated) and
        SendInput -- neither of which are managed code.

        I have searched the net at length and attacked this "simple" problem
        for many hours so I'm hoping my efforts will pay off for you.

        This is a VB.NET 2005 test bed solution that allows you to play with
        mouse_event, SendInput, and OnMouse... techniques. The OnMouse...
        approach has yet to yield fruits. Either other approach (comment out
        the other 2; uncomment the METHOD desired) work quite well.

        This example expects a form called frmMain, a picture box called
        picClick, three buttons: (btnClickStart, btnClick, btnScreen), and a
        multi-line text box called txtResults.

        This is an amalgam primarily based on
        http://vb-helper.com/howto_move_click_mouse.html and
        http://www.vbforums.com/showthread.php?t=398899 -- I'm trying to update
        http://www.pinvoke.net/ to share this information.

        Also, this code shows how to simulate a "union struct" in VB.NET -- I
        was pleased to figure this out.

        Rick Valstar
        Star Consulting
        r + last name + at + gmail + dot + com

        Here's the code:

        Option Explicit On

        Imports System.Runtime. InteropServices

        Public Class frmMain
        'Const METHOD As String = "mouse_even t"
        'Const METHOD As String = "OnMouse"
        Const METHOD As String = "SendInput"

        Const INPUT_MOUSE As Int32 = 0
        Const INPUT_KEYBOARD As Int32 = 1
        Const INPUT_HARDWARE As Int32 = 2

        Const MOUSEEVENTF_MOV E As Int32 = &H1 ' mouse move
        Const MOUSEEVENTF_LEF TDOWN As Int32 = &H2 ' left button down
        Const MOUSEEVENTF_LEF TUP As Int32 = &H4 ' left button up
        Const MOUSEEVENTF_RIG HTDOWN As Int32 = &H8 ' right button down
        Const MOUSEEVENTF_RIG HTUP As Int32 = &H10 ' right button up
        Const MOUSEEVENTF_MID DLEDOWN As Int32 = &H20 ' middle button down
        Const MOUSEEVENTF_MID DLEUP As Int32 = &H40 ' middle button up
        Const MOUSEEVENTF_ABS OLUTE As Int32 = &H8000 ' absolute move
        Const MOUSEEVENTF_WHE EL As Int32 = &H800 ' wheel button rolled

        Private Structure MOUSEINPUT
        Dim dx As Int32
        Dim dy As Int32
        Dim mouseData As Int32
        Dim dwFlags As Int32
        Dim time As Int32
        Dim dwExtraInfo As IntPtr
        End Structure

        Private Structure KEYBDINPUT
        Dim wVk As Int16
        Dim wScan As Int16
        Dim dwFlags As Int32
        Dim time As Int32
        Dim dwExtraInfo As IntPtr
        End Structure

        Private Structure HARDWAREINPUT
        Dim uMsg As Int32
        Dim wParamL As Int16
        Dim wParamH As Int16
        End Structure

        <StructLayout(L ayoutKind.Expli cit)_
        Private Structure INPUT
        <FieldOffset(0) Dim dwType As Int32
        ' simulate a union struct (C) or a variant record (Pascal)
        <FieldOffset(4) Dim mi As MOUSEINPUT
        <FieldOffset(4) Dim ki As KEYBDINPUT
        <FieldOffset(4) Dim hi As HARDWAREINPUT
        End Structure

        Private Declare Auto Sub mouse_event Lib "user32.dll " (ByVal
        dwFlags As Int32, ByVal dx As Int32, ByVal dy As Int32, ByVal cButtons
        As Int32, ByVal dwExtraInfo As IntPtr)

        <DllImport("use r32.dll", SetLastError:=T rue)_
        Private Shared Function SendInput(ByVal nInputs As Int32, ByRef
        pInputs As INPUT, ByVal cbSize As Int32) As Int32
        End Function

        Private Declare Auto Sub SetLastError Lib "kernel32.d ll" (ByVal
        dwErrCode As Int32)

        Sub ClickMouse(ByVa l MouseButton As Integer)
        Dim inputevents As New INPUT

        inputevents.mi. dx = 0
        inputevents.mi. dy = 0
        inputevents.mi. mouseData = 0
        inputevents.mi. dwFlags = MouseButton
        inputevents.mi. time = 0
        inputevents.dwT ype = INPUT_MOUSE

        SetLastError(0)
        Dim result As Integer = SendInput(1, inputevents,
        Marshal.SizeOf( GetType(INPUT)) )
        Dim lasterror As Integer = Marshal.GetLast Win32Error

        Debug.WriteLine ("Result: " & result)
        Debug.WriteLine ("LastError: " & lasterror & " " & New
        System.Componen tModel.Win32Exc eption(lasterro r).Message)
        End Sub

        Sub btnClickStart_C lick(ByVal sender As System.Object, ByVal e As
        System.EventArg s) Handles btnClickStart.C lick
        txtResults.Appe ndText("***** btnClickStart *****" & vbCrLf)

        'move mouse to the start button
        Dim pt As New System.Drawing. Point(20,
        Screen.PrimaryS creen.Bounds.He ight - 20)
        'Dim pt As Point = picClicker.Poin tToScreen(New
        Point(picClicke r.ClientRectang le.Width / 2,
        picClicker.Clie ntRectangle.Hei ght / 2))

        Debug.WriteLine ("pt " & pt.X & " " & pt.Y)

        System.Windows. Forms.Cursor.Po sition = pt
        Windows.Forms.A pplication.DoEv ents()

        ClickMouse(MOUS EEVENTF_LEFTDOW N) 'press left button
        ClickMouse(MOUS EEVENTF_LEFTUP) 'release left button
        End Sub

        Private Sub btnClick_Click( ByVal eventSender As System.Object,
        ByVal eventArgs As System.EventArg s) Handles btnClick.Click
        Dim cur_x As Single
        Dim cur_y As Single
        Dim dest_x As Single
        Dim dest_y As Single

        txtResults.Appe ndText("***** btnClick *****" & vbCrLf)

        ' mouse_event moves in a coordinate system where (0, 0) is in
        the upper left corner and (65535,65535) is in the lower right corner.

        ' Get the current mouse coordinates and convert them into this
        new system.
        cur_x = System.Windows. Forms.Cursor.Po sition.X * 65535 /
        System.Windows. Forms.Screen.Pr imaryScreen.Bou nds.Width
        cur_y = System.Windows. Forms.Cursor.Po sition.Y * 65535 /
        System.Windows. Forms.Screen.Pr imaryScreen.Bou nds.Height

        ' Convert the coordinates of the center of the picClicker
        PictureBox into this new system.
        Dim pt As Point = picClicker.Poin tToScreen(New
        Point(picClicke r.ClientRectang le.Width / 2,
        picClicker.Clie ntRectangle.Hei ght / 2))
        'Dim pt As New System.Drawing. Point(20,
        Screen.PrimaryS creen.Bounds.He ight - 20)

        dest_x = pt.X * 65535 /
        System.Windows. Forms.Screen.Pr imaryScreen.Bou nds.Width
        dest_y = pt.Y * 65535 /
        System.Windows. Forms.Screen.Pr imaryScreen.Bou nds.Height

        txtResults.Appe ndText("From " &
        System.Windows. Forms.Cursor.Po sition.X & " " &
        System.Windows. Forms.Cursor.Po sition.Y & " to " & pt.X & " " & pt.Y &
        vbCrLf)
        txtResults.Appe ndText("From " & cur_x & " " & cur_y & " to " &
        dest_x & " " & dest_y & vbCrLf)

        ' Move the mouse to its final destination and click it.
        Select Case METHOD
        Case "OnMouse"
        System.Windows. Forms.Cursor.Po sition = pt
        Windows.Forms.A pplication.DoEv ents()

        'Dim eMouseMove As New
        System.Windows. Forms.MouseEven tArgs(Windows.F orms.MouseButto ns.None, 0,
        pt.X, pt.Y, 0)

        'Me.OnMouseMove (eMouseMove)

        Dim eMouseButton As New
        System.Windows. Forms.MouseEven tArgs(Windows.F orms.MouseButto ns.Left, 1,
        0, 0, 0)

        Me.OnMouseDown( eMouseButton)
        Me.OnMouseUp(eM ouseButton)

        Case "mouse_even t"
        mouse_event(MOU SEEVENTF_ABSOLU TE + MOUSEEVENTF_MOV E +
        MOUSEEVENTF_LEF TDOWN + MOUSEEVENTF_LEF TUP, dest_x, dest_y, 0, 0)

        Case "SendInput"
        Dim pInputs(0 To 2) As INPUT

        With pInputs(0)
        .dwType = INPUT_MOUSE
        .mi.dx = dest_x
        .mi.dy = dest_y
        .mi.mouseData = 0
        .mi.dwFlags = MOUSEEVENTF_ABS OLUTE +
        MOUSEEVENTF_MOV E
        .mi.time = 0
        .mi.dwExtraInfo = IntPtr.Zero
        End With

        With pInputs(1)
        .dwType = INPUT_MOUSE
        .mi.dx = 0
        .mi.dy = 0
        .mi.mouseData = 0
        .mi.dwFlags = MOUSEEVENTF_LEF TDOWN
        .mi.time = 0
        .mi.dwExtraInfo = IntPtr.Zero
        End With

        With pInputs(2)
        .dwType = INPUT_MOUSE
        .mi.dx = 0
        .mi.dy = 0
        .mi.mouseData = 0
        .mi.dwFlags = MOUSEEVENTF_LEF TUP
        .mi.time = 0
        .mi.dwExtraInfo = IntPtr.Zero
        End With

        'System.Windows .Forms.Cursor.P osition = pt
        'Windows.Forms. Application.DoE vents()

        'Debug.WriteLin e("Size: " & Marshal.SizeOf( pInputs(0))
        & " " & Marshal.SizeOf( GetType(INPUT)) )

        SetLastError(0)
        Debug.WriteLine ("Result: " & SendInput(3, pInputs(0),
        Marshal.SizeOf( GetType(INPUT)) ))
        Debug.WriteLine ("LastError: " &
        Marshal.GetLast Win32Error & " " & New
        System.Componen tModel.Win32Exc eption(Marshal. GetLastWin32Err or).Message)

        'SetLastError(0 )
        'Debug.WriteLin e("Result: " & SendInput(1, pInputs(1),
        Marshal.SizeOf( GetType(INPUT)) ))
        'Debug.WriteLin e("LastError: " &
        Marshal.GetLast Win32Error & " " & New
        System.Componen tModel.Win32Exc eption(Marshal. GetLastWin32Err or).Message)

        'SetLastError(0 )
        'Debug.WriteLin e("Result: " & SendInput(1, pInputs(2),
        Marshal.SizeOf( GetType(INPUT)) ))
        'Debug.WriteLin e("LastError: " &
        Marshal.GetLast Win32Error & " " & New
        System.Componen tModel.Win32Exc eption(Marshal. GetLastWin32Err or).Message)

        Case Else
        Beep()
        End Select

        'Windows.Forms. Application.DoE vents()
        'My.Application .DoEvents()
        End Sub

        Private Sub btnScreen_Click (ByVal sender As System.Object, ByVal e
        As System.EventArg s) Handles btnScreen.Click
        Dim I As Integer
        Dim Screens() As System.Windows. Forms.Screen =
        System.Windows. Forms.Screen.Al lScreens

        txtResults.Appe ndText("***** btnScreen *****" & vbCrLf)

        For I = 0 To Screens.GetUppe rBound(0)
        txtResults.Appe ndText("Device Name: " +
        Screens(I).Devi ceName & vbCrLf)
        txtResults.Appe ndText("Bounds: " +
        Screens(I).Boun ds.ToString() & vbCrLf)
        txtResults.Appe ndText("Type: " +
        Screens(I).GetT ype().ToString( ) & vbCrLf)
        txtResults.Appe ndText("Working Area: " +
        Screens(I).Work ingArea.ToStrin g() & vbCrLf)
        txtResults.Appe ndText("Primary Screen: " +
        Screens(I).Prim ary.ToString() & vbCrLf)
        Next I
        End Sub

        Private Sub picClicker_Clic k(ByVal eventSender As System.Object,
        ByVal eventArgs As System.EventArg s) Handles picClicker.Clic k
        txtResults.Appe ndText("picClic ker_Click" & vbCrLf)
        End Sub

        Private Sub picClicker_Mous eDown(ByVal sender As System.Object,
        ByVal e As System.Windows. Forms.MouseEven tArgs) Handles
        picClicker.Mous eDown
        txtResults.Appe ndText("picClic ker_MouseDown (" & e.X & ", " &
        e.Y & ")" & vbCrLf)
        End Sub

        Private Sub picClicker_Mous eUp(ByVal sender As System.Object, ByVal
        e As System.Windows. Forms.MouseEven tArgs) Handles picClicker.Mous eUp
        txtResults.Appe ndText("picClic ker_MouseUp (" & e.X & ", " & e.Y
        & ")" & vbCrLf)
        End Sub

        Private Sub frmMain_Click(B yVal sender As Object, ByVal e As
        System.EventArg s) Handles Me.Click
        txtResults.Appe ndText("frmMain _Click" & vbCrLf)
        End Sub

        Private Sub frmMain_MouseDo wn(ByVal sender As Object, ByVal e As
        System.Windows. Forms.MouseEven tArgs) Handles Me.MouseDown
        txtResults.Appe ndText("frmMain _MouseDown (" & e.X & ", " & e.Y
        & ")" & vbCrLf)
        End Sub

        Private Sub frmMain_MouseUp (ByVal sender As Object, ByVal e As
        System.Windows. Forms.MouseEven tArgs) Handles Me.MouseUp
        txtResults.Appe ndText("frmMain _MouseUp (" & e.X & ", " & e.Y &
        ")" & vbCrLf)
        End Sub
        End Class

        Comment

        Working...