[python-win32] How can I detect when a user switches between windows?
Tim Roberts
timr at probo.com
Thu Dec 27 20:17:06 CET 2007
Assaf Tal wrote:
>
> I hope I've come to the right place :).
Didn't you ask this question on the newsgroup last night? I know I've
read it recently.
> The utility will execute a set of commands whenever the user switches
> his focus between different windows, including child windows in MDI
> applications (e.g. between two photos in Photoshop), based on the
> title of the window switched to.
> I've already figured how to retrieve an active window's title, by
> using win32gui's GetWindowText(GetForegroundWindow()). However, I'm
> still trying to figure out the best way of detecting whenever the
> focus shifts between windows. For my purposes, "shifting the focus" is
> equivalent to having the window's blue title bar become active.
> I've asked around and been given two ways of doing this, but both seem
> very unnatural:
> 1.) Using some timer, run a check every x seconds to see whether the
> window's title has changed, and act accordingly. This seems clumsy.
> 2.) Use PyHook and perhaps see when the keyboard focus has changed
> (not sure how to do that one yet, though). This seems like a decent
> solution (assuming I'll get it to work), but I can easily think of
> situations in which keyboard focus and window focus are not the same.
> For example, in many video and audio editing programs, one can switch
> between multiple open windows and still have his/her keyboard control
> the "mother application".
Windows doesn't really have the concept of "window focus". The focus
window is the one receiving UI events. When you switch between multiple
open windows as you describe, the messages all go to the message queue
for the main UI thread of the owning application. That's why the
"mother application" can still read them. It's up to the application to
decide whether to handle the messages globally, or to let a separate
window procedure handle them.
> So basically what I'm asking is: is there an elegant solution to this
> problem? Can I "bind" somehow a window-switching event, perhaps
> directly via the underlying windows API or some suitable wrapper?
> Your help is very much appreciated, and please let me know if I've
> picked the wrong group for this and there is some more suitable place
> to ask this question.
There is no elegant solution. The way to do this is to install a
Windows hook. The WH_CBT hook will allow you to intercept WM_ACTIVATE
and WM_DEACTIVATE messages, which are the messages that get sent when a
window receives or loses the focus. However, you probably won't want to
do that in Python, because this involves injecting a DLL into every
process in the system. You'll have to have some C code to make this work.
I'm not sure why the hook method seems unnatural. Window messages are
sent directly to the affected windows, which belong to a process.
Windows does not have the concept of a "global event queue". If you
want to see the messages being received by another process, you have to
make yourself part of that process by using a hook.
--
Tim Roberts, timr at probo.com
Providenza & Boekelheide, Inc.
More information about the python-win32
mailing list