Nie można wykryć globalnego naciśnięcia myszy za pomocą MouseKeyHook

Dec 31 2020

Szukałem przez ostatnie kilka godzin, aby dowiedzieć się, jak globalnie wykryć lewe kliknięcia myszy (nie skupione) i natknąłem się na wiele postów wspominających o użyciu globalmousekeyhook, który zainstalowałem za pośrednictwem NuGet, który wdrożyłem, jak widać poniżej:

using Gma.System.MouseKeyHook;
using System;

namespace mouse_hook_test
{
    class Program
    {
        static private IKeyboardMouseEvents m_GlobalHook;

        static void Main(string[] args)
        {
            Subscribe();

            Console.ReadKey();
        }

        static public void Subscribe()
        {
            m_GlobalHook = Hook.GlobalEvents();

            m_GlobalHook.MouseDownExt += GlobalHookMouseDownExt;
        }

        static private void GlobalHookMouseDownExt(object sender, MouseEventExtArgs e)
        {
            Console.WriteLine("Mouse Click.");
        }
    }
}

Kiedy go uruchamiam, moja mysz ekranowa nagle zaczyna się opóźniać do punktu, w którym jest bezużyteczna (nawet starałem się zamknąć wiersz polecenia), a także próbowałem kliknąć zarówno w lewo, jak iw prawo, ale nic nie jest rejestrowane. Czy robię coś zupełnie głupiego? Czuję, że brakuje mi czegoś naprawdę oczywistego, ponieważ nikt inny nie ma tego problemu lub jeśli istnieje inne rozwiązanie, chętnie go wypróbuję. Dziękuję Ci.

Visual Studio 2019, Windows 10 Pro, Project: .NET Framework 4.7.2, aplikacja konsolowa, działał w trybie debugowania

Odpowiedzi

EpicSpeedy Jan 03 2021 at 08:41

Właściwie bawiłem się jak zwykle, szukając różnych sposobów, aby to zrobić, a następnie natknąłem się na funkcję Windows API do uzyskiwania stanów kluczy (GetKeyStates) (w tym myszy), więc zaimportowałem bibliotekę DLL user32 i uruchomiłem pętlę, która sprawdza stan lewego przycisku myszy ( 0x01) co 50 ms (uznany za najlepszy czas) i wrzucił go w wątek, aby nie blokował głównego.

using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace mouse_hook_test
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread thread = new Thread(detect);
            thread.Start();
        }

        // Import the DLL that contains the function and grab it.
        [DllImport("user32.dll")]
        public static extern short GetKeyState(int vKey);

        // A very simple implementation for tracking the state of the left mouse button.
        static void detect()
        {
            short oldState = GetKeyState(0x01);

            while (true)
            {
                short newState = GetKeyState(0x01);                

                if (oldState != newState)
                {
                    oldState = newState;

                    if (newState < 0)
                    {
                        onMouseClick();
                    }
                }

                Thread.Sleep(50);
            }
        }

        static void onMouseClick()
        {
            Console.WriteLine("Clicked!");
        }
    }
}

Prawdopodobnie jest na to lepsze rozwiązanie (którego nie mogłem znaleźć), więc dlaczego tego używam. Pierwotnie oparłem to na odpowiedzi na moje dokładne pytanie, ale zamiast tego zostało napisane w Pythonie, więc przekonwertowałem je na C #. Miałem dość tego, że jedyną odpowiedzią na moje pytanie było „użycie jakiejś biblioteki innej firmy”, która z jakiegoś powodu nie działa poprawnie i zmniejszyła zużycie pamięci z 30 MB do 7 MB :).

Przetestowałem go również na Windows 7 i działa wspaniale.