使用 WinXP。我需要做的(在 VB 或 c# 中首选)是检测另一个(封闭源代码)程序何时在托盘中显示通知气球 - 并获取详细信息。任何帮助,将不胜感激。谢谢
3 回答
在类似的情况下,我使用 Microsoft 工具 Spy++ 来获取窗口信息,然后使用 pinvoke 调用FindWindow
来检测窗口何时存在。
我没有尝试使用通知气球,但我想一个 pinvoke 调用GetText
会检索内容。
我认为您需要使用 pinvoke 从 .net 语言执行此操作。
在我现在使用的系统(Vista Business SP2)上,气球窗口似乎总是有窗口类#32769(为桌面窗口保留)和窗口样式位 TTS_BALLOON 设置。
以下方法可能有效:通过创建一个临时通知气球、获取其 hWnd 并在删除之前调用GetParent()来确定所有通知气球的父窗口。然后,您可以定期轮询此父 hwnd 的子代(使用EnumWindows()或FindWindowEx())以查找具有所需类和样式的窗口。
这对我来说似乎非常不可移植,并且可能需要在各种平台上进行大量测试。
pinvoke.net和 spy++ 可能有用。
祝你好运!
您肯定需要使用 Win API 调用来实现这一点。如果这是您唯一想做的事情,最好直接使用 C 或 C++,这样您就不必为 C# 或 VB 进行大量平台调用。
由于andyjohnson 确定所有通知气球的窗口类是 #32769,并且它们具有TTS_BALLOON
样式集,因此您可以使用CBT 挂钩(如果您不熟悉 Win32 挂钩,您可能需要阅读它们),每当创建窗口时获取回调,并检查该类和具有该样式的窗口。
不过,我不确定是否为第二个和后续弹出窗口创建了一个新的气球窗口,或者是否只是隐藏并重新显示了相同的气球窗口。如果是这种情况,您可能需要一个CallWndProc 挂钩来获取WM_SHOWWINDOW
消息。
编辑:
我应该提一下,我提到的钩子不能在 .NET 中实现。除了低级键盘和鼠标钩子外,全局系统钩子必须在本机(非托管)DLL 中实现。Windows 会将此 DLL 加载到其他进程中,如果托管 DLL 加载到未加载 .NET CLR 的进程中,它将使该进程崩溃。(即使加载了 CLR,它也可能位于不同的地址,也会导致崩溃。)
因此,您必须在本机(非托管)DLL 中构建您的挂钩。可以从这里连接到托管应用程序,例如Michael Kennedy 在 Code Project 上所做的,但要正确完成并处理我上面提到的钩子类型,您需要使用进程间通信,这是一个步骤迈克尔肯尼迪被排除在外。总而言之,就您所描述的目的而言,使用本机代码构建整个事物可能会更容易。