Skip to content

Commit

Permalink
Added contextmanager for to automatically send WM_QUIT on CTRL+C or C…
Browse files Browse the repository at this point in the history
…TRL+Break.
  • Loading branch information
blep committed Aug 27, 2023
1 parent e89d655 commit 4455037
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 13 deletions.
1 change: 1 addition & 0 deletions win32_window_monitor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@
init_com,
run_message_loop,
post_quit_message,
post_quit_message_on_break_signal,
)
11 changes: 1 addition & 10 deletions win32_window_monitor/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,23 +57,14 @@ def on_event(self, win_event_hook_handle, event_id: int, hwnd: wintypes.HWND,


def main():
with init_com():
with init_com(), post_quit_message_on_break_signal():
# Register hook callback for all relevant event types
# Demonstrates that we can use a method as event hook callback without issue thanks
# to ctypes.
event_logger = WindowEventLogger()
win_event_proc = WinEventProcType(event_logger.on_event)
event_hook_handles = [set_win_event_hook(win_event_proc, et) for et in EVENT_TYPES.keys()]

# Install signal handler to exit the application when CTRL+C or CTRL+Break is pressed
def signal_handler(signum, frame):
# Send WM_QUIT message to exit the message loop started below
post_quit_message(0)

if platform.system() == 'Windows':
signal.signal(signal.SIGBREAK, signal_handler)
signal.signal(signal.SIGINT, signal_handler)

# Run Windows message loop until WM_QUIT message is received (send by signal handlers above).
# If you have a graphic UI, it is likely that your application already has a Windows message
# loop that should be used instead.
Expand Down
32 changes: 29 additions & 3 deletions win32_window_monitor/win32api.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import contextlib
import ctypes
from ctypes import wintypes
import logging
import signal
from ctypes import wintypes
from typing import Optional
from .ids import HookEvent, ObjectId
from typing import Union
import contextlib

from .ids import HookEvent

user32 = ctypes.windll.user32
ole32 = ctypes.windll.ole32
Expand Down Expand Up @@ -174,3 +176,27 @@ def run_message_loop():

def post_quit_message(exit_code: int = 0):
PostQuitMessage(exit_code)


@contextlib.contextmanager
def post_quit_message_on_break_signal():
"""Install signal handler to exit the application when CTRL+C or CTRL+Break is pressed.
Exiting the application is done by sending the WM_QUIT message (via post_quit_message),
which causes the Windows message loop of run_message_loop() that receives it to exit.
This is a contextmanager for use with the with statement.
"""
def signal_handler_post_quit_message(signum, stack_frame):
post_quit_message()

old_break_handler = signal.getsignal(signal.SIGBREAK)
signal.signal(signal.SIGBREAK, signal_handler_post_quit_message)
old_int_handler = signal.getsignal(signal.SIGINT)
signal.signal(signal.SIGINT, signal_handler_post_quit_message)

yield

# Restore the old signal handlers on exit
signal.signal(signal.SIGINT, old_int_handler)
signal.signal(signal.SIGBREAK, old_break_handler)

0 comments on commit 4455037

Please sign in to comment.