7

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?

Elmo
  • 6,409
  • 16
  • 72
  • 140
  • Are you talking about a single browser as well as redirects..? have you searched at Request / Response and accessing headers ?? just curious as to if I am on the same page as you are.. – MethodMan Jan 06 '12 at 20:54
  • 1
    Yes, hook required. Pretty sure I already told you about WH_SHELL. – Hans Passant Jan 06 '12 at 21:01
  • 1
    possible duplicate of [Log all Windows that are Closed in Windows](http://stackoverflow.com/questions/8648386/log-all-windows-that-are-closed-in-windows) – Hans Passant Jan 06 '12 at 21:02
  • 7
    This sounds likea job for an accessibility hook. Listen for EVENT_OBJECT_NAMECHANGE. – Raymond Chen Jan 06 '12 at 21:27

2 Answers2

13

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.

BrendanMcK
  • 14,252
  • 45
  • 54
  • 1
    EVENT_OBJECT_NAMECHANGE occur a lot, it is triggered even when you move the mouse on the same tab of the same window ! is it related to what you said "possibly including child window name changes", but how to avoid that ? just ignoring the same recurrent "window titles" in the callback ? – JohnTube Feb 25 '14 at 16:09
  • 1
    If you're only interested in changes in one process, you can specify the process's ID in the `SetWindowEventHook` call, which will greatly reduce the number of events observed. – Drew Noakes Jun 21 '16 at 14:20
  • @BrendanMcK I am getting titles when switched windows, for ex. from chome > notepad > visualstudio but not getting how to implement event for tab change of chrome or document change in visualstudio. can you please help? Regards – Aniket Bhansali Oct 27 '16 at 11:06
3

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 is WH_CALLWNDPROC and just check if the message you're receiving is WM_SETTEXT and the hWnd 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.

Blindy
  • 65,249
  • 10
  • 91
  • 131
  • 2
    This will work, but isn't the easiest way. The catch with a WH_CALLWNDPROC hook is that you'll need a separate C/C++ DLL - you can't do it all in C#. (Plus you'll need separate hooks for 32 and 64-bit code, if you care about that.) SetWinEventHook will likely be a better fit here, since you can have the notification delivered back to your own process, avoiding the need for a separate DLL. – BrendanMcK Jan 11 '12 at 07:18
  • You already posted your answer, why bother with this comment? – Blindy Jan 11 '12 at 13:13
  • 6
    So that a potential future SO reader will understand how the two techniques relate to one another, or will see this caveat even if the only scan the accepted answer; a comment has better spatial locality than the separate answer. – BrendanMcK Jan 11 '12 at 14:12