Full mouse control emulation using wpf: click, drag, enter, exit - c#

I'm working on a project where I need to use a joystick (DirectInput) to control the mouse pointer inside a wpf application. I need to be able to press/release a mouse button as well as possibly drag across the screen. Preferably this should actually control the mouse, allowing the joystick to be used to control other applications as well. I've got everything figured out on the DirectInput side, but I'm having trouble with the mouse-drag interaction.
This is how I'm doing left-button down:
[DllImport("user32.dll", SetLastError = true)]
static extern uint SendInput(uint nInputs, ref Input pInputs, int cbSize);
...
var aInput = new Input {
type = 0x0,
mouse = new MouseInput {
dwFlags = 0x6,
dwExtraInfo = 0,
mouseData = 0,
time = 0
}
};
SendInput(1, ref aInput, 28);
where Input and MouseInput are as follows:
[StructLayout(LayoutKind.Explicit)]
public struct Input {
[FieldOffset(0)]
public int type; // 4
[FieldOffset(4)]
public MouseInput mouse; // 24
}
[StructLayout(LayoutKind.Explicit)]
public struct MouseInput {
[FieldOffset(0)]
public int dx; // 4
[FieldOffset(4)]
public int dy; // 4
[FieldOffset(8)]
public int mouseData; // 4
[FieldOffset(12)]
public int dwFlags; // 4
[FieldOffset(16)]
public int time; // 4
[FieldOffset(20)]
public int dwExtraInfo; // 4
};
This method works for left/right mouse button down, and System.Windows.Forms.Cursor.Position works well for mouse movement, but I'm not sure how to get a mouse drag rigged up. Any pointers?

See related articles here on SO:
Injecting Mouse Input in WPF Applications
Simulate Mouse/Keyboard Input In WPF
Move the mouse in wpf
EDIT: concerning the specific "drag" need, here is another link (from the NUnitForms project here: http://nunitforms.sourceforge.net/) about a MouseController utility code that contains mouse simulation methods:
http://nunitforms.svn.sourceforge.net/viewvc/nunitforms/trunk/nunitforms/source/NUnitForms/MouseController.cs?view=markup
It has a Drag method. You could test if this works. I know, it's especially designed for WPF, but it's worth a try. Plus, if it's only about mouse mouvement, I don't see a problem if you need to reference Winforms assembly.

Benjamin, I used your code for generating mouse click. I played with the contents and found that setting "dwFlags = 0x3" did the mouse left button click and hold :)

Related

Low-Level Mouse Hook - WM_MOUSEWHEEL event data

I've implemented low level mouse hook as described in https://learn.microsoft.com/en-us/archive/blogs/toub/low-level-mouse-hook-in-c
It works fine. The only question is for WM_MOUSEWHEEL event - how to detect wheel rotation direction (forward or backward).
The system provides additional data in mouseData field only. In my tests mouseData = 7864320 for forward rotation and mouseData=4287102976 for backward rotation always.
So question: how to parse mouseData to detect the wheel rotation direction and possibly additional data related to the event?
mouseData comes from lParam
The hook provides lParam which is parsed as:
public struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}

C# Moving/Clicking Mouse Winforms

i want to make an application that will automatically move the mouse and click it with just a press of a button in the background.. I'm from Sales and Inventory / HTML Shop website programming and this is my first time making an application that involves control. please help me because i want to push my programming skills.
This is what i'm trying to do and my Idea.
*i will put an loop counter for the repetition of the moves
1.get the x/y of current cursor and save it to variable named (coordinate) (Point A)
2.Right click it and move lower right (Point B)
3.wait 2 seconds
4.Move back to the first position by using variable (coordinate)
5.End loop repeat.
that's my idea and my algorithm my problem is i don't have any idea how to move a mouse and make it stop.
In Window Form projects to move a cursor to a specific point on your screen, you can use this static method.
System.Windows.Forms.Cursor.Position = new Point (X,Y);
and to perform a click event you can use this method.
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
public void DoMouseClick()
{
//Call the imported function with the cursor's current position
uint X = (uint)System.Windows.Forms.Cursor.Position.X;
uint Y = (uint)System.Windows.Forms.Cursor.Position.Y;
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
}
You can move mouse writing some function or code like this:
private void MoveCursor()
{
// Set the Current cursor, move the cursor's Position,
// and set its clipping rectangle to the form.
this.Cursor = new Cursor(Cursor.Current.Handle);
Cursor.Position = new Point(Cursor.Position.X - 50, Cursor.Position.Y - 50);
Cursor.Clip = new Rectangle(this.Location, this.Size);
}
How To Move mouse in C#
And to find location of any control on your Form you can use the following code
Point locationOnForm = control.FindForm().PointToClient(
control.Parent.PointToScreen(control.Location));
How to get controls location in Win Forms

C# Simulate mouse movement does not affect foreground application

I have two machines: A and B
On A, I get the current (local) mouse position (x & y) and send send that mouse position over my local network to machine B.
Machine B takes the incoming position X and Y and simulate the mouse movement using the example found here. It all works fine and dandy - I can see the mouse moving, but for some reason, it does not affect the Window in the foreground on machine B.
What is this "Window"? It is a Unity3D application - a game. I expect that the mouse movement would cause the in-game camera to move around. Interestingly, if I do as described and then stop moving the mouse on machine A... and then move the mouse via the touchpad (or regular mouse) on machine B, it moves the in-game camera, as expected!
What is going on?
It seems that, for whatever reason, the code taken from here
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
does not work...properly! My mouse would move, as expected, on the remote machine but the application that I was bringing to the foreground was not detecting the mouse movements.
However, I did manage to get this to work using mouse_event:
[Flags]
public enum MouseEventFlags
{
LeftDown = 0x00000002,
LeftUp = 0x00000004,
MiddleDown = 0x00000020,
MiddleUp = 0x00000040,
Move = 0x00000001,
Absolute = 0x00008000,
RightDown = 0x00000008,
RightUp = 0x00000010
}
[DllImport("user32.dll")]
private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
public static void MouseEvent(MouseEventFlags value, Point position)
{
MousePoint position = position;
mouse_event
((int)value,
position.X,
position.Y,
0,
0)
;
}
[StructLayout(LayoutKind.Sequential)]
public struct MousePoint
{
public int X;
public int Y;
public MousePoint(int x, int y)
{
X = x;
Y = y;
}
}
To use it, just call:
mouse_event(MouseEventFlags.Move,new MousePoint{X = YOUR_X, Y = YOUR_Y});
All credit goes to this SO answer.

TabTip click &123 key programmatically

I have a C# winForms application that makes use of the Windows 8 keyboard.
I open the keyboard by launching tabtip.exe.
I am able to close the keyboard using a PostMessage command like this:
public static void HideOnScreenKeyboard()
{
uint WM_SYSCOMMAND = 274;
uint SC_CLOSE = 61536;
IntPtr KeyboardWnd = FindWindow("IPTip_Main_Window", null);
PostMessage(KeyboardWnd.ToInt32(), WM_SYSCOMMAND, (int)SC_CLOSE, 0);
}
I think using PostMessage it should be possible to simulate almost anything programmatically if you just pass the correct values.
The values used for closing the keyboard (274 and 61536) I just found on the internet.
It looks that it is possible to grab these values using Spy++, or some other tools but I am unable how to do this.
Can anybody tell me the values needed to simulate a press on the &123 key, so the keyboard switches to the numeric keyboard?
Or, does anybody know how to get these values?
I have tried Spy++, but so many messages are passing constantly that I don't know where to look.
Look at the image of the OnScreenKeyboard to see what key I mean
You could try to use SendInput to simulate a mouse click event on the &123 button of the virtual keyboard window.
Below is an example of how to use SendInput to send a mouse click (left_down + left_up) to the button but I haven't included the code to programatically find the window and get the window size.
[StructLayout(LayoutKind.Sequential)]
public struct MINPUT
{
internal uint type;
internal short dx;
internal short dy;
internal ushort mouseData;
internal ushort dwFlags;
internal ushort time;
internal IntPtr dwExtraInfo;
internal static int Size
{
get { return Marshal.SizeOf(typeof(INPUT)); }
}
}
const ushort MOUSEEVENTF_ABSOLUTE = 0x8000;
const ushort MOUSEEVENTF_LEFTDOWN = 0x0002;
const ushort MOUSEEVENTF_LEFTUP = 0x0004;
// programatically determine the position and size of the TabTip window
// compute the location of the center of the &123 key
int coordinateX = ...
int coordinateY = ...
var pInputs = new[] {
new MINPUT() {
type = 0×01; //INPUT_KEYBOARD
dx = coordinateX,
dy = coordinateY;
dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN;
time = 0;
dwExtraInfo = IntPtr.Zero;
},
new MINPUT() {
type = 0×01; //INPUT_KEYBOARD
dx = coordinateX,
dy = coordinateY;
dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP;
time = 0;
dwExtraInfo = IntPtr.Zero;
}
};
SendInput((uint)pInputs.Length, pInputs, MINPUT.Size);
Why don't you set the input scope of the edit control to numeric? New built-in edit controls with the correct properties automatically trigger the numeric mode when touched.
Rather than hacking the Touch Input Panel which appears differently in different locales, etc. set InputScope of the text box to Number and let Windows do the magic.

Virtual mouse click c#

I have an multithreaded application that needs to be able to preform multiple mouse click at the same time.
I have an IntPtr intptr to a process on which i need to send a mouse click to.
I have tried to find this information on the web and there are some examples which i have tried. But I have not got any of them to work.
As I understand the correct way to solv my issue is to use the function
SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
hWnd is the IntPtr to the process.
Msg is the wanted action, which I want a left click, int WM_LBUTTONDBLCLK = 0x0203;
IntPtr wParam is of no intrest to this problem ( as I understand)
And the coordinates to the click is in lParam.
I construct lParam like,
Int32 word = MakeLParam(x, y);
private int MakeLParam(int LoWord, int HiWord)
{
return ((HiWord << 16) | (LoWord & 0xffff));
}
But as you might understand, I cant get this to work.
My first question is, the coordinates are they within the window of this process or are
the absolut screen coordinates?
And my second question, what am I doing wrong?
I was trying to simulate mouse clicks in C# just recently, I wrote this little helper class to do the trick:
public static class SimInput
{
[DllImport("user32.dll")]
static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, UIntPtr dwExtraInfo);
[Flags]
public enum MouseEventFlags : uint
{
Move = 0x0001,
LeftDown = 0x0002,
LeftUp = 0x0004,
RightDown = 0x0008,
RightUp = 0x0010,
MiddleDown = 0x0020,
MiddleUp = 0x0040,
Absolute = 0x8000
}
public static void MouseEvent(MouseEventFlags e, uint x, uint y)
{
mouse_event((uint)e, x, y, 0, UIntPtr.Zero);
}
public static void LeftClick(Point p)
{
LeftClick((double)p.X, (double)p.Y);
}
public static void LeftClick(double x, double y)
{
var scr = Screen.PrimaryScreen.Bounds;
MouseEvent(MouseEventFlags.LeftDown | MouseEventFlags.LeftUp | MouseEventFlags.Move | MouseEventFlags.Absolute,
(uint)Math.Round(x / scr.Width * 65535),
(uint)Math.Round(y / scr.Height * 65535));
}
public static void LeftClick(int x, int y)
{
LeftClick((double)x, (double)y);
}
}
The coordinates are a fraction of 65535, which is a bit odd, but this class will handle that for you.
I'm not 100% sure I understand what you're trying to accomplish. But if you want to simulate mouse input then I'd recommend using the SendInput API.
You can provide an array of inputs to be inserted into the input stream.
See also: PInvoke reference
I don't understand why anyone would want to send multiple mouse clicks simultaneously. If it's to test your GUI, it's the wrong test. No one can physically click something multiple times in the same time space.
But going back to your question, using SendMessage won't help you, because it is basically a blocking call. Even if you tried to use PostMessage, you won't be able to accomplish simultaneous clicks, because the message queue is getting pumped from the UI thread and has messages popped off and handled sequentially.
I used this code to click left button in handle
public static void MouseLeftClick(Point p, int handle = 0)
{
//build coordinates
int coordinates = p.X | (p.Y << 16);
//send left button down
SendMessage(handle, 0x201, 0x1, coordinates);
//send left button up
SendMessage(handle, 0x202, 0x1, coordinates);
}
If you set no handle with calling - then it sends click to Desktop, so coordinates should be for whole screen, if you will set handle, then message will be sent to handle's window and you should set coordinates for window.
How about just using VirtualMouse? I use it in C# and it works great.
public partial class Form1 : Form
{
private VirtualMouse vm = new VirtualMouse();
public Form1()
{
InitializeComponent();
}
private void MouseClickHere(Point myPoint)
{
vm.ClickIt(myPoint, 150);
}
private void Clicker()
{
MouseClickHere(new Point(250,350));
}
}

Categories