Як ви імітуєте клацання миші в C #?


128

Як ви імітуєте клацання миші в додатках для формату C #?


5
Ви можете надати більше інформації, щоб отримати корисну відповідь.
Енді

36
Порада: Якщо ваш заголовок збігається з вашим запитанням, то заголовок занадто довгий або запитання занадто коротке. У цьому випадку це останнє, ви повинні дати набагато більше контексту, щоб кожен мав розумний шанс дати вам корисну відповідь.
Гуффа

Відповіді:


145

Я поєднав декілька джерел, щоб створити код нижче, який я зараз використовую. Я також видалив посилання на Windows.Forms, щоб я міг використовувати його з консольних та WPF-програм без додаткових посилань.

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

2
Я не бачу жодної переваги цього довгого вихідного коду над тим, що опублікував Маркос Плакона 17 місяців тому.
Al Kepp

47
З огляду на розпливчастість питання, я подумав, що люди можуть отримати користь із прикладу, який дозволяє їм робити більше, ніж просто клацання лівою кнопкою миші правою чи середньою клацанням або дозволяти натискання та перетягування.
Кіт

2
Чудово працює. Я прийшов сюди шукати щось подібне
CSharpie

Це те, що я шукаю, але як ти клацнеш вниз, перемістиш мишу кудись і потім відпустиш
ніндзякселіт

1
@ninjaxelite Я здогадуюсь, що ти надішлеш 1. SetCursorPos, 2. MouseEvent(LeftButtonDown), 3. SetCursorPos, 4. MouseEvent(LeftButtonUp). Потенційно оберніть це в хелперний метод
Міхал Цехан

137

Приклад, який я знайшов десь тут раніше. Можливо, вам допоможуть:

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
}

12
Десь тут, можливо?
mpen

3
Гарно зіграно. Додано посилання на оригінальну відповідь
Маркос Плакона

2
Я отримую помилку з цим кодом: Виклик функції PInvoke "MyForm! MyForm.Form1 :: mouse_event" вирівняв стек. Це, ймовірно, тому, що керований підпис PInvoke не відповідає некерованому цільовому підпису. Перевірте, чи відповідають умові виклику та параметри підпису PInvoke цільовим некерованим підписом. Будь-які ідеї?
Абдулла

12
Потрібно віддати X і Y до уінт.
Dibesjr

1
Працює чудово потрібні деякі зміни положення курсору відповідно до вимог ...
Анураг Рабадія

14

Деякі елементи керування, як-от кнопка в System.Windows.Forms, мають метод "PerformClick", щоб зробити саме це.


Якщо в елементі управління немає методу PerformClick, його можна розширити / додати, просто потрібно зателефонувати на OnMouseClick за допомогою відповідного аргументу MouseEventArgs.
Тоні Хопкінсон

8

1
Це дивно, що це було виділено у тестовому просторі імен інтерфейсу Visual Studio, але я прийму це за PInvoke в будь-який день, що мені не потрібно фільтрувати події на пристрої.
kayleeFrye_onDeck

2
Схоже, видання Visual Studio Community не постачається з цією DLL.
CM

2
Я щойно витратив годину, намагаючись змусити це працювати, копіюючи DLL-файли з проекту "закодований тест інтерфейсу" на інший, і якщо ви не використовуєте тип проекту "закодований тест інтерфейсу", моя порада: не турбуйтеся. Навіть коли я скопіював усі необхідні DLL-файли, які вони викинули InvalidUITestExtensionPackageException, так що, здається, надзвичайно метушливим щодо запуску певного типу проекту, на жаль.
Їжак

@Jez - зручно знати, дякую. Я ще не бачив жодних проблем, але зараз я принаймні знаю, що існують; 0)
Іржавий ніготь

5

Я спробував код, який розмістив Маркос, і він не працював для мене. Що б мені не було дано координату Y, курсор не переміщувався по осі Y. Код нижче буде працювати, якщо ви хочете розташувати курсор відносно лівого кута робочого столу, а не стосовно вашої програми.

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

Я використовую лише функцію mouse_event, щоб фактично виконати клацання. Ви можете надати X і Y потрібні координати, я використовував значення з текстового поля:

            X = Convert.ToInt32(tbX.Text);
            Y = Convert.ToInt32(tbY.Text);

це правильне для мене, в основному Cursor.Positionдосить добре для розміщення курсору миші туди, де ви хочете, а потім використовуйте WIN32API, щоб зробити фактичне натискання.
Ge Rong

0

вони є якимись потребами, яких я не бачу, щоб куполити щось таке, як Кіт чи Маркос Плакона , а не просто робити

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

1
Ви також можете зробити button1_Click (null, null), якщо вам не потрібен жоден із цих параметрів.
sab669

@ sab669 впевнений, але це все ще залежить від його потреб :-)
WiiMaxx

ви не повинні використовувати nullв другому параметрі, він буде кидати a NullReferenceException, замість цього використовуватиEventArgs.Empty
Etor Madiv

1
@EtorMadiv, як я сказав, перш ніж це залежить від того, що ви намагаєтеся todo ..., тому що якщо ви використовуєте його так, як я робив вище, ви не отримаєтеNullReferenceException
WiiMaxx
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.