Comment simuler un clic de souris en C #?

128

Comment simuler les clics de souris dans les applications winforms C #?

Débutant
la source
5
Vous voudrez peut-être fournir plus d'informations afin d'obtenir une réponse utile.
Andy
36
Conseil: si votre titre correspond à votre question, cela signifie que le titre est beaucoup trop long ou la question est beaucoup trop courte. Dans ce cas, c'est le dernier, vous devez donner beaucoup plus de contexte pour que quiconque ait une chance raisonnable de vous donner une réponse utile.
Guffa

Réponses:

145

J'ai combiné plusieurs sources pour produire le code ci-dessous, que j'utilise actuellement. J'ai également supprimé les références Windows.Forms afin de pouvoir l'utiliser à partir des applications console et WPF sans références supplémentaires.

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
la source
2
Je ne vois aucun avantage de ce long code source par rapport à ce que Marcos Placona a publié il y a 17 mois.
Al Kepp
46
Étant donné le caractère vague de la question, je pensais que les gens pourraient bénéficier d'un exemple qui leur permettrait de faire plus qu'un simple clic gauche, sucer un clic droit ou central ou autoriser le clic et le glisser.
Keith
2
Fonctionne très bien. Je suis venu ici à la recherche de quelque chose comme ça
CSharpie
C'est ce que je recherche, mais comment cliquer vers le bas, déplacer la souris ailleurs, puis relâcher ??
ninjaxelite
1
@ninjaxelite Je suppose que vous envoyez 1. SetCursorPos, 2. MouseEvent(LeftButtonDown), 3. SetCursorPos, 4. MouseEvent(LeftButtonUp). Potentiellement envelopper dans une méthode d'aide
Michal Ciechan
137

Un exemple que j'ai trouvé quelque part ici dans le passé. Cela pourrait vous aider:

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
la source
12
Quelque part étant ici peut-être?
mpen
3
Bien joué. Référence ajoutée à la réponse originale
Marcos Placona
2
J'obtiens une erreur avec ce code: Un appel à la fonction PInvoke 'MyForm! MyForm.Form1 :: mouse_event' a déséquilibré la pile. Cela est probablement dû au fait que la signature PInvoke gérée ne correspond pas à la signature cible non gérée. Vérifiez que la convention d'appel et les paramètres de la signature PInvoke correspondent à la signature non gérée cible. Des idées?
Abdulla
12
Vous devez convertir le X et le Y en uints.
Dibesjr
1
Fonctionne parfaitement nécessite quelques changements dans la position du curseur selon les exigences ...
Anurag Rabadia
14

Certains contrôles, comme Button dans System.Windows.Forms, ont une méthode "PerformClick" pour faire exactement cela.

Denis
la source
Si le contrôle n'a pas de méthode PerformClick, vous pouvez en étendre / en ajouter une, il suffit d'appeler OnMouseClick avec un argument MouseEventArgs approprié.
Tony Hopkinson
8
Mouse.Click();

Microsoft.VisualStudio.TestTools.UITesting

clou rouillé
la source
1
C'est un peu étrange que cela ait été isolé dans l'espace de noms de test de l'interface utilisateur de Visual Studio, mais je prendrai cela sur PInvoke chaque jour que je n'ai pas besoin de filtrer les événements par appareil.
kayleeFrye_onDeck
2
Il semble que l'édition communautaire de Visual Studio ne soit pas livrée avec cette DLL.
CM
2
Je viens de passer une heure à essayer de faire en sorte que cela fonctionne en copiant les DLL d'un projet de «test d'interface utilisateur codée» vers un autre et à moins que vous n'utilisiez un type de projet «test d'interface utilisateur codé», mon conseil est: ne vous inquiétez pas. Même lorsque j'ai copié toutes les DLL nécessaires, cela a lancé un InvalidUITestExtensionPackageException, il semble donc extrêmement difficile de s'exécuter dans un type de projet particulier, malheureusement.
Jez
@Jez - Pratique à savoir, merci. Je n'ai encore vu aucun problème moi-même, mais maintenant j'en connais au moins certains; 0)
Rusty Nail
5

J'ai essayé le code que Marcos a publié et cela n'a pas fonctionné pour moi. Peu importe ce que j'ai reçu de la coordonnée Y, le curseur ne s'est pas déplacé sur l'axe Y. Le code ci-dessous fonctionnera si vous voulez la position du curseur par rapport au coin gauche en haut de votre bureau, et non par rapport à votre application.

    [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);
    }

J'utilise uniquement la fonction mouse_event pour effectuer réellement le clic. Vous pouvez donner à X et Y les coordonnées que vous voulez, j'ai utilisé les valeurs de la zone de texte:

            X = Convert.ToInt32(tbX.Text);
            Y = Convert.ToInt32(tbY.Text);
AlinaM
la source
c'est le bon pour moi, en gros, Cursor.Positionc'est assez bon pour positionner le curseur de la souris où vous voulez, puis utilisez WIN32API pour faire le clic réel.
Ge Rong
0

ce sont des besoins que je ne peux pas voir pour dôme comme Keith ou Marcos Placona l'ont fait au lieu de simplement faire

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
la source
1
Vous pouvez également faire button1_Click (null, null) si vous n'avez besoin d'aucun de ces paramètres.
sab669
@ sab669 bien sûr mais cela dépend toujours de ses besoins :-)
WiiMaxx
vous ne devriez pas utiliser nulldans le deuxième paramètre, il lancera un NullReferenceException, utilisez plutôtEventArgs.Empty
Etor Madiv
1
@EtorMadiv comme je l'ai dit avant cela dépend de ce que vous essayez de faire ..., parce que si vous l'utilisez comme je l'ai fait ci-dessus, vous n'obtiendrez pas unNullReferenceException
WiiMaxx