How do I press and move the mouse in C#? - c#

I need to send mouse signals in C# so that other applications register them. To be exact, I need to simulate mouse buttons and the move of the mouse. Is there a way to do this in C#? (Windows)

The mouse's cursor position is a settable property - you can use it to move the mouse wherever you want.

You need to call the SendInput API function.
See here for P/Invoke defnitions.

As far as the buttonpresses go, you can do the following
[DllImport("user32.dll")]
public static extern uint SendInput(uint nInputs, ref Input pInputs, int cbSize);
const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
const uint MOUSEEVENTF_LEFTUP = 0x0004;
const uint MOUSEEVENTF_RIGHTDOWN = 0x0008;
const uint MOUSEEVENTF_RIGHTUP = 0x0010;
public static void DoMouseClick()
{
var input =
new Input
{
type = 0,
mouseinput =
new Mouseinput
{
dx = Cursor.Position.X,
dy = Cursor.Position.Y,
dwFlags = MOUSEEVENTF_LEFTDOWN
}
};
SendInput(1, ref input, 28);
}
[StructLayout(LayoutKind.Explicit, Size = 28)]
public struct Input
{
[FieldOffset(0)]
public uint type;
[FieldOffset(4)]
public Mouseinput mouseinput;
};
[StructLayout(LayoutKind.Explicit, Size = 28)]
public struct Mouseinput
{
[FieldOffset(0)]
public int dx;
[FieldOffset(4)]
public int dy;
[FieldOffset(8)]
public uint mouseData;
[FieldOffset(12)]
public uint dwFlags;
[FieldOffset(16)]
public uint time;
[FieldOffset(20)]
public uint dwExtraInfo;
}

Related

Restore suppressed cursor after touch injection

I'm writing a helper for injecting touch in UI-tests using InjectTouchInput.
The injected touch works fine but injecting mouse input after touch does not work.
Mouse.Click(point); // works
Touch.Tap(point); // works
Mouse.Click(point); // does not work, mouse cursor no longer visible on screen.
Calling GetCursorInfo() reveals that cursor is CURSOR_SUPPRESSED and I have not found a way to restore it.
Moving the physical mouse brings back the cursor and clicking things work fine.
How can I restore things so that mouse works again here?
Use the API SendInput to Simulated mouse input.
PInvoke to SendInput – this is the official way to simulate input. It
pushes the input through all of the expected code paths, and is
indistinguishable from real input.
Here is the code sample:
public class MouseSimulator
{
[DllImport("user32.dll", SetLastError = true)]
static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize);
[StructLayout(LayoutKind.Sequential)]
struct INPUT
{
public SendInputEventType type;
public MouseKeybdhardwareInputUnion mkhi;
}
[StructLayout(LayoutKind.Explicit)]
struct MouseKeybdhardwareInputUnion
{
[FieldOffset(0)]
public MouseInputData mi;
[FieldOffset(0)]
public KEYBDINPUT ki;
[FieldOffset(0)]
public HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public int uMsg;
public short wParamL;
public short wParamH;
}
struct MouseInputData
{
public int dx;
public int dy;
public uint mouseData;
public MouseEventFlags dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[Flags]
enum MouseEventFlags : uint
{
MOUSEEVENTF_MOVE = 0x0001,
MOUSEEVENTF_LEFTDOWN = 0x0002,
MOUSEEVENTF_LEFTUP = 0x0004,
MOUSEEVENTF_RIGHTDOWN = 0x0008,
MOUSEEVENTF_RIGHTUP = 0x0010,
MOUSEEVENTF_MIDDLEDOWN = 0x0020,
MOUSEEVENTF_MIDDLEUP = 0x0040,
MOUSEEVENTF_XDOWN = 0x0080,
MOUSEEVENTF_XUP = 0x0100,
MOUSEEVENTF_WHEEL = 0x0800,
MOUSEEVENTF_VIRTUALDESK = 0x4000,
MOUSEEVENTF_ABSOLUTE = 0x8000
}
enum SendInputEventType : int
{
InputMouse,
InputKeyboard,
InputHardware
}
public static void MoveMouseButton(int x, int y)
{
INPUT mouseMoveInput = new INPUT();
mouseMoveInput.type = SendInputEventType.InputMouse;
mouseMoveInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_MOVE| MouseEventFlags.MOUSEEVENTF_ABSOLUTE;
mouseMoveInput.mkhi.mi.dx = x;
mouseMoveInput.mkhi.mi.dy = y;
SendInput(1, ref mouseMoveInput, Marshal.SizeOf(new INPUT()));
}
}

C# SendInput() always returns 0 in Console Application

I have developed a simple Console application to poll an Xbox Controller using xinput. I would like to use the values obtained from one of the thumbsticks to move the mouse. I am able to get the x and y values from the thumbstick, but when I use those values to SendInput() (using the User32.dll), the mouse does not move and the return value is 0.
According to Microsoft, "If the function returns zero, the input was already blocked by another thread."
How do I find the other thread that is blocking it? It is just a simple Console Application (exe) started by Visual Studio that prints the x and y values to the screen and attempts to move the mouse.
long x = controller.x; // values from the controller
long y = controller.y; // these are checked and do contain numbers
INPUT mouseMoveInput = new INPUT();
mouseMoveInput.type = 0; // mouse
mouseMoveInput.mi.dx = x;
mouseMoveInput.mi.dy = y;
mouseMoveInput.mi.mouseData = 0;
mouseMoveInput.mi.dwFlags = MOUSEEVENTF_MOVE;
var result = SendInput(1, ref mouseMoveInput, Marshal.SizeOf(new INPUT());
// result always returns 0
Am I missing something? Should this work?
Here are declarations:
[StructLayout(LayoutKind.Explicit)]
public struct MOUSEINPUT
{
[FieldOffset(0)]
public long X;
[FieldOffset(8)]
public long Y;
[FieldOffset(16)]
public uint MouseData;
[FieldOffset(20)]
public uint Flags;
[FieldOffset(24)]
public uint Time;
[FieldOffset(28)]
public IntPtr ExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
internal struct KEYBOARDINPUT
{
public ushort Vk;
public ushort Scan;
public uint Flags;
public uint Time;
public IntPtr ExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
internal struct HARDWAREINPUT
{
public uint Msg;
public ushort ParamL;
public ushort ParamH;
}
[StructLayout(LayoutKind.Explicit)]
public struct INPUT
{
[FieldOffset(0)]
public uint type;
[FieldOffset(4)]
public MOUSEINPUT mi;
[FieldOffset(4)]
public KEYBOARDINPUT ki;
[FieldOffset(4)]
public HARDWAREINPUT hi;
}
UPDATE: using mouse-event does work, but this function is deprecated. Is there a problem with using it anyway since it works?
There is something odd I'm getting with the struct sizes:
Size of tagINPUT: 40
Size of mouseMoveInput: 40
Size of MOUSEINPUT: 32
Size of uint: 4
But if tagINPUT consists of MOUSEINPUT and uint then shouldn't it's size be 36?
The 2nd parameter of SendInput should be a pointer to an array, not a ref parameter, and especially not a ref directly to the struct.
I would also use explicit layout only for the struct that actually needs it, and let the rest be sequential. It's easier.
This code works for me:
const int INPUT_MOUSE = 0;
const int MOUSEEVENTF_MOVE = 0x0001;
[DllImport("user32.dll", SetLastError = true)]
private static extern uint SendInput(uint numberOfInputs, [MarshalAs(UnmanagedType.LPArray)] INPUT[] inputs, int sizeOfInputStructure);
void Main()
{
INPUT mouseMoveInput = new INPUT();
mouseMoveInput.type = INPUT_MOUSE;
mouseMoveInput.mi.dx = 10;
mouseMoveInput.mi.dy = 10;
mouseMoveInput.mi.mouseData = 0;
mouseMoveInput.mi.dwFlags = MOUSEEVENTF_MOVE;
var result = SendInput(1, new INPUT[] { mouseMoveInput}, Marshal.SizeOf(mouseMoveInput));
if(result == 0) {
throw new Win32Exception();
}
}
[StructLayout(LayoutKind.Sequential)]
public struct MOUSEINPUT
{
public int dx;
public int dy;
public uint mouseData;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct HARDWAREINPUT
{
public uint Msg;
public ushort ParamL;
public ushort ParamH;
}
[StructLayout(LayoutKind.Explicit)]
public struct INPUT
{
[FieldOffset(0)]
public uint type;
[FieldOffset(4)]
public MOUSEINPUT mi;
[FieldOffset(4)]
public KEYBDINPUT ki;
[FieldOffset(4)]
public HARDWAREINPUT hi;
}

mouse_event not firing on a specific application (C#)

I am trying to programatically simulate a left button mouse click:
[DllImport("user32.dll")]
static extern bool SetCursorPos(int x, int y);
[DllImport("user32.dll")]
public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
public const int MOUSEEVENTF_LEFTDOWN = 0x02;
public const int MOUSEEVENTF_LEFTUP = 0x04;
public static void LeftMouseClick(int xpos, int ypos)
{
SetCursorPos(xpos, ypos);
mouse_event(MOUSEEVENTF_LEFTDOWN, xpos, ypos, 0, 0);
System.Threading.Thread.Sleep(1000);
mouse_event(MOUSEEVENTF_LEFTUP, xpos, ypos, 0, 0);
}
The cursor moves to the appropriate position on the screen, but the click is not firing there. Any thoughts?
EDIT: I did a couple of tests. The method i use does not seem to be the issue (it clicks on applications like steam, skype successfully). When calling the click method when the cursor is above the application that i specifically want to click on (an android emulator) nothing happens. The mouse cursor moves to the spot but wont click... Going to test another emulator now.
I wrote a helper class for another project I was working on which wrapped up the mouse event:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
class MouseHelper
{
internal struct INPUT
{
public UInt32 Type;
public MOUSEKEYBDHARDWAREINPUT Data;
}
[StructLayout(LayoutKind.Explicit)]
internal struct MOUSEKEYBDHARDWAREINPUT
{
[FieldOffset(0)]
public MOUSEINPUT Mouse;
}
internal struct MOUSEINPUT
{
public Int32 X;
public Int32 Y;
public UInt32 MouseData;
public UInt32 Flags;
public UInt32 Time;
public IntPtr ExtraInfo;
}
/// <summary>
/// Synthesizes keystrokes, mouse motions, and button clicks.
/// </summary>
[DllImport("user32.dll")]
internal static extern uint SendInput(uint nInputs, [MarshalAs(UnmanagedType.LPArray), In] INPUT[] pInputs, int cbSize);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
private const int MOUSEEVENTF_RIGHTUP = 0x10;
public static void DoMouseClick()
{
var inputMouseDown = new INPUT();
inputMouseDown.Type = 0; /// input type mouse
inputMouseDown.Data.Mouse.Flags = 0x0002; /// left button down
var inputMouseUp = new INPUT();
inputMouseUp.Type = 0; /// input type mouse
inputMouseUp.Data.Mouse.Flags = 0x0004; /// left button up
var inputs = new INPUT[] { inputMouseDown, inputMouseUp };
SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
}
public static void DoMouseClick2()
{
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
}
}
All I needed to do was call MouseHelper.DoMouseClick() whenever I wanted a mouse click. I suspect the mouse move functionality could be added as an enhancement.

Why does pressing the key once act like it is repeatedly pressed?

I'm using a Winform to give Buttons in a DirectX Game. Therefore I'm using this class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace DirectInput
{
public class cDirectInput
{
[DllImport("user32.dll")]
static extern UInt32 SendInput(UInt32 nInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] INPUT[] pInputs, Int32 cbSize);
[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
public int dx;
public int dy;
public int mouseData;
public int dwFlags;
public int time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
public short wVk;
public short wScan;
public int dwFlags;
public int time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public int uMsg;
public short wParamL;
public short wParamH;
}
[StructLayout(LayoutKind.Explicit)]
struct INPUT
{
[FieldOffset(0)]
public int type;
[FieldOffset(4)]
public MOUSEINPUT mi;
[FieldOffset(4)]
public KEYBDINPUT ki;
[FieldOffset(4)]
public HARDWAREINPUT hi;
}
const int KEYEVENTF_EXTENDEDKEY = 0x0001;
const int KEYEVENTF_KEYUP = 0x0002;
const int KEYEVENTF_UNICODE = 0x0004;
const int KEYEVENTF_SCANCODE = 0x0008;
public void Send_Key(short Keycode, int KeyUporDown)
{
INPUT[] InputData = new INPUT[1];
InputData[0].type = 1;
InputData[0].ki.wScan = Keycode;
InputData[0].ki.dwFlags = KeyUporDown;
InputData[0].ki.time = 0;
InputData[0].ki.dwExtraInfo = IntPtr.Zero;
SendInput(1, InputData, Marshal.SizeOf(typeof(INPUT)));
}
}
}
Then I'm sending Buttons with this:
DirectInput.cDirectInput d = new DirectInput.cDirectInput();
d.Send_Key(0x11, 0x0008);
But when I send it it is permanent. When I send w the player is moving forward forever. I can stop that by pressing w on the keyboard. Why isn't it stopping? When I send it to an editor it stops when I stop sending, ingame it doesn't stop. What is the problem?
Thank you in advance!
You're sending a key down message, but not sending a key up message following it. From the documentation:
KEYBDINPUT.dwFlags:
KEYEVENTF_KEYUP (0x0002)
If specified, the key is being released. If not specified, the key is being pressed.
To move forward for 1 second, try:
d.Send_Key(0x11, 0x0008);
Thread.Sleep(1000);
d.Send_Key(0x11, 0x000A);
Note that the reason pressing w fixes the problem is it sends a keydown event (which would be ignored) and then a keyup event, finally releasing the key.

SendInput fails on 64bit [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
SendInput and 64bits
I'm using SendInput from .NET code (PInvoke). code used to work fine on 32bit OS, but now on WIN7 SendInput returns 0, and last error is set to 57 (ERROR_INVALID_PARAMETER).I cannot compile my code as x86 as I am loaded into a 64bit host. Also, I tried various solutions regarding structure sizes and field offsets, none worked.
These are my PInvoke imports and types:
[StructLayout(LayoutKind.Sequential)]
struct KEYBOARD_INPUT
{
public uint type;
public ushort vk;
public ushort scanCode;
public uint flags;
public uint time;
public uint extrainfo;
public uint padding1;
public uint padding2;
}
[DllImport("User32.dll", SetLastError=true)]
private static extern uint SendInput(
uint numberOfInputs,
[MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] KEYBOARD_INPUT[] input,
int structSize);
and code usage is:
uint result = SendInput(
(uint)inputs.Count,
inputs.ToArray(),
Marshal.SizeOf(inputs[0]));
where inputs array contains 1 KEYBOARD_INPUT struct.
this yields in result = 0, and when I check last error I get that last error is set to 57 (ERROR_INVALID_PARAMETER, The parameter is incorrect).
Is there a way to make this work under 64bit host in WIN7 64bit OS? this works in XP...
thanks
Try using the following definitions (courtesy of pinvoke.net):
const int INPUT_MOUSE = 0;
const int INPUT_KEYBOARD = 1;
const int INPUT_HARDWARE = 2;
const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
const uint KEYEVENTF_KEYUP = 0x0002;
const uint KEYEVENTF_UNICODE = 0x0004;
const uint KEYEVENTF_SCANCODE = 0x0008;
struct INPUT
{
public int type;
public InputUnion u;
}
[StructLayout(LayoutKind.Explicit)]
struct InputUnion
{
[FieldOffset(0)]
public MOUSEINPUT mi;
[FieldOffset(0)]
public KEYBDINPUT ki;
[FieldOffset(0)]
public HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
public int dx;
public int dy;
public uint mouseData;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
/*Virtual Key code. Must be from 1-254. If the dwFlags member specifies KEYEVENTF_UNICODE, wVk must be 0.*/
public ushort wVk;
/*A hardware scan code for the key. If dwFlags specifies KEYEVENTF_UNICODE, wScan specifies a Unicode character which is to be sent to the foreground application.*/
public ushort wScan;
/*Specifies various aspects of a keystroke. See the KEYEVENTF_ constants for more information.*/
public uint dwFlags;
/*The time stamp for the event, in milliseconds. If this parameter is zero, the system will provide its own time stamp.*/
public uint time;
/*An additional value associated with the keystroke. Use the GetMessageExtraInfo function to obtain this information.*/
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public uint uMsg;
public ushort wParamL;
public ushort wParamH;
}
[DllImport("user32.dll")]
static extern IntPtr GetMessageExtraInfo();
[DllImport("user32.dll", SetLastError = true)]
static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
Then, in your client code, use:
INPUT[] inputs = new INPUT[]
{
new INPUT
{
type = INPUT_KEYBOARD,
u = new InputUnion
{
ki = new KEYBDINPUT
{
wVk = key,
wScan = 0,
dwFlags = 0,
dwExtraInfo = GetMessageExtraInfo(),
}
}
}
};
SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));

Categories

Resources