【问题标题】:Window Title Changed Event窗口标题更改事件
【发布时间】:2012-02-04 13:36:23
【问题描述】:

如果是一个窗口,例如Firefox,将其标题从 Firefox 更改为 Stack Overflow - Firefox 然后我希望我的应用程序记录 Firefox 更改了其标题。

如果不使用钩子和循环(EnumWindows),这可能吗?如果只能用钩子来做,那是什么钩子呢?

【问题讨论】:

  • 您是在谈论单个浏览器以及重定向..?您是否在请求/响应中搜索并访问标题?只是好奇我是否和你在同一页上..
  • 是的,需要挂钩。很确定我已经告诉过你 WH_SHELL。
  • 这听起来像是一个辅助钩子的工作。监听 EVENT_OBJECT_NAMECHANGE。

标签: c# .net vb.net winapi hook


【解决方案1】:

您将需要一个钩子(或您在问题中提到的轮询技术)。

基本上在 Windows API 中,要更改“窗口标题”——或者更准确地说是窗口的文本——你发送WM_SETTEXT,所以你的钩子需要拦截那个消息。您需要的钩子类型是 WH_CALLWNDPROC 并且只需检查您收到的消息是否是 WM_SETTEXT 并且 hWnd 是您正在查看的应用程序的主窗口(这样您就不会得到像这样的误报应用程序试图设置子窗口的文本)。

这里的小提示:虽然这里可能不是这种情况,但请注意,您看到的标题实际上可以手动绘制,而不是通过通常的 Windows API。在沿着这条路线走得太远之前,使用 Spy++ 或其他东西看看发生了什么,你可能会浪费很多时间。

【讨论】:

  • 这可行,但不是最简单的方法。使用 WH_CALLWNDPROC 钩子的问题是您需要一个单独的 C/C++ DLL - 您不能在 C# 中完成所有操作。 (另外,如果您关心的话,您需要单独的 32 位和 64 位代码挂钩。)SetWinEventHook 可能更适合这里,因为您可以将通知传递回您自己的进程,从而避免需要单独的 DLL。
  • 你已经发布了你的答案,为什么还要麻烦这个评论?
  • 这样潜在的未来 SO 读者将了解这两种技术如何相互关联,或者即使仅扫描已接受的答案也会看到此警告;评论比单独的答案具有更好的空间局部性。
【解决方案2】:

WinEvents 是这里的方法。您需要的 API 是 SetWinEventHook() - 如果您关心特定窗口,请使用 GetWindowThreadProcessId() 获取 HWND 的 threadId,然后仅侦听来自该特定线程的事件。对于窗口标题更改,您需要 EVENT_OBJECT_NAMECHANGE 事件。

您可以“在上下文中”或“在上下文之外”挂钩 - 后者是最简单的,这意味着事件被传递回您自己的进程,因此您不需要单独的 DLL - 这使得它成为可能全部用 C# 完成;但是调用 SetWinEventHook 的线程必须有一个消息循环(GetMessage/TranslateMessage/DispatchMessage),因为事件是在幕后使用消息形式传递的。

在您的 WinEvent 回调中,您需要检查 HWND 是否是您关心的,因为您将获得该目标线程上任何 UI 的名称更改,可能包括子窗口名称更改或其他您不在乎。

--

顺便说一句,您可以查看this answer 以获得一些使用 WinEvents 的示例 C# 代码;它使用它们来跟踪桌面上所有窗口的前台窗口更改;但应该只需要进行上面概述的一些简单修改即可跟踪特定窗口上的名称更改。

【讨论】:

  • EVENT_OBJECT_NAMECHANGE 经常发生,即使您在同一窗口的同一选项卡上移动鼠标也会触发它!是否与您所说的“可能包括子窗口名称更改”有关,但是如何避免呢?只是忽略回调中相同的经常性“窗口标题”?
  • 如果只对某个进程的变化感兴趣,可以在SetWindowEventHook调用中指定进程的ID,这样会大大减少观察到的事件数。
  • @BrendanMcK 我在切换窗口时获得标题,例如。从 chome > notepad > visualstudio 但没有得到如何实现事件以更改 chrome 的选项卡或在 visualstudio 中更改文档。你能帮忙吗?问候
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-08
  • 2014-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多