C# Mouse Tıklamalarını Yakalama

Gokrtl

Gökhan Kartal (TeknoDay)
Staff member
Katılım
27 Şubat 2019
Mesajlar
11,212
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


C# Mouse Yakalama:
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.

C++:
            [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")]
 
C#:
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.

C#:
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);
            }
        }
    }
}
 

Forum istatistikleri

Konular
5,833
Mesajlar
99,499
Üyeler
2,479
Son üye
yiyehuoxing32

Son kaynaklar

Son profil mesajları

gruptaki arkadaşlara selamlar. sıteyi bu gün fark ettim. Asansör için 2x7 segment LCD gösterge üretmek istiyorum. acaba bu sayfadaki arkadaşlardan destek alabilirmiyim. LCD nin mantık açılımı ektedir.
deneyci wrote on TA3UIS's profile.
Selam.
Amatör telsiz lisansı nasıl alınıyor?
Lisansı olmayanı forumlarına almıyorlar. :)
Bilgi alamıyoruz.
cemalettin keçeci wrote on HaydarBaris's profile.
barış kardeşim bende bu sene akıllı denizaltı projesine girdim ve sensörleri arastırıyorum tam olarak hangi sensör ve markaları kullandınız yardımcı olabilir misin?
m.white wrote on Altair's profile.
İyi akşamlar.Arabanız ne marka ve sorunu nedir.Ben araba tamircisi değilim ama tamirden anlarım.
* En mühim ve feyizli vazifelerimiz millî eğitim işleridir. Millî eğitim işlerinde mutlaka muzaffer olmak lâzımdır. Bir milletin hakikî kurtuluşu ancak bu suretle olur. (1922)
Back
Top