MouseKeyHookでグローバルマウスダウンを検出できません

Dec 31 2020

私は過去数時間、マウスの左クリックをグローバルに(フォーカスされていない)検出する方法を見つけるために調査しており、以下に示すように実装したNuGetを介してインストールしたglobalmousekeyhookの使用について言及している複数の投稿に遭遇しました:

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.");
        }
    }
}

それを実行すると、画面上のマウスが突然使用できなくなるまで遅れ始め(コマンドプロンプトを閉じるのに苦労しました)、左右両方をクリックしようとしましたが、何もログに記録されません。私は完全に愚かなことをしていますか?他の誰もこの問題を抱えていないので、私が見逃している本当に明白な何かがあると感じます。または、別の解決策があれば、私はそれを試してみてうれしいです。ありがとうございました。

Visual Studio 2019、Windows 10 Pro、プロジェクト:.NET Framework 4.7.2、コンソールアプリケーション、デバッグモードで実行

回答

EpicSpeedy Jan 03 2021 at 08:41

私は実際にいつものように遊んでいて、それを行うさまざまな方法を探していて、キーの状態(GetKeyStates)(マウスを含む)を取得するためのWindows API関数に出くわしたので、user32 DLLをインポートして、チェックするループを開始しましたマウスの左ボタンの状態(0x01)は50ミリ秒ごとに(これが最適な時間であることがわかりました)、メインのボタンをブロックしないようにスレッドにスローしました。

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!");
        }
    }
}

これにはおそらくもっと良い解決策があります(私は見つけることができませんでした)ので、なぜ私はこれを使用しています。私はもともと私の正確な質問に対する答えに基づいていましたが、代わりにPythonで書かれていたので、C#に変換しました。私の質問に対する唯一の答えが「サードパーティのライブラリを使用する」ことであることにうんざりしていました。これは何らかの理由で適切に機能せず、メモリ使用量も30MBから7MBに減少しました:)。

私もそれをWindows7でテストしました、そしてそれは素晴らしい働きをします。