先にどうぞ。
前回は、フックを行うための準備まで実装しました。
今回はいよいよ、フック処理を実装します。
の前に、フック処理の開始 / 終了を切り替えるボタンを設置しましょう。
"Form1.cs"のデザイナを開き、"Button"を"Form1"上に設置します。
作成された"button1"をダブルクリックし"button1_Click"メソッドを作成します。
では、マウスフック処理を行うための準備をします。
まずは、"Form1.cs"に名前空間の修飾省略定義を行います。
/*** Form1.cs ***/
using System.Runtime.Interopesrvices;
次に、位置と、マウスフックを表す構造体を宣言します。
/*** Form1.cs ***/
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public class MouseHookStruct
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
構造体"POINT"は画面内の座標を表します。
同じく,"MouseHookStruct"はマウスフックを表します。
フックプロシージャのハンドルを保存しておくための、静的フィールドを用意します。
/*** Form1.cs ***/
private static IntPtr hHook = IntPtr.Zero;
次に,マウスに対するフックタイプを宣言します。
/*** Form1.cs ***/
private const int WH_MOUSE = 7;
フックタイプには,様々なものがあります。詳しくはMSDNを参照して下さい。
マウスフックを設定 / 削除するためのメソッドを作成します。
/*** Form1.cs ***/
private void SetMouseHook(HookMethods.HookProcedureDelegate proc)
{
// マウスフックを設定
hHook = HookMethods.SetWindowsHookEx(WH_MOUSE, proc, IntPtr.Zero, AppDomain.GetCurrentThreadId());
if (hHook == IntPtr.Zero)
{
MessageBox.Show("SetWindowsHookEx Failed.");
}
}
private void RemoveMouseHook()
{
// フックを削除
if (HookMethods.UnhookWindowsHookEx(hHook) == false)
{
MessageBox.Show("UnhookWindowsHookEx Failed.");
}
}
マウスフックプロシージャの実装を行います。
/*** Form1.cs ***/
public IntPtr MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if(nCode >= 0)
{
// コールバックからのデータを整理する.
MouseHookStruct MyMouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
String strCaption = "x = " + MyMouseHookStruct.pt.x.ToString("d") + " : y = " + MyMouseHookStruct.pt.y.ToString("d");
this.Text = strCaption;
}
return HookMethods.CallNextHookEx(hHook, nCode, wParam, lParam);
}
これで、マウスフックの処理を行うための準備ができました。
では、実際にマウスフック処理を行ってみましょう。
"button1"が押されたらフックを開始し、再度押されたらフックを終了する処理を記述します。
/*** Form1.cs ***/
private void button1_Click(object sender, EventArgs e)
{
if (hHook == IntPtr.Zero)
{
SetMouseHook(MouseHookProc);
this.button1.Text = "Unhook Windows Hook";
}
else
{
RemoveMouseHook();
this.button1.Text = "Set Windwos Hook";
}
}
実行します。
以下のような警告がでますが、後ほど削除する部分なので、無視します。
'System.AppDomain.GetCurrentThreadId()' は古い形式です: 'AppDomain.GetCurrentThreadId has been deprecated because it does not provide a stable Id when managed threads are running on fibers (aka lightweight threads). To get a stable identifier for a managed thread, use the ManagedThreadId property on Thread. http://go.microsoft.com/fwlink/?linkid=14202'
"button1"を押すと、フックが開始されます。
"Form1"内でマウスを動かすと、その座標がタイトルに表示されます。
"Form1"外では、タイトルが変化しません。
もう一度"button1"を押すと、フックが終了します。
ローカルフックを用いて、マウスの位置を取得し続けることはできました。
.NETのみで実装した場合に比べて、動きがスムーズです。
次は、グローバルフックを用いた場合について説明しますが、
今回も長くなってしまったので、次回にまわしたいと思います。
0 件のコメント:
コメントを投稿