正確には、「.NET Frameworkだけではできない」です。
このようなイベントを設定するためには、"フック"を用いるそうです。
フックについては「参照:KAB-studio フックのしくみ」が非常にわかりやすいので、知らない人は参照してみて下さい。
まとめると、
- "フック"
- システム内のメッセージを条件に合わせて拾い上げること
- "ローカルフック"
- 自スレッドのみに対して働くフック
- "グローバルフック"
- 全てのスレッドに対して働くフック
です。
前述のように「(範囲の内外を問わず)マウスの位置に応じて処理を行う」場合は、
グローバルフックを用いなければなりません。
しかし、「グローバルフックは .NET Framework ではサポートされていない」そうです。
・・・「.NET Framework では」?
つまり、.NET Framework 以外でグローバルフックを取得すればいいわけです。
まずはローカルフックのみを試してみます。
(前回のプログラムと内容的には類似していますが、精度が違います。)
前回と同様に、新しいプロジェクトを開始します。
("ファイル" > "新しいプロジェクト" > "Windows フォームアプリケーション")
ソースコードを見やすくするために、フックを扱うクラス"HookMethods"を別に定義します。
("プロジェクト" > "クラスの追加" > "クラス" で名前を"HookMethods.cs"と入力)
名前空間の修飾省略定義を行う。
/*** HookMethods.cs ***/
using System.Runtime.InteropServices;
フックを扱うためのメソッドを3つ、"user32.dll"より呼び出します。
/*** HookMethods.cs ***/
// フックプロシージャのためのデリゲート
public delegate IntPtr HookProcedureDelegate(int nCode, IntPtr wParam, IntPtr lParam);
// フックプロシージャ"lpfn"をフックチェーン内にインストールする
// 返り値はフックプロシージャのハンドル
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr SetWindowsHookEx(int idHook, HookProcedureDelegate lpfn, IntPtr hInstance, int threadId);
// "SetWindowHookEx"でインポートされたフックプロシージャを削除する
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(IntPtr idHook);
// 次のフックプロシージャにフック情報を渡す
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);
3つのメソッドについて解説します。
"SetWindowsHookEx"と"UnhookWindowsEx"はセットで使われます。
"SetWindowsHookEx"は、フックタイプに関係するフックチェーンに対して、
フックプロシージャをインストールするためのメソッドです。
監視する対象はフックタイプで指定します。
フックタイプには,マウスを監視する"WH_MOUSE"やキーボードを監視する
"WH_KEYBOARD"があります。
1つ目の引数"iHook"に指定します。
フックした時の処理は、フックプロシージャの実装に委ねられます。
フックプロシージャへのポインタを2つ目の引数"lpfn"に指定します。
そのため、C#ではデリゲートを用います。
フックプロシージャの実装は、デリゲートの実装で行います。
"SetWindowsHookEx"メソッドの返り値は、
メソッドが成功した場合は、フックプロシージャのハンドルが、
メソッドが失敗した場合は、NULLが、
返ります。
"SetWindowsHookEx"で返されたフックプロシージャのハンドルを、
"UnhookWindowsHookEx"の引数として指定することで、フックが削除されます。
"CallNextHookEx"は、現在のフックチェーン内の次のフックプロシージャに、
フック情報を渡します。
他のプログラムが同じフックチェーンに対してフックしている場合、
他のプログラムのフックプロシージャに対してフック情報を渡さなければ、
そのフックプロシージャは実行されません。つまり、フックされません。
"CallNextHookEx"を実行しなければ、他のプログラムに影響を及ぼします。
そのため、フックプロシージャの実装コード内で、"CallNextHookEx"を呼び出す
必要があります。
これらのメソッドは、必ず3つセットで利用する必要があります。
"SetWindowsHookEx"は、フックタイプに関係するフックチェーンに対して、
フックプロシージャをインストールするためのメソッドです。
監視する対象はフックタイプで指定します。
フックタイプには,マウスを監視する"WH_MOUSE"やキーボードを監視する
"WH_KEYBOARD"があります。
1つ目の引数"iHook"に指定します。
フックした時の処理は、フックプロシージャの実装に委ねられます。
フックプロシージャへのポインタを2つ目の引数"lpfn"に指定します。
そのため、C#ではデリゲートを用います。
フックプロシージャの実装は、デリゲートの実装で行います。
"SetWindowsHookEx"メソッドの返り値は、
メソッドが成功した場合は、フックプロシージャのハンドルが、
メソッドが失敗した場合は、NULLが、
返ります。
"SetWindowsHookEx"で返されたフックプロシージャのハンドルを、
"UnhookWindowsHookEx"の引数として指定することで、フックが削除されます。
"CallNextHookEx"は、現在のフックチェーン内の次のフックプロシージャに、
フック情報を渡します。
他のプログラムが同じフックチェーンに対してフックしている場合、
他のプログラムのフックプロシージャに対してフック情報を渡さなければ、
そのフックプロシージャは実行されません。つまり、フックされません。
"CallNextHookEx"を実行しなければ、他のプログラムに影響を及ぼします。
そのため、フックプロシージャの実装コード内で、"CallNextHookEx"を呼び出す
必要があります。
これらのメソッドは、必ず3つセットで利用する必要があります。
これで、フックを行う準備はできました。
今回は長くなってしまったので、続きは次回にします。
参照:
MSDNフォーラム クリックしただけで別アプリケーション上の TextBox に文字列をペーストしたい
Stephen Toub : Low-Level Mouse Hook in C#
MSDN フック
0 件のコメント:
コメントを投稿