窗口标题更改事件
如果一个窗口(例如 Firefox)将其标题从 Firefox
更改为 Stack Overflow - Firefox
,那么我希望我的应用程序记录 Firefox 更改了其标题。
不使用钩环(EnumWindows)是否可以实现?如果只能用钩子完成,哪种类型的钩子?
If a window, for e.g. Firefox, changes its title, from Firefox
to Stack Overflow - Firefox
then I want my app to record that Firefox changed its title.
Is this possible without the use of a hook and loop (EnumWindows)? If can be only done with a hook, which type of hook?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
WinEvents 是您的最佳选择。您需要的 API 是 SetWinEventHook() - 如果您关心特定窗口,请使用 GetWindowThreadProcessId() 获取 HWND 的 threadId,然后仅侦听来自该特定线程的事件。对于窗口标题更改,您需要 EVENT_OBJECT_NAMECHANGE 事件。
您可以挂钩“上下文中”或“上下文外” - 后者是最简单的,意味着事件被传递回您自己的进程,因此您不需要单独的 DLL - 这使得可以做到这一点全部用 C# 编写;但是调用 SetWinEventHook 的线程必须有一个消息循环 (GetMessage/TranslateMessage/DispatchMessage),因为事件是在幕后使用消息形式传递的。
在 WinEvent 回调中,您需要检查 HWND 是否是您关心的,因为您将获得该目标线程上任何 UI 的名称更改,可能包括子窗口名称更改或您不关心的其他内容关心。
--
顺便说一句,您可以查看此答案以获取一些使用 WinEvents 的示例 C# 代码;它使用它们来跟踪桌面上所有窗口的前景窗口变化;但应该只需要进行一些上面概述的简单修改即可跟踪特定窗口上的名称更改。
WinEvents is the way to go here. The API you need is SetWinEventHook() - if you care about a specific window, use GetWindowThreadProcessId() to get the HWND's threadId and then listen to events only from that specific thread. For window title changes, you'll want the EVENT_OBJECT_NAMECHANGE event.
You can hook either "in context" or "out of context" - the latter is the simplest, and means the event gets delivered back to your own process, so you don't need a separate DLL - which makes it possible to do it all in C#; but the thread that calls SetWinEventHook must have a message loop (GetMessage/TranslateMessage/DispatchMessage), since the events are delivered using a form of messages behind the scenes.
In your WinEvent callback, you'll need to check that the HWND is the one you care about, since you'll get name changes for any UI on that target thread, possibly including child window name changes, or other things you don't care about.
--
By the way, you can check this answer for some sample C# code that uses WinEvents; it's using them to track foreground window changes across all windows on the desktop; but should just take a few simple modifications outlined above to track name changes on a specific window.
您将需要一个钩子(或您在问题中提到的轮询技术)。
基本上在 Windows API 中,要更改“窗口标题”(或更准确地说是窗口的文本),您需要发送 WM_SETTEXT,因此您的钩子需要拦截该消息。您需要的挂钩类型是
WH_CALLWNDPROC
,只需检查您收到的消息是否为WM_SETTEXT
并且hWnd
是应用程序的主窗口您正在查看(这样您就不会得到误报,例如应用程序尝试设置子窗口的文本)。这里需要注意的是:虽然这里的情况可能并非如此,但请注意,您看到的标题实际上可以手动绘制,而不是通过通常的 Windows API。在沿着这条路线走得太远之前,使用 Spy++ 或其他东西来看看发生了什么,你可能会浪费很多时间。
You will need a hook (or the polling technique you mentioned in your question).
Basically in the Windows API, to change the "window caption" -- or more precisely the text of a window -- you send
WM_SETTEXT
, so your hook needs to intercept that message. The hook type you need isWH_CALLWNDPROC
and just check if the message you're receiving isWM_SETTEXT
and thehWnd
is the main window for the application you're looking at (so you don't get false positives like the application trying to set the text of children windows).Small note here: While this is probably not the case here, be aware that the title you see can actually just be drawn there manually, not going through the usual Windows API. Use Spy++ or something to see what's going on before going too far down this route, you might spend a lot of time for nothing.