-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathwin32.py
More file actions
128 lines (106 loc) · 4.43 KB
/
Copy pathwin32.py
File metadata and controls
128 lines (106 loc) · 4.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# Copyright 2016-2018 Dirk Thomas
# Licensed under the Apache License, Version 2.0
import sys
import time
from colcon_core.logging import colcon_logger
from colcon_core.plugin_system import satisfies_version
from colcon_core.plugin_system import SkipExtensionException
from colcon_notification.desktop_notification \
import DesktopNotificationExtensionPoint
logger = colcon_logger.getChild(__name__)
class Win32DesktopNotification(DesktopNotificationExtensionPoint):
"""Use the Windows API to show notifications."""
def __init__(self): # noqa: D107
super().__init__()
satisfies_version(
DesktopNotificationExtensionPoint.EXTENSION_POINT_VERSION, '^1.0')
if sys.platform != 'win32':
raise SkipExtensionException('Not used on non-Windows systems')
self._initialized = False
self._last_notification = None
def notify(self, *, title, message, icon_path=None): # noqa: D102
NotificationWindow(title, message, icon_path=icon_path)
class NotificationWindow:
"""Notification windows using the Win32 API."""
def __init__(self, title, message, icon_path=None): # noqa: D107
try:
import win32con
except ImportError as e: # noqa: F841
logger.debug(
'Failed to import win32con: {e}'.format_map(locals()))
return
try:
import win32gui
except ImportError as e: # noqa: F841
logger.debug(
'Failed to import win32gui: {e}'.format_map(locals()))
return
wc, class_atom = NotificationWindow._create_window_class()
# create the window
hwnd = win32gui.CreateWindow(
NotificationWindow._class_atom,
'Colcon notification', # window class name
win32con.WS_OVERLAPPED | win32con.WS_SYSMENU, # style
0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT,
0, 0, NotificationWindow._wc.hInstance, None)
win32gui.UpdateWindow(hwnd)
# load icon image
try:
if icon_path is None:
# use fall back
raise Exception()
hicon = win32gui.LoadImage(
NotificationWindow._wc.hInstance, icon_path,
win32con.IMAGE_ICON, 0, 0,
win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE, # flags
)
except Exception: # noqa: B902
hicon = win32gui.LoadIcon(0, win32con.IDI_APPLICATION)
# show the notification
flags = win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP
nid = (hwnd, 0, flags, win32con.WM_USER + 20, hicon, 'tooltip')
try:
win32gui.Shell_NotifyIcon(
win32gui.NIM_ADD, nid)
win32gui.Shell_NotifyIcon(
win32gui.NIM_MODIFY, (
hwnd, 0, win32gui.NIF_INFO, win32con.WM_USER + 20, hicon,
'Balloon tooltip', message, 200, title))
except Exception as e: # noqa: F841
logger.debug(
'Failed to show the notification: {e}'.format_map(locals()))
else:
# wait a while before destroying the window
time.sleep(5)
finally:
win32gui.DestroyWindow(hwnd)
_wc = None
_class_atom = None
@staticmethod
def _create_window_class(): # noqa: D102
import win32api
import win32con
import win32gui
# register the window class once
if NotificationWindow._wc is None:
NotificationWindow._wc = win32gui.WNDCLASS()
NotificationWindow._wc.hInstance = win32api.GetModuleHandle(None)
NotificationWindow._wc.lpszClassName = 'ColconTaskbar'
NotificationWindow._wc.lpfnWndProc = {
win32con.WM_DESTROY: NotificationWindow._on_destroy,
}
NotificationWindow._class_atom = win32gui.RegisterClass(
NotificationWindow._wc)
return (NotificationWindow._wc, NotificationWindow._class_atom)
@staticmethod
def _on_destroy(hwnd, msg, wparam, lparam): # noqa: D102
import win32gui
nid = (hwnd, 0)
try:
win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, nid)
except Exception as e: # noqa: F841
logger.debug(
'Failed to delete the notification handle: {e}'
.format_map(locals()))
win32gui.PostQuitMessage(0)
return 0