import os import logging import win32con import win32gui from time import sleep class ToastNotifier: def show_toast(self, title, msg, icon_path=None, duration=5): message_map = {win32con.WM_DESTROY: self.on_destroy} # Register the Window class. wc = win32gui.WNDCLASS() wc.lpszClassName = "PythonTaskbar" wc.lpfnWndProc = message_map # could also specify a wndproc. classAtom = win32gui.RegisterClass(wc) self.hinst = wc.hInstance = win32gui.GetModuleHandle(None) # Create the Window. style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU self.hwnd = win32gui.CreateWindow( classAtom, "Taskbar", style, 0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, 0, 0, self.hinst, None, ) win32gui.UpdateWindow(self.hwnd) self.hicon = self._set_icon(icon_path) flags = win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP nid = (self.hwnd, 0, flags, win32con.WM_USER + 20, self.hicon, "Tooltip") # Add a new notification icon win32gui.Shell_NotifyIcon(win32gui.NIM_ADD, nid) win32gui.Shell_NotifyIcon( win32gui.NIM_MODIFY, ( self.hwnd, 0, win32gui.NIF_INFO, win32con.WM_USER + 20, self.hicon, "Balloon Tooltip", msg, 200, title, ), ) sleep(duration) win32gui.DestroyWindow(self.hwnd) win32gui.UnregisterClass(wc.lpszClassName, None) def _set_icon(self, icon_path): # icon if icon_path is not None: icon_path = os.path.realpath(icon_path) else: return None icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE try: hicon = win32gui.LoadImage( self.hinst, icon_path, win32con.IMAGE_ICON, 0, 0, icon_flags ) except Exception as e: logging.error("Some trouble with the icon ({}): {}".format(icon_path, e)) hicon = win32gui.LoadIcon(0, win32con.IDI_APPLICATION) return hicon def on_destroy(self, hwnd, msg, wparam, lparam): nid = (hwnd, 0) win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, nid) win32gui.PostQuitMessage(0) _notifier = ToastNotifier() def show_toast(title, msg, icon_path=None, duration=5): _notifier.show_toast(title, msg, icon_path=None, duration=5) if __name__ == "__main__": toaster = ToastNotifier() toaster.show_toast("Hello world", "Test")