single.php

C# WinFormsプロジェクトでマウスの右クリックを検出したい場合の対処法

C#のWinFormsプロジェクトで、フォーム以外の場所でのマウスの右クリックを検出したい場合の対処法について備忘録的に投稿します。

WindowHookで検出

タスクトレイの常駐アプリなどフォームを持たないアプリでマウスの右クリックを検出するには、WindowHookを利用して検出が可能です。

とはいえ、C#のみのアセンブリでは難しいのでWin32 APIを使います。

private const int WH_MOUSE_LL = 14;
private const int WM_RBUTTONDOWN = 0x0204;
private const int WM_RBUTTONUP = 0x0205;

private static IntPtr _hookID = IntPtr.Zero;
private static LowLevelMouseProc _proc = HookCallback;

public static event Action<string>? MouseAction;

[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
public static extern IntPtr CallNextHookEx(IntPtr hHook, int nCode, IntPtr wParam, IntPtr lParam);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr GetModuleHandle(string lpModuleName);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool UnhookWindowsHookEx(IntPtr hhk);

private static IntPtr SetHook(LowLevelMouseProc proc)
{
    
    using (Process curProcess = Process.GetCurrentProcess())
    using (ProcessModule? curModule = curProcess.MainModule)
    {
        if(curModule != null)
        {
            return SetWindowsHookEx(WH_MOUSE_LL, proc,
                GetModuleHandle(curModule.ModuleName), 0);
        }
        else
        {
            return IntPtr.Zero;
        }
    }
}

private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);

private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
    if (nCode >= 0)
    {
        int msg = wParam.ToInt32();

        if (msg == WM_RBUTTONDOWN)
        {
            // 押した瞬間
            MouseAction?.Invoke("R_DOWN");
        }
        else if (msg == WM_RBUTTONUP)
        {
            // 離した瞬間
            MouseAction?.Invoke("R_UP");
        }
    }

    return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

チョット面倒な処理ですが、マウスの右ボタン以外でも検出するメッセージを追加すれば取得ができます。

Actionイベントで取得可能

[NativeWindow]クラス内で[Action]イベントを使って、Windows側のテーマ変更を受け取ります。

WindowHookの呼び出しはクラスのコンストラクター部分で、SetHookを呼び出して、取得後のイベントを追加します。

コードにすると、こんな感じです。

public SampleApp()
{
    _hookID = SetHook(_proc);
    if(_hookID != IntPtr.Zero)
    {
      MouseAction += OnMouseAction;
    }
}

private void OnMouseAction(string action)
{
    if (MouseAction != null)
    {
        if(action == "R_DOWN")
        {
            Console.WriteLine("マウスの右ボタンが押された");
        }
        else if(action == "R_UP")
        {
            Console.WriteLine("マウスの右ボタンが離された");
        }
    }
}

実行すると、フォーム以外の部分でマウスの右ボタンを押すと[OnMouseAction]イベントが動作します。

まとめ

今回は短い記事ですがC#のWinFormsプロジェクトでフォーム以外の場所でのマウスの右クリックを検出したい場合の対処法について書きました。

WindowHookを追加することで、フォーム以外の場所でマウスの右ボタンが押されたイベントを検出できます。

WinFormsプロジェクトで右クリックなどマウスのイベントを検出したい人の参考になれば幸いです。

スポンサーリンク

最後までご覧いただき、ありがとうございます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です