web-dev-qa-db-fra.com

clic de souris par programmation dans une autre fenêtre

Est-il possible de cliquer par programme sur un emplacement dans une autre fenêtre sans déplacer la souris à cet emplacement et même si la fenêtre n'est pas sur le dessus? Je souhaite envoyer une sorte de message dans une autre fenêtre pour simuler un clic de souris sur un emplacement.

J'ai essayé d'accomplir cela avec PostMessage:

PostMessage(WindowHandle, 0x201, IntPtr.Zero, CreateLParam(300,300));
PostMessage(WindowHandle, 0x202, IntPtr.Zero, CreateLParam(300,300));

J'ai créé la fonction CreateLParam de cette façon:

private static IntPtr CreateLParam(int LoWord, int HiWord)
{
     return (IntPtr)((HiWord << 16) | (LoWord & 0xffff));
}

Le problème est que la fenêtre se verrouille sur son emplacement. Je pense que mon application clique sur la coordonnée (1,1). Certains peuvent-ils m'aider à résoudre ce problème?

Edit: C'est PostMessage:

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
public static extern bool PostMessage(IntPtr WindowHandle, int Msg, IntPtr wParam, IntPtr lParam);

Et 0x201 et 0x202 sont respectivement WM_LBUTTONDOWN et WM_LBUTTONUP.

22
Dagob

Vous ne pouvez pas le faire en envoyant des messages, utilisez plutôt l'API Windows SendInput.

Méthode d'appel ClickOnPoint, il s'agit d'un exemple d'événement de clic de formulaire, donc this.handle est le descripteur de formulaire, notez que ce sont les coordonnées du client sur la fenêtre lorsque le descripteur est envoyé, vous pouvez facilement le modifier et envoyer les coordonnées de l'écran, et dans ce cas, vous n'avez pas besoin du descripteur ou de l'appel ClientToScreen ci-dessous.

ClickOnPoint(this.Handle, new Point(375, 340));

MISE À JOUR: en utilisant SendInput maintenant, tnx Tom.

btw. J'ai utilisé uniquement les déclarations nécessaires pour cet exemple, pour quoi que ce soit de plus, il y a une belle bibliothèque: Windows Input Simulator (C # SendInput Wrapper - Simulate Keyboard and Mouse)

  public class ClickOnPointTool
  {

    [DllImport("user32.dll")]
    static extern bool ClientToScreen(IntPtr hWnd, ref Point lpPoint);

    [DllImport("user32.dll")]
    internal static extern uint SendInput(uint nInputs, [MarshalAs(UnmanagedType.LPArray), In] INPUT[] pInputs,  int cbSize);

#pragma warning disable 649
    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;
    }

#pragma warning restore 649


    public static void ClickOnPoint(IntPtr wndHandle , Point clientPoint)
    {
      var oldPos = Cursor.Position;

      /// get screen coordinates
      ClientToScreen(wndHandle, ref clientPoint);

      /// set cursor on coords, and press mouse
      Cursor.Position = new Point(clientPoint.X, clientPoint.Y);

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

      /// return mouse 
      Cursor.Position = oldPos;
    }

  }
30
Antonio Bakula

J'ai trouvé dans le passé un moyen d'envoyer un message à Windows Media Player donc je l'ai utilisé pour simuler le clic dans l'application que je voulais!

Utiliser cette classe (code ci-dessous) pour trouver la fenêtre et envoyer les messages que vous voulez!

using System;
using System.Runtime.InteropServices;

namespace Mouse_Click_Simulator
{
    /// <summary>
    /// Summary description for Win32.
    /// </summary>
    public class Win32
    {
        // The WM_COMMAND message is sent when the user selects a command item from 
        // a menu, when a control sends a notification message to its parent window, 
        // or when an accelerator keystroke is translated.
        public const int WM_KEYDOWN = 0x100;
        public const int WM_KEYUP = 0x101;
        public const int WM_COMMAND = 0x111;
        public const int WM_LBUTTONDOWN = 0x201;
        public const int WM_LBUTTONUP = 0x202;
        public const int WM_LBUTTONDBLCLK = 0x203;
        public const int WM_RBUTTONDOWN = 0x204;
        public const int WM_RBUTTONUP = 0x205;
        public const int WM_RBUTTONDBLCLK = 0x206;

        // The FindWindow function retrieves a handle to the top-level window whose
        // class name and window name match the specified strings.
        // This function does not search child windows.
        // This function does not perform a case-sensitive search.
        [DllImport("User32.dll")]
        public static extern int FindWindow(string strClassName, string strWindowName);

        // The FindWindowEx function retrieves a handle to a window whose class name 
        // and window name match the specified strings.
        // The function searches child windows, beginning with the one following the
        // specified child window.
        // This function does not perform a case-sensitive search.
        [DllImport("User32.dll")]
        public static extern int FindWindowEx(
            int hwndParent, 
            int hwndChildAfter, 
            string strClassName, 
            string strWindowName);


        // The SendMessage function sends the specified message to a window or windows. 
        // It calls the window procedure for the specified window and does not return
        // until the window procedure has processed the message. 
        [DllImport("User32.dll")]
        public static extern Int32 SendMessage(
            int hWnd,               // handle to destination window
            int Msg,                // message
            int wParam,             // first message parameter
            [MarshalAs(UnmanagedType.LPStr)] string lParam); // second message parameter

        [DllImport("User32.dll")]
        public static extern Int32 SendMessage(
            int hWnd,               // handle to destination window
            int Msg,                // message
            int wParam,             // first message parameter
            int lParam);            // second message parameter
    }
}

Par exemple:

 Win32.SendMessage(iHandle, Win32.WM_LBUTTONDOWN, 0x00000001, 0x1E5025B);

Voici le code source de mon application que j'ai créé pour cliquer automatiquement dans l'application "BlueStacks" dans un intervalle spécifique!

Pour FindWindow, wParam, lParam, etc. vous pouvez vous sentir libre de me demander comment faire! ce n'est pas trop dur :);) J'espère que cela a aidé! :)

17
ACE