I'm developing an app that have to send some keys or mouse events to the active window.
I'm using this class:
Mouse
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Mouse
{
public static class VirtualMouse
{
// import the necessary API function so .NET can
// marshall parameters appropriately
[DllImport("user32.dll")]
static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
// constants for the mouse_input() API function
private const int MOUSEEVENTF_MOVE = 0x0001;
private const int MOUSEEVENTF_LEFTDOWN = 0x0002;
private const int MOUSEEVENTF_LEFTUP = 0x0004;
private const int MOUSEEVENTF_RIGHTDOWN = 0x0008;
private const int MOUSEEVENTF_RIGHTUP = 0x0010;
private const int MOUSEEVENTF_MIDDLEDOWN = 0x0020;
private const int MOUSEEVENTF_MIDDLEUP = 0x0040;
private const int MOUSEEVENTF_ABSOLUTE = 0x8000;
// simulates movement of the mouse. parameters specify changes
// in relative position. positive values indicate movement
// right or down
public static void Move(int xDelta, int yDelta)
{
mouse_event(MOUSEEVENTF_MOVE, xDelta, yDelta, 0, 0);
}
// simulates movement of the mouse. parameters specify an
// absolute location, with the top left corner being the
// origin
public static void MoveTo(int x, int y)
{
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, x, y, 0, 0);
}
// simulates a click-and-release action of the left mouse
// button at its current position
public static void LeftClick()
{
mouse_event(MOUSEEVENTF_LEFTDOWN, Control.MousePosition.X, Control.MousePosition.Y, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, Control.MousePosition.X, Control.MousePosition.Y, 0, 0);
}
public static void RightClick()
{
mouse_event(MOUSEEVENTF_RIGHTDOWN, Control.MousePosition.X, Control.MousePosition.Y, 0, 0);
mouse_event(MOUSEEVENTF_RIGHTUP, Control.MousePosition.X, Control.MousePosition.Y, 0, 0);
}
}
}
Keyboard
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Mouse
{
public static class VirtualKeyboard
{
[DllImport("user32.dll")] static extern uint keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
public static void KeyDown(System.Windows.Forms.Keys key)
{
keybd_event((byte)key, 0, 0, 0);
}
public static void KeyUp(System.Windows.Forms.Keys key)
{
keybd_event((byte)key, 0, 0x7F, 0);
}
}
}
this is my testing code:
private void button1_Click(object sender, EventArgs e)
{
Thread.Sleep(2000);
VirtualMouse.Move(100, 100);
VirtualMouse.RightClick();
VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.A);
VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.A);
}
Mouse moves, but doesn't send click. Any idea?
How can I make a key continue pressed for some time? I tried using thread.sleep between KeyDown and KeyUp and it's not working.
There is an open source project on CodePlex (Microsoft's open source website)
Windows Input Simulator (C# SendInput Wrapper - Simulate Keyboard and Mouse)
http://inputsimulator.codeplex.com/
It has examples and real simple to use.
Your definitions should be Uint32:
private const UInt32 MOUSEEVENTF_LEFTDOWN = 0x02;
private const UInt32 MOUSEEVENTF_ABSOLUTE = 0x8000;
private const UInt32 MOUSEEVENTF_LEFTUP = 0x04;
private const UInt32 MOUSEEVENTF_RIGHTDOWN = 0x08;
private const UInt32 MOUSEEVENTF_RIGHTUP = 0x10;
Related
I'd like to click in a game's button. I've tried with several ways, SendInput, and MouseEvent are some of them. Nevertheless I always got the same result, it doesn't work.
This is the original button.
And this is the button once I click on it with SendInput or MouseEvent
The color changes, but it doesn't work at all. (I also tried with leftClick, double LeftClick, and leftClickUp/Down.) My guess is that it is just supposed to work if the click isn't virtual? I'm not sure at all, since I don't have much idea about it.
Any idea?
Little update: As I've mentioned I have tried with SendInput, MouseEvent, InputSimulator and so on, the problem is always the same, while it works out of that game, it doesn't with that button. I'm pretty sure it could be because the game detect it's a virtual click simulation.
Since some fellas asked for code. (I'll repeat, this doesn't look a problem in the code tho...)
This one is for InputSimulator.
InputSimulator sim = new InputSimulator();
sim.Mouse.LeftButtonDoubleClick();
This one is using MouseEvent
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
private const int MOUSEEVENT_LEFTDOWN = 0x02;
private const int MOUSEEVENT_LEFTUP = 0x04;
private const int MOUSEEVENT_MIDDLEDOWN = 0x20;
private const int MOUSEEVENT_MIDDLEUP = 0x40;
private const int MOUSEEVENT_RIGHTDOWN = 0x08;
private const int MOUSEEVENT_RIGHTUP = 0x10;
static void Click(){
mouse_event(MOUSEEVENT_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENT_LEFTUP, 0, 0, 0, 0);
}
private void timer1_Tick(object sender, EventArgs e) {
Click();
}
This one is using SendInput. (MouseSimulator is a static class using SendInput.)
MouseSimulator.ClickLeftMouseButton();
This is the class for the MouseSimulator.
using System;
using System.Runtime.InteropServices;
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 ClickLeftMouseButton()
{
INPUT mouseDownInput = new INPUT();
mouseDownInput.type = SendInputEventType.InputMouse;
mouseDownInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTDOWN;
SendInput(1, ref mouseDownInput, Marshal.SizeOf(new INPUT()));
INPUT mouseUpInput = new INPUT();
mouseUpInput.type = SendInputEventType.InputMouse;
mouseUpInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTUP;
SendInput(1, ref mouseUpInput, Marshal.SizeOf(new INPUT()));
}
public static void ClickRightMouseButton()
{
INPUT mouseDownInput = new INPUT();
mouseDownInput.type = SendInputEventType.InputMouse;
mouseDownInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_RIGHTDOWN;
SendInput(1, ref mouseDownInput, Marshal.SizeOf(new INPUT()));
INPUT mouseUpInput = new INPUT();
mouseUpInput.type = SendInputEventType.InputMouse;
mouseUpInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_RIGHTUP;
SendInput(1, ref mouseUpInput, Marshal.SizeOf(new INPUT()));
}
}
All of them work well out of the game, inside they just work as I described above.
Since this is happening with all buttons in the game, this is a gif showing what's happening versus what's is expecting.
This is the expected behavior.
https://gyazo.com/ffd6af281414c5b0b10e19cf7a27823d
Nevertheless this is what's happening. (You can see that the color change and it looks like if it was pressed but it clearly doesn't)
https://gyazo.com/20ebb3bc360a4a5bccbe3ea5207d201b
Your question has a really low quality. The design of the button is´t relevant, your code would be. But I´ll take a guess anyway.
Well. It looks like the click got registered. Could it be that your script presses the mousebutton and never releases it? Many UI´s wont trigger at the pressing but on the release of the button. I don´t know much about C# but in Powershell you need to tell the script to PRESS and to RELEASE the button seperatly.
I am making an AI and want it to function as a player. I use some code to make the mouse click and this works. Then I made some code to make the mouse click on random places but then it stopped working.
I changed
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
to
private const int MOUSEEVENTF_LEFTDOWN = 0x0002;
private const int MOUSEEVENTF_LEFTUP = 0x0004;
but it did not seem to change anything except the location it pressed on.
I also made it wait 0,5 sec between mouseDown and mouseUp but it still did not work when I ran rndPlay();, when I tried to do just press1(); it did work.
public static void MoveTo(int x, int y)
{
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, x, y, 0, 0);
}
public static void LeftClick()
{
mouse_event(MOUSEEVENTF_LEFTDOWN, System.Windows.Forms.Control.MousePosition.X, System.Windows.Forms.Control.MousePosition.Y, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, System.Windows.Forms.Control.MousePosition.X, System.Windows.Forms.Control.MousePosition.Y, 0, 0);
}
public static void LeftMouseClick(int x, int y)
{
MoveTo(x, y);
LeftClick();
}
public static void press1()
{
LeftMouseClick(28000, 25000);
last2Moves("1");
}
public static void press2()
{
LeftMouseClick(33000, 25000);
last2Moves("2");
}
//etc
public static void rndPlay()
{
for (int r = 0; moveSucces != true && r < 10000; r++)
{
Random rndP = new Random();
int rndPress = rndP.Next(1, 10);
if (rndPress == 1)
{
press1();
}
if (rndPress == 2)
{
press2();
}
//etc
}
}
When I run rndPlay(); I see the mouse move but it does not seem to click. Is there another way to make the mouse click in a location that would work better/faster?
Apart from using very large values for X and Y your code seems ok.
I whipped up a small example using a textbox to show when and where the mouse was clicked, connected to a simple Forms timer to simulate clicks.
public partial class Form1 : Form
{
[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);
private const int MouseLeftDown = 0x02;
private const int MouseLeftUp = 0x04;
private readonly Timer _timer = new Timer();
public Form1()
{
InitializeComponent();
_timer.Interval = 1000;
_timer.Tick += (s, a) => mouse_event(MouseLeftDown | MouseLeftUp, (uint)MousePosition.X, (uint)MousePosition.Y, 0, 0);
_timer.Enabled = true;
_textBox.Click += (s, a) => _textBox.AppendText($"Clicked at {PointToClient(MousePosition)}\n");
}
}
I am trying to open an application through C# using Process.Start() and then simulate a mouse click on the application.
When I run the application, the mouse click occurs in the left top corner, which is not what I want.
public partial class Form1 : Form
{
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, int dx, int dy,
int dwData, int dwExtraInfo);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
private const int MOUSEEVENTF_ABSOLUTE = 0x8000;
private const int MOUSEEVENTF_LEFTDOWN = 0x0002;
private const int MOUSEEVENTF_LEFTUP = 0x0004;
private const int MOUSEEVENTF_MIDDLEDOWN = 0x0020;
private const int MOUSEEVENTF_MIDDLEUP = 0x0040;
private const int MOUSEEVENTF_MOVE = 0x0001;
private const int MOUSEEVENTF_RIGHTDOWN = 0x0008;
private const int MOUSEEVENTF_RIGHTUP = 0x0010;
private const int MOUSEEVENTF_WHEEL = 0x0800;
private const int MOUSEEVENTF_XDOWN = 0x0080;
private const int MOUSEEVENTF_XUP = 0x0100;
private void button1_Click(object sender, EventArgs e)
{
new Thread(() =>
{
AddTextToListBox1(label1);
}).Start();
new Thread(() =>
{
// AddTextToListBox2(label2);
}).Start();
}
private void AddTextToListBox1(Label label)
{
if (label1.InvokeRequired)
{
stringDelegate sd = new stringDelegate(AddTextToListBox1);
this.Invoke(sd, new object[] { label1 });
}
else
{
label1.Text = this.ToString()+"Hi";
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "C://xyz//xyz.exe";
p.Start();
IntPtr hwnd = p.MainWindowHandle;
}
}
private void AddTextToListBox2(Label label)
{
if (label1.InvokeRequired)
{
stringDelegate sd = new stringDelegate(AddTextToListBox2);
this.Invoke(sd, new object[] { label1 });
}
else
{
label2.Text = "done";
Thread.Sleep(6000);
int X = 579;
int Y = 637;
mouse_event(MOUSEEVENTF_ABSOLUTE| MOUSEEVENTF_MOVE, X, Y, 0, 0);
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
}
}
I think mouse_event will only raise event in current app because it doesn't take hwnd on params. My experience in this area is really low, but I've done some research. Look at SendMessage function.
MSDN article:
Sends the specified message to a window or windows.
The SendMessage function calls the window procedure for the specified window
and does not return until the window procedure has processed the message.
You can send many messages with it, including mouse events
If I wanted to control the mouse cursor, including clicking etc, what API would I need to use for this? For example, i'm developing an application for the PC using the Kinect, and I wish to control the mouse cursor with this, as opposed to creating my own in-app cursor. What would I need to 'tap into' to achieve this?
Thanks.
See answer from Marcos Placona in: How to simulate Mouse Click in C#?
Now you only need to add the mouse move events. More info here: http://pinvoke.net/default.aspx/user32.mouse_event
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
public class Form1 : Form
{
[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);
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 Form1()
{
}
public void DoMouseClick()
{
//Call the imported function with the cursor's current position
int X = Cursor.Position.X;
int Y = Cursor.Position.Y;
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
}
//...other code needed for the application
}
I need to control other application by simulating mouse movement and keyboard input. How do I accomplish this in C#? Is it even possible?
Have you looked at White TestStack?
Sample code:
Application application = Application.Launch("foo.exe");
Window window = application.GetWindow("bar", InitializeOption.NoCache);
Button button = window.Get<Button>("save");
button.Click();
I don't think it can get better than that. The library is created by ThoughtWorks.
See "To send a keystroke to a different application" on this page:
http://msdn.microsoft.com/en-us/library/ms171548.aspx
You can use p/invoke, I stole the following code for mouse clicks in random spots on a button with a known handle:
[Flags]
public enum MouseEventFlags
{
LEFTDOWN = 0x00000002,
LEFTUP = 0x00000004,
MIDDLEDOWN = 0x00000020,
MIDDLEUP = 0x00000040,
MOVE = 0x00000001,
ABSOLUTE = 0x00008000,
RIGHTDOWN = 0x00000008,
RIGHTUP = 0x00000010
}
[StructLayout(LayoutKind.Sequential)]
public struct Rectangle
{
public int X;
public int Y;
public int Width;
public int Height;
}
private static void Click(IntPtr Handle)
{
lock (typeof(MouseAction))
{
Rectangle buttonDesign;
GetWindowRect(Handle, out buttonDesign);
Random r = new Random();
int curX = 10 + buttonDesign.X + r.Next(100 - 20);
int curY = 10 + buttonDesign.Y + r.Next(60 - 20);
SetCursorPos(curX, curY);
//Mouse Right Down and Mouse Right Up
mouse_event((uint)MouseEventFlags.LEFTDOWN, curX, curY, 0, 0);
mouse_event((uint)MouseEventFlags.LEFTUP, curX, curY, 0, 0);
}
}
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
[DllImport("user32.dll")]
private static extern void mouse_event(
long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
[DllImport("user32.dll")]
static extern bool GetWindowRect(IntPtr hWnd, out Rectangle rect);
you can use AutoIT, it's freeware, and it has a dll version that you can import into C# (DllImport). It allows you to click on controls, write strings to edit boxes, make combobox selections etc on another application from C#.
Use the SendMessage Native Win32 API. DllImport this method from the User32.dll. You can use this API to send both keyboard & mouse messages
I tried to do the same: to use the mouse i used this class
(you need to add using System.Runtime.InteropServices;)
public class MouseClick1 //public is important here**
{
[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);
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 int CoordX { get; set; }
public int CoordY { get; set; }
public void Click1()
{
Cursor.Position = new Point(CoordX, CoordY);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
}
}
and after on your form1 (presuming the name is form1) you can
public partial class form1 : Form
{
MouseClick1 button1 = new MouseClick1();
MouseClick1 button2 = new MouseClick1();
[...]
public void Simulate_button1and2_Click(object sender, EventArgs e)
{
button1.CoordX = 1652; //random coordinates
button1.CoordY = 225;
button2.CoordX = 1650;
button2.CoordY = 250;
button1.Click1();
button1.Click2();
}
}
To have the coordinates on your pointer, I use a timer and a label:
private void timer1_Tick(object sender, EventArgs e)
{
Coord.Text = Cursor.Position.X.ToString() + " : " + Cursor.Position.Y.ToString(); //Premet d'avoir les coord en direct
}
Work fine with me.