OS(Windows XP 32ビット)でウィンドウがアクティブになったときに、.NET Windowsアプリケーションで通知される可能性を探していました。CodeProject で、グローバル システム フックを使用して解決策を見つけました。
http://www.codeproject.com/Articles/18638/Using-Window-Messages-to-Implement-Global-System-H。
この手順の簡単な要約を次に示します。
アンマネージ アセンブリ (C++ で記述) では、WH_CBT
フックをインストールするメソッドが実装されます。
bool InitializeCbtHook(int threadID, HWND destination)
{
if (g_appInstance == NULL)
{
return false;
}
if (GetProp(GetDesktopWindow(), " HOOK_HWND_CBT") != NULL)
{
SendNotifyMessage((HWND)GetProp(GetDesktopWindow(), "HOOK_HWND_CBT"),
RegisterWindowMessage("HOOK_CBT_REPLACED"), 0, 0);
}
SetProp(GetDesktopWindow(), " HOOK_HWND_CBT", destination);
hookCbt = SetWindowsHookEx(WH_CBT, (HOOKPROC)CbtHookCallback, g_appInstance, threadID);
return hookCbt != NULL;
}
コールバック メソッド (フィルター関数) では、フック タイプ ウィンドウに応じてメッセージが宛先ウィンドウに送信されます。
static LRESULT CALLBACK CbtHookCallback(int code, WPARAM wparam, LPARAM lparam)
{
if (code >= 0)
{
UINT msg = 0;
if (code == HCBT_ACTIVATE)
msg = RegisterWindowMessage("HOOK_HCBT_ACTIVATE");
else if (code == HCBT_CREATEWND)
msg = RegisterWindowMessage("HOOK_HCBT_CREATEWND");
else if (code == HCBT_DESTROYWND)
msg = RegisterWindowMessage("HOOK_HCBT_DESTROYWND");
else if (code == HCBT_MINMAX)
msg = RegisterWindowMessage("HOOK_HCBT_MINMAX");
else if (code == HCBT_MOVESIZE)
msg = RegisterWindowMessage("HOOK_HCBT_MOVESIZE");
else if (code == HCBT_SETFOCUS)
msg = RegisterWindowMessage("HOOK_HCBT_SETFOCUS");
else if (code == HCBT_SYSCOMMAND)
msg = RegisterWindowMessage("HOOK_HCBT_SYSCOMMAND");
HWND dstWnd = (HWND)GetProp(GetDesktopWindow(), HOOK_HWND_CBT");
if (msg != 0)
SendNotifyMessage(dstWnd, msg, wparam, lparam);
}
return CallNextHookEx(hookCbt, code, wparam, lparam);
}
このアセンブリを .NET Windows アプリケーションで使用するには、次のメソッドをインポートする必要があります。
[DllImport("GlobalCbtHook.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool InitializeCbtHook (int threadID, IntPtr DestWindow);
[DllImport("GlobalCbtHook.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void UninitializeCbtHook(int hookType);
InitializeCbtHook
から受信したメッセージを呼び出した後、次のGlobalCbtHook.dll
ように処理できます。
protected override void WndProc(ref Message msg)
を呼び出して、メッセージをアセンブリとアプリケーションの両方に登録する必要があります
RegisterWindowMessage
。
[DllImport("user32.dll")]
private static extern int RegisterWindowMessage(string lpString);
この実装は正常に機能します。しかし、ほとんどの場合、Microsoft Office Outlook をアクティブ化すると、Outlook を最小化するか他のウィンドウをアクティブ化した後で、.NET アプリケーションがアクティブ化イベントを受け取ります。最初は、.NET ラッパーが問題の原因であると考えていました。しかし、上記のリンクのソースを使用した後、同じ動作を認識できました。私の実際の回避策は、WH_SHELL
フックを使用することです。WH_CBT
とフックの違いの 1 つは、WH_SHELL
フックを使用すると、メソッドWH_CBT
を呼び出さないことでフィルター関数チェーンを中断できることです。CallNextHookEx
これは私の問題で役割を果たすことができますか? 助けてください。