Sending a click to exact coordinates in an inactive program
So I'm trying to send a click of exact coordinates to an inactive program. I've used this code send clicks before and it's worked fine but the coordinates don't seem to be correct because when I enter them in the textboxes for the ovalshape the messagebox won't popup. So my question is, how can I grab the coordinates that work with the click and set them to label1.text?
Here's the form:
http://i.imgur.com/YgSJZac.png
And here's the complete code:
Code:
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function PostMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
End Function
<DllImport("user32.dll")> _
Shared Function WindowFromPoint(ByVal pnt As Point) As IntPtr
End Function
Private point As New Point
Private lButtonUp As UInteger = &H202
Private lButtonDown As UInteger = &H201
Private Function returnlParam(ByVal Lo As Short, ByVal Hi As Short) As IntPtr
Return CInt(Hi) << 16 Or Lo
End Function
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Label1.Text = (Cursor.Position.X - Me.Location.X) & ", " & (Cursor.Position.Y - Me.Location.Y)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
point = New Point(textbox1.text, textbox2.text)
Timer2.Enabled = True
End Sub
Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
Dim hWnd As IntPtr
Dim wParam As IntPtr
Dim lParam As IntPtr
hWnd = WindowFromPoint(point)
wParam = CUInt(Keys.LButton)
lParam = returnlParam(point.X, point.Y)
PostMessage(hWnd, lButtonDown, wParam, lParam)
PostMessage(hWnd, lButtonUp, wParam, lParam)
MsgBox("clicked")
Timer2.Enabled = False
End Sub
Private Sub OvalShape1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OvalShape1.Click
MsgBox("clicked me!")
End Sub
End Class
This is the code I'm using to get the coordinates currently:
Code:
Label1.Text = (Cursor.Position.X - Me.Location.X) & ", " & (Cursor.Position.Y - Me.Location.Y)
Re: Sending a click to exact coordinates in an inactive program
if you want to get the point using the forms events
in form_clickevent or any click event for that matter
use the event arguments, the location of the click is there
Code:
Private Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
Dim message As String
message = DirectCast(e, System.Windows.Forms.MouseEventArgs).X & "," & DirectCast(e, System.Windows.Forms.MouseEventArgs).Y
MessageBox.Show(message)
End Sub
Re: Sending a click to exact coordinates in an inactive program
Quote:
Originally Posted by
GBeats
if you want to get the point using the forms events
in form_clickevent or any click event for that matter
use the event arguments, the location of the click is there
Code:
Private Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
Dim message As String
message = DirectCast(e, System.Windows.Forms.MouseEventArgs).X & "," & DirectCast(e, System.Windows.Forms.MouseEventArgs).Y
MessageBox.Show(message)
End Sub
That still does not work. Using that code I found a point on top of the ovalshape is 110,110. However when I enter this and hit the buttons, nothing happens.
Re: Sending a click to exact coordinates in an inactive program
Quote:
So I'm trying to send a click of exact coordinates to an inactive program.
Why? There must be more to this than you''re telling us because frankly the whole exercise appears to be completely pointless. If you tell us what you're ultimately trying to achieve we might be able to make useful suggestions.
Your main problem is that you make no distinction between screen co-ordinates, the active client co-ordinates, and the inactive client co-ordinates, and more importantly which of the commands uses which of them. An inactive form is particularly tricky in that respect.
Re: Sending a click to exact coordinates in an inactive program
Quote:
Originally Posted by
dunfiddlin
Why? There must be more to this than you''re telling us because frankly the whole exercise appears to be completely pointless. If you tell us what you're ultimately trying to achieve we might be able to make useful suggestions.
Your main problem is that you make no distinction between screen co-ordinates, the active client co-ordinates, and the inactive client co-ordinates, and more importantly which of the commands uses which of them. An inactive form is particularly tricky in that respect.
It appears pointless because it is pointless and is a challenge given to me by my professor. Alright I think I understand what you're saying. So the active coordinates are different from the inactive coordinates. But why? If I find the coords while the form is active then click on something else (without moving the form) shouldn't the coords be the same?
Re: Sending a click to exact coordinates in an inactive program
When the form is inactive you cannot seek a point on the form, you must seek a point on the screen. Now there are two problems. If the form has become covered then even an accurate click won't work. And you cannot convert the form co-ordinates to a screen point using PointToScreen because the form's co-ordinate system is not accessible. So you have to record the screen position while the form is active, ensure that the form is not moved or covered, then pray that the cursor isn't being moved when the timing tick occurs because it will immediately override your cursor positioning and that the form is woken in time to process the events responding to the click.
For all those reasons you simply wouldn't do this in real life. If you wanted to access an inactive form programatically you would always activate it first so that you can be sure of where it's at. And you would only do a move cursor and click simulation as a last resort in any case.
One thing I did notice, is that you are using the top left corner as your cursor target which is always a bad idea as it only takes an error of 1 pixel in 3/4 of all possible directions to miss the control altogether. You should always aim for a point inside the control, preferably at its centre.
Re: Sending a click to exact coordinates in an inactive program
Quote:
Originally Posted by
dunfiddlin
When the form is inactive you cannot seek a point on the form, you must seek a point on the screen. Now there are two problems. If the form has become covered then even an accurate click won't work. And you cannot convert the form co-ordinates to a screen point using PointToScreen because the form's co-ordinate system is not accessible. So you have to record the screen position while the form is active, ensure that the form is not moved or covered, then pray that the cursor isn't being moved when the timing tick occurs because it will immediately override your cursor positioning and that the form is woken in time to process the events responding to the click.
For all those reasons you simply wouldn't do this in real life. If you wanted to access an inactive form programatically you would always activate it first so that you can be sure of where it's at. And you would only do a move cursor and click simulation as a last resort in any case.
One thing I did notice, is that you are using the top left corner as your cursor target which is always a bad idea as it only takes an error of 1 pixel in 3/4 of all possible directions to miss the control altogether. You should always aim for a point inside the control, preferably at its centre.
Thanks for the explanation. I think my professor just assigned me this because I'm ahead of my class and he was looking to stump me. Anyways I found a solution to my issue.
me.cursor.position returns the correct points to use with the postmessage function. However upon using it (me.cursor.position.tostring) I got a warning that reads:
Code:
Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
My app still runs fine and displays the coordinates so I'm looking into what this means. Thanks again for responding.
And I know I didn't ask for this (and neither did my professor), but to click the control without a coordinate you can just use the control's handle in the hWnd parameter.