diff --git a/lib/pystray/_base.py b/lib/pystray/_base.py index 8b8c754..30a8c06 100644 --- a/lib/pystray/_base.py +++ b/lib/pystray/_base.py @@ -66,6 +66,10 @@ class Icon(object): #: notification. HAS_NOTIFICATION = True + #: Whether this particular implementation forces displaying a + #: large notification icon + FORCE_LARGE_NOTIFICATION_ICON = False + def __init__( self, name, icon=None, title=None, menu=None): self._name = name diff --git a/lib/pystray/_util/win32.py b/lib/pystray/_util/win32.py index e2d7eb7..ae31eaa 100644 --- a/lib/pystray/_util/win32.py +++ b/lib/pystray/_util/win32.py @@ -74,6 +74,12 @@ NIF_REALTIME = 0x00000040 NIF_SHOWTIP = 0x00000080 +NIIF_NONE = 0x00000000 +NIIF_ICON_MASK = 0x0000000F + +SM_CXICON = 11 +SM_CYICON = 12 + NIM_ADD = 0x00000000 NIM_MODIFY = 0x00000001 NIM_DELETE = 0x00000002 @@ -271,6 +277,18 @@ def _err(result, func, arguments): InsertMenuItem.restype = wintypes.BOOL InsertMenuItem.errcheck = _err +FindWindow = windll.user32.FindWindowW +FindWindow.argtypes = ( + wintypes.LPCWSTR, wintypes.LPCWSTR) + +GetDpiForWindow = windll.user32.GetDpiForWindow +GetDpiForWindow.argtypes = ( + wintypes.HWND, ) + +GetSystemMetricsForDpi = windll.user32.GetSystemMetricsForDpi +GetSystemMetricsForDpi.argtypes = ( + wintypes.INT, wintypes.UINT) + LoadImage = windll.user32.LoadImageW LoadImage.argtypes = ( wintypes.HINSTANCE, wintypes.LPCWSTR, wintypes.UINT, wintypes.INT, diff --git a/lib/pystray/_win32.py b/lib/pystray/_win32.py index 23d039c..160b167 100644 --- a/lib/pystray/_win32.py +++ b/lib/pystray/_win32.py @@ -28,6 +28,9 @@ class Icon(_base.Icon): _HWND_TO_ICON = {} + #: Force large notification icon size on loading the file + FORCE_LARGE_NOTIFICATION_ICON = False + def __init__(self, *args, **kwargs): super(Icon, self).__init__(*args, **kwargs) @@ -97,7 +100,8 @@ def _notify(self, message, title=None): win32.NIM_MODIFY, win32.NIF_INFO, szInfo=message, - szInfoTitle=title or self.title or '') + szInfoTitle=title or self.title or '', + dwInfoFlags=win32.NIIF_ICON_MASK if Icon.FORCE_LARGE_NOTIFICATION_ICON else win32.NIIF_NONE) def _remove_notification(self): self._message( @@ -336,19 +340,26 @@ def _release_icon(self): win32.DestroyIcon(self._icon_handle) self._icon_handle = None + def _size_for_current_dpi(self): + hwnd = win32.FindWindow("Shell_TrayWnd", "") + dpi = win32.GetDpiForWindow(hwnd) + w = win32.GetSystemMetricsForDpi(win32.SM_CXICON, dpi) + h = win32.GetSystemMetricsForDpi(win32.SM_CYICON, dpi) + return w, h + def _assert_icon_handle(self): """Asserts that the cached icon handle exists. """ if self._icon_handle: return - + w, h = self._size_for_current_dpi() with serialized_image(self.icon, 'ICO') as icon_path: self._icon_handle = win32.LoadImage( None, icon_path, win32.IMAGE_ICON, - 0, - 0, + w, + h, win32.LR_DEFAULTSIZE | win32.LR_LOADFROMFILE) def _register_class(self):