gpt4 book ai didi

c# - Windows 钩子(Hook)的奇怪行为

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:59:18 25 4
gpt4 key购买 nike

我一直在寻找在操作系统(Windows XP 32 位)中激活任何窗口时在 .NET Windows 应用程序中收到通知的可能性。在 CodeProject 上,我找到了使用全局系统 Hook 的解决方案。

http://www.codeproject.com/Articles/18638/Using-Window-Messages-to-Implement-Global-System-H .

这里是这个过程的简短总结:

在非托管程序集(用 C++ 编写)中,实现了一种安装 WH_CBT 的方法。钩子(Hook)。

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;

}

在回调方法(过滤器函数)中,根据 Hook 类型将窗口消息发送到目标窗口。

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 之间有一个区别和 WH_SHELL钩子(Hook)是在使用 WH_CBT 时钩子(Hook)可以通过不调用 CallNextHookEx 来中断过滤器函数链方法。这可以解决我的问题吗?请提供帮助。

最佳答案

显然 Hook 在 outlook 的情况下不起作用 - 其他 微软产品(word,power point ...)??

但是,为什么要 Hook ?即使激活了 outlook,这个小类也能正常工作

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsMonitor
{
public class ActiveWindowChangedEventArgs : EventArgs
{
public IntPtr CurrentActiveWindow { get; private set; }
public IntPtr LastActiveWindow { get; private set; }

public ActiveWindowChangedEventArgs(IntPtr lastActiveWindow, IntPtr currentActiveWindow)
{
this.LastActiveWindow = lastActiveWindow;
this.CurrentActiveWindow = currentActiveWindow;
}
}

public delegate void ActiveWindowChangedEventHandler(object sender, ActiveWindowChangedEventArgs e);

public class ActiveWindowMonitor
{
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();

private Timer monitorTimer;

public IntPtr ActiveWindow { get; private set; }
public event ActiveWindowChangedEventHandler ActiveWindowChanged;

public ActiveWindowMonitor()
{
this.monitorTimer = new Timer();
this.monitorTimer.Tick += new EventHandler(monitorTimer_Tick);
this.monitorTimer.Interval = 10;
this.monitorTimer.Start();
}

private void monitorTimer_Tick(object sender, EventArgs e)
{
CheckActiveWindow();
}

private void CheckActiveWindow()
{
IntPtr currentActiveWindow = GetForegroundWindow();
if (this.ActiveWindow != currentActiveWindow)
{
IntPtr lastActiveWindow = this.ActiveWindow;
this.ActiveWindow = currentActiveWindow;

OnActiveWindowChanged(lastActiveWindow, this.ActiveWindow);
}
}

protected virtual void OnActiveWindowChanged(IntPtr lastActiveWindow, IntPtr currentActiveWindow)
{
ActiveWindowChangedEventHandler temp = ActiveWindowChanged;
if (temp != null)
{
temp.Invoke(this, new ActiveWindowChangedEventArgs(lastActiveWindow, currentActiveWindow));
}
}
}
}

用法

    public void InitActiveWindowMonitor()
{
WindowsMonitor.ActiveWindowMonitor monitor = new WindowsMonitor.ActiveWindowMonitor();
monitor.ActiveWindowChanged += new WindowsMonitor.ActiveWindowChangedEventHandler(monitor_ActiveWindowChanged);
}

private void monitor_ActiveWindowChanged(object sender, WindowsMonitor.ActiveWindowChangedEventArgs e)
{
//ouh a window got activated
}

关于c# - Windows 钩子(Hook)的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12115244/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com