[VB.net] Clicks in another program at special coordinates

06/29/2013 13:56 Unlocked.,#1
Hi,
I want to simulate clicks in another program at special coordinates, without having the program opened (multitasking).
Does somebody happen to know how?
Regards :P
07/01/2013 04:21 »jD«#2
You can use P/Invokes. All you need to do is grab the main windows handle, and invoke "SendMessage" with a mouse click and it will work.

EDIT: Found the sample code:

Code:
<DllImport("user32.dll", CharSet := CharSet.Auto, SetLastError := False)> _
Private Shared Function SendMessage(hWnd As IntPtr, Msg As Integer, wParam As Integer, lParam As Integer) As IntPtr
End Function

<StructLayout(LayoutKind.Explicit)> _
Structure LParamLocation
	<FieldOffset(0)> _
	Private Number As Integer

	<FieldOffset(0)> _
	Public X As Short

	<FieldOffset(2)> _
	Public Y As Short

	Public Shared Widening Operator CType(p As LParamLocation) As Integer
		Return p.Number
	End Operator
End Structure

Private Sub Form1_MouseClick(sender As Object, e As MouseEventArgs)
	Dim process = Process.GetProcessesByName("chrome")
	Dim points As New LParamLocation()
	points.X = CShort(PointToScreen(e.Location).X)
	points.Y = CShort(PointToScreen(e.Location).Y)

	'MouseLeft down message
	SendMessage(process(0).MainWindowHandle, &H201, 0, points)
	'MouseLeft up message
	SendMessage(process(0).MainWindowHandle, &H202, 0, points)
End Sub
-jD
07/01/2013 11:27 dready#3
If i remember right, this approach has some drawbacks, there are quite some applications that fetch their input deeper down on the driver, if they use directinput as example.

Just FYI if you have problems getting this code working ;)
07/01/2013 14:52 »jD«#4
This will actually inject it in the message queue, you will only find issues maybe if its running full screen.

-jD
07/01/2013 15:02 dready#5
Didnt DirectInput ignore the messagequeue ?
07/01/2013 16:07 MrSm!th#6
^Yep.
SendInput injects events directly at the driver layer.
07/02/2013 03:22 »jD«#7
Quote:
Originally Posted by MrSm!th View Post
^Yep.
SendInput injects events directly at the driver layer.
So DirectInput does or does not see the events? I'm pretty sure it does because I develop a bot for Diablo III that uses this method...

-jD
07/02/2013 10:44 .SkyneT.#8
Quote:
Originally Posted by »jD« View Post
So DirectInput does or does not see the events?.
Yes, DirectInput gets everything directly from the driver, and bypasses
the windows message stuff.
07/05/2013 17:09 »jD«#9
Yep. Makes sense, Just going back over our codebase and read through our input injection. We use kernel mode injection techniques to inject input directly in as if it came from the driver. There's also some really nice DirectInput hooking code in there too that we use to override some DirectInput methods in user space so we have the ability to inject input that way, however it seems this is a tad overkill to be posting code samples of as it requires a lot higher level of knowledge than the OP probably has!

Does the SendInput method work OP?

-jD
07/06/2013 22:34 Unlocked.,#10
Quote:
Originally Posted by »jD« View Post
You can use P/Invokes. All you need to do is grab the main windows handle, and invoke "SendMessage" with a mouse click and it will work.

EDIT: Found the sample code:

Code:
<DllImport("user32.dll", CharSet := CharSet.Auto, SetLastError := False)> _
Private Shared Function SendMessage(hWnd As IntPtr, Msg As Integer, wParam As Integer, lParam As Integer) As IntPtr
End Function

[COLOR="Cyan"]<StructLayout(LayoutKind.Explicit)> _
Structure LParamLocation
	<FieldOffset(0)> _
	Private Number As Integer

	<FieldOffset(0)> _
	Public X As Short

	<FieldOffset(2)> _
	Public Y As Short

	Public Shared Widening Operator CType(p As LParamLocation) As Integer
		Return p.Number
	End Operator
End Structure[/COLOR]

Private Sub Form1_MouseClick(sender As Object, e As MouseEventArgs)
	Dim process = Process.GetProcessesByName("chrome")
	Dim points As New LParamLocation()
	points.X = CShort(PointToScreen(e.Location).X)
	points.Y = CShort(PointToScreen(e.Location).Y)

	'MouseLeft down message
	SendMessage(process(0).MainWindowHandle, &H201, 0, points)
	'MouseLeft up message
	SendMessage(process(0).MainWindowHandle, &H202, 0, points)
End Sub
-jD
Hey, thanks for the info.
What is the structure thing for?
Regards
07/07/2013 03:31 »jD«#11
The parameters variable for that particular message takes a single integer for both the X and Y values. It takes what's called the upper and lower bits of the single integer to determine which coordinate to click on. If you think of an integer, it's 4 bytes correct? What the click parameter does is it takes the lower 2 bytes for the X value and the upper 2 bytes for the Y value. The LayoutKind.Explicit attribute says to windows that you want to explicitly control how that struct looks in memory. What it's doing here is it's overlapping the X and Y shorts over the same memory space as the integer. Because a short is 2 bytes, this has the same effect of setting the lower and higher bytes of an integer. To make things even simpler, I implemented an explicit cast operator to cast to the integer the SendMessage expects seamlessly! When I'm home I'll post some images to make it easier to understand.

-jD