¿Cómo simula el clic del mouse en C #?

128

¿Cómo simula los clics del mouse en aplicaciones C # winforms?

Novato
fuente
55
Es posible que desee proporcionar más información para que pueda obtener una respuesta útil.
Andy
36
Consejo: Si su título es el mismo que su pregunta, entonces el título es demasiado largo o la pregunta es demasiado corta. En este caso es el último, debe dar mucho más contexto para que cualquiera tenga una oportunidad razonable de darle una respuesta útil.
Guffa

Respuestas:

145

He combinado varias fuentes para producir el siguiente código, que actualmente estoy usando. También he eliminado las referencias de Windows.Forms para poder usarlo desde la consola y las aplicaciones WPF sin referencias adicionales.

using System;
using System.Runtime.InteropServices;

public class MouseOperations
{
    [Flags]
    public enum MouseEventFlags
    {
        LeftDown = 0x00000002,
        LeftUp = 0x00000004,
        MiddleDown = 0x00000020,
        MiddleUp = 0x00000040,
        Move = 0x00000001,
        Absolute = 0x00008000,
        RightDown = 0x00000008,
        RightUp = 0x00000010
    }

    [DllImport("user32.dll", EntryPoint = "SetCursorPos")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool SetCursorPos(int x, int y);      

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool GetCursorPos(out MousePoint lpMousePoint);

    [DllImport("user32.dll")]
    private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);

    public static void SetCursorPosition(int x, int y) 
    {
        SetCursorPos(x, y);
    }

    public static void SetCursorPosition(MousePoint point)
    {
        SetCursorPos(point.X, point.Y);
    }

    public static MousePoint GetCursorPosition()
    {
        MousePoint currentMousePoint;
        var gotPoint = GetCursorPos(out currentMousePoint);
        if (!gotPoint) { currentMousePoint = new MousePoint(0, 0); }
        return currentMousePoint;
    }

    public static void MouseEvent(MouseEventFlags value)
    {
        MousePoint position = GetCursorPosition();

        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;
        }
    }
}
Keith
fuente
2
No puedo ver ninguna ventaja de este largo código fuente sobre lo que publicó Marcos Placona hace 17 meses.
Al Kepp
46
Dada la vaguedad de la pregunta, pensé que las personas podrían beneficiarse de un ejemplo que les permite hacer más que solo un clic izquierdo, succionar un clic derecho o medio o permitir hacer clic y arrastrar.
Keith
2
Funciona genial. Vine aquí buscando algo como esto
CSharpie
Esto es lo que estoy buscando, pero ¿cómo haces clic, mueves el mouse a otro lugar y luego sueltas?
ninjaxelite
1
@ninjaxelite Supongo que enviarás 1. SetCursorPos, 2. MouseEvent(LeftButtonDown), 3. SetCursorPos, 4. MouseEvent(LeftButtonUp). Potencialmente envolverlo en un método auxiliar
Michal Ciechan
137

Un ejemplo que encontré en algún lugar aquí en el pasado. Podría ser de alguna ayuda:

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);
   //Mouse actions
   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
      uint X = (uint)Cursor.Position.X;
      uint Y = (uint)Cursor.Position.Y;
      mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
   }

   //...other code needed for the application
}
Marcos Placona
fuente
12
¿En algún lugar estar aquí quizás?
mpen
3
Bien jugado. Se agregó referencia a la respuesta original
Marcos Placona,
2
Recibo un error con este código: una llamada a la función PInvoke 'MyForm! MyForm.Form1 :: mouse_event' ha desequilibrado la pila. Esto es probable porque la firma PInvoke administrada no coincide con la firma de destino no administrada. Verifique que la convención de llamada y los parámetros de la firma PInvoke coincidan con la firma no administrada de destino. ¿Algunas ideas?
Abdulla
12
Necesitas lanzar la X e Y a las uniones.
Dibesjr
1
Funciona perfectamente necesita algunos cambios en la posición del cursor según los requisitos ...
Anurag Rabadia
14

Algunos controles, como Button en System.Windows.Forms, tienen un método "PerformClick" para hacer precisamente eso.

Denis
fuente
Si el control no tiene un método PerformClick, puede extender / agregar uno, solo necesita llamar a OnMouseClick con un argumento adecuado de MouseEventArgs.
Tony Hopkinson el
8
Mouse.Click();

Microsoft.VisualStudio.TestTools.UITesting

clavo oxidado
fuente
1
Es un poco extraño que esto esté aislado en el espacio de nombres de prueba de Visual Studio UI, pero lo tomaré sobre PInvoke cualquier día que no necesite filtrar eventos por dispositivo.
kayleeFrye_onDeck
2
Parece que la edición Visual Studio Community no se incluye con esta DLL.
CM
2
Acabo de pasar una hora tratando de hacer que esto funcione copiando archivos DLL de un proyecto de "prueba de IU codificada" a otro y, a menos que esté usando un tipo de proyecto de "prueba de IU codificada", mi consejo es: no se moleste. Incluso cuando copié todas las DLL necesarias, arrojó un InvalidUITestExtensionPackageException, por lo que parece ser extremadamente exigente con la ejecución de un tipo de proyecto en particular, lamentablemente.
Jez
@Jez - Práctico para saber, gracias. Todavía no he visto ningún problema, pero ahora al menos sé que existen algunos; 0)
Rusty Nail el
5

He probado el código que Marcos publicó y no me funcionó. Independientemente de lo que se me dio a la coordenada Y, el cursor no se movió en el eje Y. El código a continuación funcionará si desea la posición del cursor en relación con la esquina izquierda de su escritorio, no en relación con su aplicación.

    [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_MOVE = 0x0001;

    public void DoMouseClick()
    {
        X = Cursor.Position.X;
        Y = Cursor.Position.Y;

        //move to coordinates
        pt = (Point)pc.ConvertFromString(X + "," + Y);
        Cursor.Position = pt;       

        //perform click            
        mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
        mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
    }

Solo uso la función mouse_event para realizar el clic. Puede dar a X e Y qué coordenadas desea, utilicé valores del cuadro de texto:

            X = Convert.ToInt32(tbX.Text);
            Y = Convert.ToInt32(tbY.Text);
AlinaM
fuente
este es el adecuado para mí, básicamente Cursor.Positiones lo suficientemente bueno para colocar el cursor del mouse donde quieras, luego usa WIN32API para hacer el clic real.
Ge Rong
0

son algunas necesidades que no puedo ver en domo, como lo hicieron Keith o Marcos Placona en lugar de simplemente hacer

using System;
using System.Windows.Forms;

namespace WFsimulateMouseClick
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            button1_Click(button1, new MouseEventArgs(System.Windows.Forms.MouseButtons.Left, 1, 1, 1, 1));

            //by the way
            //button1.PerformClick();
            // and
            //button1_Click(button1, new EventArgs());
            // are the same
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("clicked");
        }
    }
}
WiiMaxx
fuente
1
También puede hacer button1_Click (null, null) si no necesita ninguno de esos parámetros.
sab669
@ sab669 seguro, pero aún depende de sus necesidades :-)
WiiMaxx
no debe usar nullen el segundo parámetro, arrojará un NullReferenceException, en su lugar useEventArgs.Empty
Etor Madiv
1
@EtorMadiv como dije antes, depende de lo que intentes hacer ... porque si lo usas como lo hice antes, no obtendrás unNullReferenceException
WiiMaxx