[python-win32] window events via SetWindowsHookExA

Antoine Martin antoine at nagafix.co.uk
Fri Sep 18 18:53:55 CEST 2009


Hi Tim,

Tim Roberts wrote:
> Antoine Martin wrote:
>> I am trying to use SetWindowsHookExA via ctypes to be notified when
>> Windows are mapped/unmapped, to get the same functionality as
>> SUBSTRUCTURE_MASK events on the root X-window (or is there a better way
>> that I have missed?)
> 
> WH_CALLWNDPROC is a bit extreme.  The equivalent to mapping and
> unmapping in the Windows world is activation, done with the WM_ACTIVATE
> and WM_DEACTIVATE messages.  You should be able to monitor those with
> WH_CBT, which is a bit lighter weight than the WH_CALLWNDPROC hooks.
Hah, ok.

> There is a problem with your code, however:
> 
> 
>> Here is the code:
>>
>> WIN_HOOK = CFUNCTYPE(c_long, c_int, c_uint, c_long)
>> def register_hook()
>>     WH_CALLWNDPROCRET = 4
>>     dll_handle = ctypes.windll.user32._handle
>>     self.call_next_hook = ctypes.windll.user32.CallNextHookEx
>>     self.hook_handle =
>> types.windll.user32.SetWindowsHookExA(WH_CALLWNDPROCRET,
>> WIN_HOOK(window_hook), dll_handle, 0)
> 
> You are telling it that the function to be called is inside of
> user32.dll.  When you install an invasive hook like this, the operating
> system actually injects that DLL into every process that owns a window. 
> Your hook function is then called in the context of those other
> processes.  That's why they tell you that most hook procedures must
> reside in a DLL.
Yes, I used "dll_handle" without really understanding it... It just
refused to register the hook otherwise, as it is a "global" one.
I'll use another technique I think, but just for my own knowledge: if I
made a DLL with my hook, how would it get loaded into the other
processes' address space? Just by calling SetWindowsHookExA()?

> In your case, the function address you gave is local to your EXE.  It
> won't exist in other processes (or it will point to random memory). 
> When the first event occurs, your callback will be called in a thread in
> some other process.  That thread gets an exception, because that address
> points into random space, and your app is terminated.
Yup!

> There used to be a great project at the University of North Carolina
> called pyAA that could do this, but it hasn't been updated past Python
> 2.4.  At this point, I do not know of a way to implement Windows hooks
> in straight Python.
Yes, I looked at that, there's a nice WindowWatcher class, but
unfortunately it is not in pure python.

Thanks a lot for the explanation.
Antoine



More information about the python-win32 mailing list