C # 'da Fare Tıklamasını nasıl simüle edersiniz?


128

C # winforms uygulamalarında Fare tıklamalarını nasıl simüle edersiniz?


5
Faydalı bir yanıt alabilmek için daha fazla bilgi vermek isteyebilirsiniz.
Andy

36
İpucu: Başlığınız sorunuzla aynıysa, başlık çok uzun veya soru çok kısa. Bu durumda, ikincisi, size yararlı bir cevap vermesi için makul bir şansa sahip olmak için çok daha fazla bağlam vermelisiniz.
Guffa

Yanıtlar:


145

Şu anda kullanmakta olduğum aşağıdaki kodu üretmek için birkaç kaynağı birleştirdim. Windows.Forms referanslarını da kaldırdım, böylece ek referanslar olmadan konsol ve WPF uygulamalarından kullanabiliyorum.

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
Bu uzun kaynak kodunun, Marcos Placona'yı 17 ay önce yayınlayanlara kıyasla hiçbir avantajını göremiyorum.
Al Kepp

47
Sorunun belirsizliği göz önünde bulundurulduğunda, insanların bir sol tıklama ile sağ veya orta tıklama emmekten veya tıklama ve sürüklemeye izin vermekten daha fazlasını yapmalarına izin veren bir örnekten yararlanabileceklerini düşündüm.
Keith

2
Harika çalışıyor. Buraya böyle bir şey aramak için geldim
CSharpie

Benim aradığım şey bu, ama nasıl tıklarsınız, fareyi başka bir yere hareket ettirir ve sonra bırakırsınız?
ninjaxelite

1
@ninjaxelite gönderdiğini tahmin ediyorum 1. SetCursorPos, 2. MouseEvent(LeftButtonDown), 3. SetCursorPos, 4. MouseEvent(LeftButtonUp). Potansiyel olarak yardımcı bir yöntemle sarın
Michal Ciechan

137

Geçmişte burada bir yerde bulduğum bir örnek . Biraz yardımcı olabilir:

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
Bir yerde olmak burada belki?
mpen

3
Güzel oynadı. Orijinal yanıta referans eklendi
Marcos Placona

2
Bu kodla ilgili bir hata alıyorum: 'MyForm! MyForm.Form1 :: mouse_event' PInvoke işlevine yapılan bir çağrı yığını dengesizleştirdi. Bunun nedeni muhtemelen yönetilen PInvoke imzasının yönetilmeyen hedef imzasıyla eşleşmemesidir. Çağrı kuralı ve PInvoke imzasının parametrelerinin, hedef yönetilmeyen imzayla eşleştiğini kontrol edin. Herhangi bir fikir?
Abdulla

12
X ve Y'yi uintlere atmanız gerekir.
Dibesjr

1
İşler, gereksinimlere göre imleç konumunda bazı değişikliklere ihtiyaç duyuyor ...
Anurag Rabadia

14

System.Windows.Forms'daki Button gibi bazı kontroller, tam da bunu yapmak için "PerformClick" yöntemine sahiptir.


Denetimin bir PerformClick yöntemi yoksa, bir tane genişletebilir / ekleyebilirsiniz, sadece uygun bir MouseEventArgs bağımsız değişkeniyle OnMouseClick'i çağırmanız yeterlidir.
Tony Hopkinson

8

1
Bunun Visual Studio UI test ad alanında izole edilmiş olması biraz garip, ancak olayları cihaza göre filtrelemem gerekmediği her gün bunu PInvoke'a devredeceğim.
kayleeFrye_onDeck

2
Görünüşe göre Visual Studio Community sürümü bu DLL ile birlikte gelmiyor.
CM

2
DLL'leri bir "kodlanmış UI testi" projesinden diğerine kopyalayarak bunu çalıştırmak için bir saatimi harcadım ve "kodlanmış UI testi" proje türü kullanmıyorsanız, tavsiyem: zahmet etmeyin. Gerekli tüm DLL'leri kopyaladığımda bile bir attı InvalidUITestExtensionPackageException, bu yüzden maalesef belirli bir proje türünde çalıştırmak konusunda son derece titiz görünüyor.
Jez

@Jez - Bilmesi faydalı, teşekkürler. Henüz herhangi bir sorun görmedim, ama şimdi en azından bazılarının var olduğunu biliyorum; 0)
Rusty Nail

5

Marcos'un gönderdiği kodu denedim ve benim için işe yaramadı. Y koordinatına ne verilirse verilsin, imleç Y ekseninde hareket etmedi. Aşağıdaki kod, imlecin konumunu uygulamanıza göre değil, masaüstünüzün sol üst köşesine göre istiyorsanız işe yarar.

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

Tıklamayı gerçekten gerçekleştirmek için yalnızca mouse_event işlevini kullanıyorum. X ve Y'ye istediğiniz koordinatları verebilirsiniz, metin kutusundaki değerleri kullandım:

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

bu benim için doğru olanı, temelde Cursor.Positionfare imlecini istediğiniz yere konumlandırmak için yeterince iyi, ardından gerçek tıklamayı yapmak için WIN32API kullanın.
Ge Rong

0

Keith veya Marcos Placona gibi şeyleri yapmak yerine yaptığını göremediğim bazı ihtiyaçlar

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
Bu parametrelerden herhangi birine ihtiyacınız yoksa button1_Click (null, null) da yapabilirsiniz.
sab669

@ sab669 elbette ama yine de ihtiyaçlarına bağlı :-)
WiiMaxx

Eğer kullanmamalısınız nullikinci parametrede, bir atacağım NullReferenceExceptionyerine kullanmakEventArgs.Empty
Etor Madiv

1
İ Eğer todo çalışıyoruz bağlıdır önce söylediğim gibi yukarıda yaptım gibi @EtorMadiv ..., bunu kullanmak çünkü eğer bir olsun alışkanlıkNullReferenceException
WiiMaxx
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.