Как имитировать щелчок мышью в C #?

128

Как вы имитируете щелчки мышью в приложениях C # winforms?

Новичок
источник
5
Возможно, вы захотите предоставить дополнительную информацию, чтобы получить полезный ответ.
Энди
36
Совет: если ваш заголовок совпадает с вашим вопросом, значит, заголовок слишком длинный или вопрос слишком короткий. В данном случае это последнее, вам нужно предоставить намного больше контекста, чтобы у кого-то был разумный шанс дать вам полезный ответ.
Guffa

Ответы:

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 месяцев назад.
Аль Кепп
47
Учитывая расплывчатость вопроса, я подумал, что людям может быть полезен пример, который позволяет им делать больше, чем просто щелчок левой кнопкой мыши, щелчок правой или средней кнопкой мыши или разрешать щелчок и перетаскивание.
Кейт
2
Прекрасно работает. Я пришел сюда в поисках чего-то вроде этого
CSharpie
Это то, что я ищу, но как вы щелкните вниз, переместите мышь в другое место, а затем отпустите?
ninjaxelite
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
Отлично сработано. Добавлена ​​ссылка на оригинальный ответ
Marcos Placona
2
Я получаю сообщение об ошибке с этим кодом: вызов функции PInvoke «MyForm! MyForm.Form1 :: mouse_event» разбалансировал стек. Вероятно, это связано с тем, что подпись управляемого PInvoke не соответствует подписи неуправляемого целевого объекта. Убедитесь, что соглашение о вызовах и параметры подписи PInvoke соответствуют целевой неуправляемой подписи. Любые идеи?
Абдулла
12
Вам нужно преобразовать X и Y в uints.
Dibesjr 05
1
Работает отлично, нужно немного изменить положение курсора в соответствии с требованиями ...
Анураг Рабадия
14

Некоторые элементы управления, например Button в System.Windows.Forms, имеют для этого метод PerformClick.

Денис
источник
Если элемент управления не имеет метода PerformClick, вы можете расширить / добавить его, просто нужно вызвать OnMouseClick с подходящим аргументом MouseEventArgs.
Тони Хопкинсон
8
Mouse.Click();

Microsoft.VisualStudio.TestTools.UITesting

ржавый гвоздь
источник
1
Как-то странно, что это было изолировано в пространстве имен тестов пользовательского интерфейса Visual Studio, но я возьму это на себя с помощью PInvoke в любой день, когда мне не нужно фильтровать события по устройствам.
kayleeFrye_on, декабрь
2
Похоже, что версия Visual Studio Community не поставляется с этой DLL.
CM
2
Я просто потратил час, пытаясь заставить это работать, копируя библиотеки DLL из проекта «закодированного теста пользовательского интерфейса» в другой, и если вы не используете тип проекта «закодированный тест пользовательского интерфейса», мой совет: не беспокойтесь. Даже когда я скопировал все необходимые библиотеки DLL, он выкинул a InvalidUITestExtensionPackageException, поэтому, к сожалению, он кажется очень суетливым при работе с конкретным типом проекта.
Jez
@Jez - Полезно знать, спасибо. Сам пока не замечал никаких проблем, но теперь я, по крайней мере, знаю, что они существуют; 0)
Rusty Nail
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);
AlinaM
источник
это правильный Cursor.Positionвыбор для меня, в основном он достаточно хорош для размещения курсора мыши в любом месте, а затем использовать WIN32API для фактического щелчка.
Ге Ронг
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");
        }
    }
}
WiiMaxx
источник
1
Вы также можете использовать button1_Click (null, null), если вам не нужен ни один из этих параметров.
sab669
@ sab669 конечно, но это все еще зависит от его потребностей :-)
WiiMaxx
вы не должны использовать nullво втором параметре, он выдаст a NullReferenceException, вместо этого используйтеEventArgs.Empty
Etor Madiv
1
@EtorMadiv, как я уже сказал, это зависит от того, что вы пытаетесь сделать ... потому что, если вы используете его, как я сделал выше, вы не получитеNullReferenceException
WiiMaxx