I want to get the handle of every new Dialog which pops up from a specific application.
I understand I should set a hook with SetWinEventHook which is in user32.dll
in windows, but I don't know how to do that in python. Would you give me an example ?
Asked
Active
Viewed 3,474 times
10

kissgyorgy
- 2,947
- 2
- 32
- 54
-
You might find the [pyHook](http://sourceforge.net/apps/mediawiki/pyhook/index.php?title=Main_Page) python wrapper useful. – martineau Apr 06 '13 at 12:44
-
it is only useful for mouse and keyboard events and the main logic is hidden in a .pyd file :( – kissgyorgy Apr 06 '13 at 23:39
-
1PyHook is open-source, so you can look at the source code for an example. There are others out there, like [pyconsole](http://code.google.com/p/pyconsole/source/browse/trunk/pyconsole.py?r=5) you can also look at, just use [Google](https://www.google.com/search?hl=en&as_q=python&as_epq=SetWinEventHook&as_oq=&as_eq=&as_nlo=&as_nhi=&lr=&cr=&as_qdr=all&as_sitesearch=&as_occt=any&safe=images&tbs=&as_filetype=&as_rights=). Unless you write or use a C extension module, you're likely going to need to learn about and use several of the built-in `win32xxx` modules and `ctypes.windll.user32`. – martineau Apr 07 '13 at 17:19
1 Answers
13
Here's a very simple example that prints to the console the window text for each dialog that is opened:
import sys
import time
import ctypes
import ctypes.wintypes
EVENT_SYSTEM_DIALOGSTART = 0x0010
WINEVENT_OUTOFCONTEXT = 0x0000
user32 = ctypes.windll.user32
ole32 = ctypes.windll.ole32
ole32.CoInitialize(0)
WinEventProcType = ctypes.WINFUNCTYPE(
None,
ctypes.wintypes.HANDLE,
ctypes.wintypes.DWORD,
ctypes.wintypes.HWND,
ctypes.wintypes.LONG,
ctypes.wintypes.LONG,
ctypes.wintypes.DWORD,
ctypes.wintypes.DWORD
)
def callback(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime):
length = user32.GetWindowTextLengthA(hwnd)
buff = ctypes.create_string_buffer(length + 1)
user32.GetWindowTextA(hwnd, buff, length + 1)
print buff.value
WinEventProc = WinEventProcType(callback)
user32.SetWinEventHook.restype = ctypes.wintypes.HANDLE
hook = user32.SetWinEventHook(
EVENT_SYSTEM_DIALOGSTART,
EVENT_SYSTEM_DIALOGSTART,
0,
WinEventProc,
0,
0,
WINEVENT_OUTOFCONTEXT
)
if hook == 0:
print 'SetWinEventHook failed'
sys.exit(1)
msg = ctypes.wintypes.MSG()
while user32.GetMessageW(ctypes.byref(msg), 0, 0, 0) != 0:
user32.TranslateMessageW(msg)
user32.DispatchMessageW(msg)
user32.UnhookWinEvent(hook)
ole32.CoUninitialize()

David Heffernan
- 601,492
- 42
- 1,072
- 1,490
-
nice and clean! Thank you ! One last question: what happens if I don't `UnhookWinEvent` (for example, my app crashes or something) – kissgyorgy Apr 09 '13 at 12:08
-
1The system will clean it up for you. If you need the hook to be active for the entire duration of the process, then you don't need to bother calling `UnhookWinEvent` or `CoUninitialize`. – David Heffernan Apr 09 '13 at 12:09
-
-
1
-
1@HellOfACode Replace EVENT_SYSTEM_DIALOGSTART, with EVENT_OBJECT_FOCUS where EVENT_OBJECT_FOCUS = 0x8005. – Carel Aug 02 '15 at 15:24
-
1See [here](https://msdn.microsoft.com/en-us/library/windows/desktop/dd318066(v=vs.85).aspx) for various values for the min/max arguments. – Carel Aug 02 '15 at 16:18
-
is there a way to listen for hotkeys, specifically Ctrl+C in order to kill the console? – faustus Mar 16 '22 at 11:40