我一直在寻找一种可能性,在.NET Windows应用程序时,在操作系统(Windows XP 32位)被激活的任何窗口通知。 在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中我的.NET应用程序接收激活事件后,我尽量减少Outlook或激活其他窗口。 起初我还以为我的.NET包装是问题的原因。 但我用从上面的链接的来源后,我可以确认的相同的行为。 我其实解决方法是使用WH_SHELL
钩。 我知道之间的一个差WH_CBT
和WH_SHELL
当使用钩是WH_CBT
钩有可能通过不调用中断滤波器函数链CallNextHookEx
方法。 难道这发挥我的问题的作用? 请提供帮助。