2 votes

Déplacement de la souris dans Windows 7 - Clic gauche et Glisser

Je suis en train d'essayer de dessiner automatiquement dans un programme similaire à paint en simulant le mouvement de la souris et les clics avec user32.dll sous Windows 7.

Voici ce que j'ai et comment je l'utilise :

Configuration

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

    [Flags]
    public enum MouseEventFlags
    {
        LEFTDOWN = 0x00000002,
        LEFTUP = 0x00000004,
        MIDDLEDOWN = 0x00000020,
        MIDDLEUP = 0x00000040,
        MOVE = 0x00000001,
        ABSOLUTE = 0x00008000,
        RIGHTDOWN = 0x00000008,
        RIGHTUP = 0x00000010
    }

    public void LeftMouseDown()
    {
        mouse_event((int)(MouseEventFlags.LEFTDOWN), Cursor.Position.X, Cursor.Position.Y, 0, 0);
    }

    public void LeftMouseUp()
    {
        mouse_event((int)(MouseEventFlags.LEFTUP), Cursor.Position.X, Cursor.Position.Y, 0, 0);
    }

Lors du dessin

            foreach (var contour in contours)
            {
                LeftMouseDown();
                foreach (var point in contour)
                {
                    var x = point.X + offsetX;
                    var y = point.Y + offsetY;
                    Cursor.Position = new Point(x, y);
                    //LeftMouseDown();
                    System.Threading.Thread.Sleep(2);
                }
                LeftMouseUp();
            }

Ce que j'essaie de simuler, c'est le maintien du clic gauche de la souris, le déplacement sur un tas de points dans chaque contour puis de laisser la souris avant de passer au prochain contour.

Le problème, c'est que cela maintient simplement le bouton de la souris enfoncé pour le premier mouvement, puis le relâche.

TL;DR

Comment puis-je maintenir le clic gauche de la souris enfoncé lorsque la souris est déplacée de manière programmatique ?

Je tente de simuler le dessin dans une application tierce (Tableau blanc de Microsoft LINQ, le client IM.)

2voto

Hans Passant Points 475940

Résumant la piste de commentaire : cela n'a pas le résultat attendu car le code simule uniquement des clics de souris, pas le mouvement de la souris. Déplacer le curseur avec Cursor.Position modifie directement la position du curseur, contournant la file d'attente des événements d'entrée Windows. Ne génère donc aucune notification (messages WM_MOUSEMOVE) à la fenêtre qui a le focus.

Correction en ajoutant une méthode MouseMove() à la classe d'aide qui utilise mouse_event() avec MouseEventFlags.MOVE

1voto

Alvin Wong Points 5803

Une réponse tardive, mais je pense que l'erreur que vous avez commise est d'appeler mouse_event. Fondamentalement, mouse_event signale un mouvement de souris relatif (lorsqu'il n'y a pas de MOUSEEVENTF_ABSOLUTE) mais vous passez une position absolue, ce qui le fait agir incorrectement. De plus, vous devriez déplacer le curseur vers la position pour appuyer sur le bouton de la souris avant d'effectuer l'appui sur la souris.

Voici donc ma correction :

// J'ai un peu modifié la signature de la méthode, mais cela n'a pas vraiment d'importance
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
static extern void mouse_event(MouseEventFlags flags, uint dx, uint dy, uint delta, IntPtr extraInfo);

[Flags]
enum MouseEventFlags : uint
{
    Absolute = 0x8000,
    LeftDown = 0x0002,
    LeftUp = 0x0004,
    MiddleDown = 0x0020,
    MiddleUp = 0x0040,
    Move = 0x0001,
    RightDown = 0x0008,
    RightUp = 0x0010,
    Wheel = 0x0800,
    XDown = 0x0080,
    XUp = 0x0100,
    HWheel = 0x1000,
}

public void LeftMouseDown()
{
    // Simuler un clic gauche, remarquez que le mouvement RELATIF est à 0
    mouse_event(MouseEventFlags.LeftDown, 0, 0, 0, IntPtr.Zero);
}

public void LeftMouseUp()
{
    // Simuler un relâchement du clic gauche, remarquez que le mouvement RELATIF est également à 0
    mouse_event(MouseEventFlags.LeftUp, 0, 0, 0, IntPtr.Zero);
}

Et lors du déplacement de la souris...

foreach (var contour in contours)
{
    // simuler un appui sur la souris APRÈS avoir déplacé le curseur sur le premier point (IMPORTANT !)
    var x = contour[0].X + offsetX;
    var y = contour[0].Y + offsetY;
    Cursor.Position = new Point(x, y);
    LeftMouseDown();
    foreach (var point in contour)
    {
        x = point.X + offsetX;
        y = point.Y + offsetY;
        Cursor.Position = new Point(x, y);
        System.Threading.Thread.Sleep(2);
    }
    // le curseur est déjà à la position finale
    LeftMouseUp();
}

Et une note importante, via quelques tests simples, définir Cursor.Position génère un message WM_MOUSEMOVE.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X