C# Mouse Tıklamalarını Yakalama

Gokrtl

Gökhan Kartal (TeknoDay)
Staff member
Katılım
27 Şubat 2019
Mesajlar
12,195
C# ile mouse tıklamalarını yakalayıp sayan küçük bir program yazmaya çalışıyorum.
Formun kendi içinde mouse tıklayıp sayma olayını "MouseDown" ile yaptım ama bana Windows genelinde mouse yakalayacak bir kod lazım.
Nette araştırmalarımda "Hook" atmak gerektiğini öğrendim. Örnek kod olarak mouse bulamadım ama klavye yakalaması buldum.
Bu kodların içinde 13 parametresi girilince "WH_KEYBOARD_LL" çalışıyormuş. Araştırınca 14 parametresinin de "WH_MOUSE_LL" parametresini çalıştırdığını öğrendim.
Bu kodları mouse için uydurmaya çalıştım ama "DLL Import" hatası alıyorum. bu konuda yardımcı olabilecek var mı?

Kaynak (Sayfaya girince aşağılardaki Windows Genelinde Tuş Vuruşu Yakalama kısmından aldım kodları)

mouse_hook.png


Kod:
namespace Sayaç
{
    public partial class Sayaç : Form
    {
            private delegate int MouseHookProc(int code, int wParam, ref MouseHookStruct lParam);

            [DllImport("user32.dll")]
            private static extern IntPtr SetWindowsHookEx(int idHook, MouseHookProc callback, IntPtr hInstance, uint threadId);

            [DllImport("kernel32.dll")]
            private static extern IntPtr LoadLibrary(string lpFileName);

            [DllImport("user32.dll")]
            private static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref MouseHookStruct lParam);

            private readonly IntPtr _hook;

            private struct MouseHookStruct
            {
                public int VkCode;
                public int ScanCode;
                public int Flags;
                public int Time;
                public int DwExtraInfo;
            }

        public Sayaç()
        {
            InitializeComponent();
            var hInstance = LoadLibrary("User32");
            _hook = SetWindowsHookEx(14, HookProc, hInstance, 0);
        }
        private int HookProc(int code, int wParam, ref MouseHookStruct lParam)
        {
            if (code >= 0 && lParam.Flags == 0)
            {
                var key = (Keys)lParam.VkCode;
                MessageBox.Show(key.ToString());
            }
            return CallNextHookEx(_hook, code, wParam, ref lParam);
        }
 
Visual Studio önerisini kullanarak dll import sorununu aşağıdaki şekilde çözdüm.
Şimdi başka bir problemim var. Bu kodlar mouse hareketini yakalıyor. Benim tıklamaları yakalamam gerek.
Bunun içinde MK_LBUTTON parametresi var ama nereye gireceğimi bulamadım.

Kod:
            [System.Runtime.InteropServices.DllImport("user32.dll")]
            private static extern IntPtr SetWindowsHookEx(int idHook, MouseHookProc callback, IntPtr hInstance, uint threadId);

            [System.Runtime.InteropServices.DllImport("kernel32.dll")]
            private static extern IntPtr LoadLibrary(string lpFileName);

            [System.Runtime.InteropServices.DllImport("user32.dll")]
 
Kod:
namespace Sayaç
{
public partial class Sayaç : Form
{
private delegate int MouseHookProc(int code, int wParam, ref MouseHookStruct lParam);
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(int idHook, MouseHookProc callback, IntPtr hInstance, uint threadId);
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern IntPtr LoadLibrary(string lpFileName);
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref MouseHookStruct lParam);
private readonly IntPtr _hook;
private struct MouseHookStruct
{
public int VkCode;
public int ScanCode;
public int Flags;
public int Time;
public int DwExtraInfo;
}
public Sayaç()
{
InitializeComponent();
var hInstance = LoadLibrary("User32");
_hook = SetWindowsHookEx(14, HookProc, hInstance, 0);
}
private int HookProc(int code, int lParam, ref MouseHookStruct wParam)
{
if (code >= 0 && wParam.Flags == 0)
{
var sayi = (Keys)wParam.VkCode;
//MessageBox.Show(sayi.ToString());
if (sayi <= 0)
{
sayi = 0;
label1.Text = Convert.ToString(sayi);
}
else
{
sayi--;
label1.Text = Convert.ToString(sayi);
}
}
return CallNextHookEx(_hook, code, lParam, ref wParam);
}
 
Aşağıdaki kod bloğunu başka bir yerden bulup kendime göre uyarladım.
Burada bir sorun oluştu;
Form dışındaki Mouse tıklamalarını sayıyor ama anlık olarak label içine yazmıyor. Taaki Form içine tıklayana kadar.
Sayı 100 ise ve ben mouse'a 5 defa tıkladıysam Form içi Label 100 de kalmaya devam ediyor. Eğer form içinde bir yere tıklarsam direk 95'e düşüyor.
Benim istediğim her tık'ı anlık olarak sayıdan düşmesi.

Kod:
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Sayaç
{
    public partial class Sayaç : Form
    {
        public Sayaç()
        {
            InitializeComponent();
            this.MouseLeave += Sayaç_MouseLeave;
            this.Leave += Sayaç_Leave;
            this.Deactivate += Sayaç_Deactivate;
            this.MouseEnter += Sayaç_MouseEnter;
            this.Activated += Sayaç_Activated;
            this.Enter += Sayaç_Enter;
            this.VisibleChanged += Sayaç_VisibleChanged;
        }
        byte sayi = 0;

        private AutoResetEvent are = new AutoResetEvent(false);

        // You could create just one handler, but this is to show what you need to link to
        private void Sayaç_MouseLeave(object sender, EventArgs e) => StartWaitingForClickFromOutside();
        private void Sayaç_Leave(object sender, EventArgs e) => StartWaitingForClickFromOutside();
        private void Sayaç_Deactivate(object sender, EventArgs e) => StartWaitingForClickFromOutside();
        private void StartWaitingForClickFromOutside()
        {
            are.Reset();
            var ctx = new SynchronizationContext();

            var task = Task.Run(() =>
            {
                while (true)
                {
                    if (are.WaitOne(1)) break;
                    if (MouseButtons == MouseButtons.Left)
                    {
                        //ctx.Send(CLickFromOutside, null);
                        // You might need to put in a delay here and not break depending on what you want to accomplish
                        if (sayi <= 0)
                        {
                            sayi = 0;
                            label1.Text = Convert.ToString(sayi);
                        }
                        else
                        {
                            sayi--;
                            label1.Text = Convert.ToString(sayi);
                        }
                        break;
                    }
                }
            });
        }

        private void CLickFromOutside(object state) => MessageBox.Show("Clicked from outside of the window");
        private void Sayaç_MouseEnter(object sender, EventArgs e) => are.Set();
        private void Sayaç_Activated(object sender, EventArgs e) => are.Set();
        private void Sayaç_Enter(object sender, EventArgs e) => are.Set();
        private void Sayaç_VisibleChanged(object sender, EventArgs e)
        {
            if (Visible) are.Set();
            else StartWaitingForClickFromOutside();
        }

       
        byte sec;

        private void Sayaç_Load(object sender, EventArgs e)
        {
            this.TopMost = true;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            sayi = 75;
            sec = 0;
            label1.Text = Convert.ToString(sayi);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            sayi = 35;
            sec = 1;
            label1.Text = Convert.ToString(sayi);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (sec == 0){
                sayi = 75;
                label1.Text = Convert.ToString(sayi);
            }else if (sec == 1)
            {
                sayi = 35;
                label1.Text = Convert.ToString(sayi);
            }
        }

        private void Sayaç_MouseDown(object sender, MouseEventArgs e)
        {
            if (sayi <=0) {
                sayi = 0;
                label1.Text = Convert.ToString(sayi);
            }
            else
            {
                sayi--;
                label1.Text = Convert.ToString(sayi);
            }
        }
    }
}
 

Çevrimiçi üyeler

Forum istatistikleri

Konular
7,285
Mesajlar
123,217
Üyeler
2,939
Son üye
Cano

Son kaynaklar

Son profil mesajları

Freemont2.0 herbokolog Freemont2.0 wrote on herbokolog's profile.
nick iniz yakıyor
:D
Freemont2.0 posta Freemont2.0 wrote on posta's profile.
Merhabalar :)
az bilgili çok meraklı
Prooffy semih_s Prooffy wrote on semih_s's profile.
Merhaba, sizden DSO2C10 hakkında bilgi rica ettim. Yanıtlarsanız sevinirim...
Unal taydin Unal wrote on taydin's profile.
Timur Bey, Arduino kontrollü bir akü şarj cihazı yapmaya çalışıyorum. Aklımdaki fikri basit bir çizim olarak konu açmıştım. Özellikle sizin fikirlerinizi çok önemsiyorum.
Back
Top