Como você simula o clique do mouse em c #?

128

Como você simula cliques do mouse em aplicativos c # winforms?

Novato
fonte
5
Você pode fornecer mais informações para obter uma resposta útil.
Andy
36
Dica: se o título for o mesmo que a sua pergunta, o título é muito longo ou a pergunta é muito curta. Nesse caso, é o último, você precisa dar muito mais contexto para que alguém tenha uma chance razoável de dar uma resposta útil.
Guffa

Respostas:

145

Combinei várias fontes para produzir o código abaixo, que estou usando atualmente. Também removi as referências do Windows.Forms para que eu possa usá-lo nos aplicativos de console e WPF sem referências adicionais.

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
fonte
2
Não vejo nenhuma vantagem desse longo código-fonte em relação ao postado por Marcos Placona há 17 meses.
Al Kepp
46
Dada a imprecisão da pergunta, pensei que as pessoas pudessem se beneficiar de um exemplo que lhes permita fazer mais do que apenas um clique esquerdo, sugando um clique direito ou do meio ou permitindo clicar e arrastar.
Keith
2
Funciona bem. Eu vim aqui à procura de algo assim
CSharpie
É isso que estou procurando, mas como você clica para baixo, move o mouse para outro lugar e depois libera?
Ninjaxelite 26/12/16
1
@ ninjaxelite Acho que você envia 1. SetCursorPos, 2. MouseEvent(LeftButtonDown), 3. SetCursorPos, 4. MouseEvent(LeftButtonUp). Potencialmente envolvê-la em um método auxiliar
Michal Ciechan
137

Um exemplo que encontrei em algum lugar aqui no passado. Pode ser de alguma ajuda:

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
fonte
12
Em algum lugar estar aqui, talvez?
MPEN
3
Bem jogado. Referência adicionada à resposta original
Marcos Placona 27/03
2
Estou recebendo um erro com este código: Uma chamada para a função PInvoke 'MyForm! MyForm.Form1 :: mouse_event' desequilibrou a pilha. Provavelmente, porque a assinatura PInvoke gerenciada não corresponde à assinatura de destino não gerenciada. Verifique se a convenção de chamada e os parâmetros da assinatura PInvoke correspondem à assinatura não gerenciada de destino. Alguma ideia?
Abdulla
12
Você precisa converter o X e o Y em pontos.
Dibesjr
1
Funciona perfeitamente precisa de algumas mudanças na posição do cursor como por exigências ...
Anurag Rabadia
14

Alguns controles, como Button no System.Windows.Forms, têm um método "PerformClick" para fazer exatamente isso.

Denis
fonte
Se o controle não tiver um método PerformClick, você poderá estender / adicionar um, basta chamar OnMouseClick com um argumento MouseEventArgs adequado.
Tony Hopkinson
8
Mouse.Click();

Microsoft.VisualStudio.TestTools.UITesting

Prego enferrujado
fonte
1
É meio estranho que isso tenha sido isolado no namespace de teste da interface do usuário do Visual Studio, mas eu assumirei o PInvoke todos os dias em que não preciso filtrar eventos por dispositivo.
kayleeFrye_onDeck
2
Parece que a edição da Comunidade do Visual Studio não é fornecida com esta DLL.
CM
2
Passei apenas uma hora tentando fazer isso funcionar, copiando DLLs de um projeto de "teste de interface do usuário codificada" para outro e, a menos que você esteja usando um tipo de projeto de "teste de interface do usuário codificada", meu conselho é: não se preocupe. Mesmo quando eu copiei todas as DLLs necessárias, ele gerou um InvalidUITestExtensionPackageException, por isso parece ser extremamente exigente quanto à execução em um tipo de projeto específico, infelizmente.
Jez
@ Jez - Útil para saber, obrigado. Não vi quaisquer problemas ainda mim, mas agora eu pelo menos sei que alguns existem; 0)
Rusty Nail
5

Eu tentei o código que Marcos postou e não funcionou para mim. Tudo o que foi dado à coordenada Y, o cursor não se moveu no eixo Y. O código abaixo funcionará se você desejar a posição do cursor em relação ao canto esquerdo da área de trabalho, não em relação ao seu aplicativo.

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

Eu só uso a função mouse_event para realmente executar o clique. Você pode dar a X e Y as coordenadas que deseja, usei valores da caixa de texto:

            X = Convert.ToInt32(tbX.Text);
            Y = Convert.ToInt32(tbY.Text);
AlinaM
fonte
este é o caminho certo para mim, basicamente Cursor.Positioné bom o suficiente para posicionar o cursor do mouse onde você quiser e, em seguida, use o WIN32API para fazer o clique real.
Ge Rong
0

são algumas necessidades que eu não vejo como dominar coisas como Keith ou Marcos Placona fizeram, em vez de apenas fazer

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
fonte
1
Você também pode fazer o button1_Click (nulo, nulo) se não precisar de nenhum desses parâmetros.
sab669
@ sab669 certeza, mas ainda depende de suas necessidades :-)
WiiMaxx
você não deve usar nullno segundo parâmetro, ele vai jogar um NullReferenceException, em vez usarEventArgs.Empty
Etor Madiv
1
@EtorMadiv como eu disse antes, depende do que você está tentando Tudo ..., porque se você usá-lo como eu fiz acima, você não vai conseguir umNullReferenceException
WiiMaxx