Example #1
0
 def __init__(self):
     # Register window class; it's okay to do this multiple times
     wc = WNDCLASS()
     wc.lpszClassName = "ServoTaskbarNotification"
     wc.lpfnWndProc = {win32con.WM_DESTROY: self.OnDestroy}
     self.classAtom = RegisterClass(wc)
     self.hinst = wc.hInstance = GetModuleHandle(None)
Example #2
0
def show_windows_notification(title, msg, icon_path):
    global tool_window, tool_icon
    from win32api import GetModuleHandle
    from win32con import (
        CW_USEDEFAULT,
        IMAGE_ICON,
        LR_DEFAULTSIZE,
        LR_LOADFROMFILE,
        WM_USER,
        WS_OVERLAPPED,
        WS_SYSMENU,
    )
    from win32gui import (
        NIF_ICON,
        NIF_INFO,
        NIF_MESSAGE,
        NIF_TIP,
        NIM_ADD,
        NIM_MODIFY,
        WNDCLASS,
        CreateWindow,
        LoadImage,
        RegisterClass,
        Shell_NotifyIcon,
        UpdateWindow,
    )

    wc = WNDCLASS()
    hinst = wc.hInstance = GetModuleHandle(None)
    wc.lpszClassName = "FastFlix"
    if not tool_window:
        tool_window = CreateWindow(
            RegisterClass(wc),
            "Taskbar",
            WS_OVERLAPPED | WS_SYSMENU,
            0,
            0,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            0,
            0,
            hinst,
            None,
        )
        UpdateWindow(tool_window)

        icon_flags = LR_LOADFROMFILE | LR_DEFAULTSIZE
        tool_icon = LoadImage(hinst, icon_path, IMAGE_ICON, 0, 0, icon_flags)

        flags = NIF_ICON | NIF_MESSAGE | NIF_TIP
        nid = (tool_window, 0, flags, WM_USER + 20, tool_icon,
               "FastFlix Notifications")
        Shell_NotifyIcon(NIM_ADD, nid)

    Shell_NotifyIcon(NIM_MODIFY,
                     (tool_window, 0, NIF_INFO, WM_USER + 20, tool_icon,
                      "Balloon Tooltip", msg, 200, title, 4))
Example #3
0
 def __init__(self):
     # Register window class; it's okay to do this multiple times
     wc = WNDCLASS()
     wc.lpszClassName = 'ServoTaskbarNotification'
     wc.lpfnWndProc = {
         win32con.WM_DESTROY: self.OnDestroy,
     }
     self.classAtom = RegisterClass(wc)
     self.hinst = wc.hInstance = GetModuleHandle(None)
    def __init__(self):
        """Initialize."""
        message_map = {WM_DESTROY: self.on_destroy, }

        # Register the window class.
        wc = WNDCLASS()
        self.hinst = wc.hInstance = GetModuleHandle(None)
        wc.lpszClassName = str("PythonTaskbar")  # must be a string
        wc.lpfnWndProc = message_map  # could also specify a wndproc.
        self.classAtom = RegisterClass(wc)
    def __init__(self):
        """Initialize."""
        message_map = {WM_DESTROY: self.on_destroy}

        # Register the window class.
        wc = WNDCLASS()
        self.hinst = wc.hInstance = GetModuleHandle(None)
        wc.lpszClassName = str("PythonTaskbar")  # must be a string
        wc.lpfnWndProc = message_map  # could also specify a wndproc.
        self.classAtom = RegisterClass(wc)
Example #6
0
    def __init__(self, message, title):

        message_map = {win32con.WM_DESTROY: self.OnDestroy}
        # Register the Window class.
        wc = WNDCLASS()
        hinst = wc.hInstance = GetModuleHandle(None)
        wc.lpszClassName = "PythonTaskbar"
        wc.lpfnWndProc = message_map  # could also specify a wndproc.
        classAtom = RegisterClass(wc)
        # Create the Window.
        style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU
        self.hwnd = CreateWindow(
            classAtom,
            "Taskbar",
            style,
            0,
            0,
            win32con.CW_USEDEFAULT,
            win32con.CW_USEDEFAULT,
            0,
            0,
            hinst,
            None,
        )
        UpdateWindow(self.hwnd)
        iconPathName = os.path.abspath(
            os.path.join(sys.path[0], "balloontip.ico"))
        icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE
        try:
            hicon = LoadImage(hinst, iconPathName, win32con.IMAGE_ICON, 0, 0,
                              icon_flags)
        except:
            hicon = LoadIcon(0, win32con.IDI_APPLICATION)

        flags = NIF_ICON | NIF_MESSAGE | NIF_TIP
        nid = (self.hwnd, 0, flags, win32con.WM_USER + 20, hicon, "tooltip")
        Shell_NotifyIcon(NIM_ADD, nid)
        Shell_NotifyIcon(
            NIM_MODIFY,
            (
                self.hwnd,
                0,
                NIF_INFO,
                win32con.WM_USER + 20,
                hicon,
                "Balloon  tooltip",
                message,
                200,
                title,
            ),
        )
        time.sleep(10)
        DestroyWindow(self.hwnd)
        UnregisterClass(classAtom, hinst)
Example #7
0
    def _show_toast(self, title, msg, duration):
        message_map = {
            WM_DESTROY: self.on_destroy,
        }
        self.wc = WNDCLASS()
        self.hinst = self.wc.hInstance = GetModuleHandle(None)
        self.wc.lpszClassName = str("PythonTaskbar")
        self.wc.lpfnWndProc = message_map
        try:
            self.classAtom = RegisterClass(self.wc)
        except:
            pass
        style = WS_OVERLAPPED | WS_SYSMENU
        self.hwnd = CreateWindow(self.classAtom, "Taskbar", style, 0, 0,
                                 CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
                                 self.hinst, None)
        UpdateWindow(self.hwnd)

        hicon = LoadIcon(0, IDI_APPLICATION)
        flags = NIF_ICON | NIF_MESSAGE | NIF_TIP
        nid = (self.hwnd, 0, flags, WM_USER + 20, hicon, "Tooltip")
        Shell_NotifyIcon(NIM_ADD, nid)
        Shell_NotifyIcon(NIM_MODIFY,
                         (self.hwnd, 0, NIF_INFO, WM_USER + 20, hicon,
                          "Balloon Tooltip", msg, 200, title))
        sleep(duration)
        DestroyWindow(self.hwnd)
        UnregisterClass(self.wc.lpszClassName, None)
        return None
Example #8
0
    def __init__(self):

        # List of all notifications. Each notification is represented by its ID (key) and thread (value).
        self._notifications = {}

        # Notification ID counter
        self._current_id = 0

        self.logger = logging.getLogger("zroya")

        # Event mapping. Keys is event type and value callback function.
        self._event_map = {
            WM_DESTROY: self.quit,
        }

        # Create window
        self._window_class = WNDCLASS()
        self._window_class.lpszClassName = str("Notification")
        self._window_class.lpfnWndProc = self._eventLoop
        self._class = RegisterClass(self._window_class)
        self._handle = GetModuleHandle(None)

        self._window = CreateWindow(self._class, "Notification", WS_OVERLAPPED | WS_SYSMENU,
                                    0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, self._handle, None
                                    )

        # Draw window
        UpdateWindow(self._window)

        self.logger.info("NotificationCenter created.")
Example #9
0
    def windows_notify(self, title, message, config):
        config = self.prepare_config(config)
        try:
            from win32api import GetModuleHandle, PostQuitMessage
            from win32con import (CW_USEDEFAULT, IMAGE_ICON, IDI_APPLICATION,
                                  LR_DEFAULTSIZE, LR_LOADFROMFILE, WM_DESTROY,
                                  WS_OVERLAPPED, WS_SYSMENU, WM_USER)
            from win32gui import (CreateWindow, DestroyWindow, LoadIcon,
                                  LoadImage, NIF_ICON, NIF_INFO, NIF_MESSAGE,
                                  NIF_TIP, NIM_ADD, NIM_DELETE, NIM_MODIFY,
                                  RegisterClass, Shell_NotifyIcon,
                                  UpdateWindow, WNDCLASS)
        except ImportError:
            raise DependencyError(
                __name__, 'pypiwin32',
                'pywin32 module is required for desktop notifications on '
                'windows. You can install it with `pip install pypiwin32`')

        # Register the window class.
        wc = WNDCLASS()
        hinst = wc.hInstance = GetModuleHandle(None)
        wc.lpszClassName = "FlexGetTaskbar"
        if not self.windows_classAtom:
            self.windows_classAtom = RegisterClass(wc)
        style = WS_OVERLAPPED | WS_SYSMENU
        hwnd = CreateWindow(self.windows_classAtom, "Taskbar", style, 0, 0,
                            CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hinst, None)
        UpdateWindow(hwnd)

        hicon = LoadIcon(0, IDI_APPLICATION)
        # Hackily grab the icon from the webui if possible
        icon_flags = LR_LOADFROMFILE | LR_DEFAULTSIZE
        try:
            import flexget.ui
            icon_path = os.path.join(flexget.ui.__path__[0], 'src',
                                     'favicon.ico')
            hicon = LoadImage(hinst, icon_path, IMAGE_ICON, 0, 0, icon_flags)
        except Exception as e:
            log.debug('Error trying to get flexget icon from webui folder: %s',
                      e)

        # Taskbar icon
        flags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO
        nid = (hwnd, 0, flags, WM_USER + 20, hicon, "FlexGet Notification",
               message, config['timeout'] * 1000, title)
        Shell_NotifyIcon(NIM_ADD, nid)
Example #10
0
    def show_toast(self,
                   title="Notification",
                   msg="Here comes the message",
                   icon_path=None,
                   duration=5):
        """Notification settings.

        :title: notification title
        :msg: notification message
        :icon_path: path to the .ico file to custom notification
        :duration: delay in seconds before notification self-destruction
        """
        message_map = {
            WM_DESTROY: self.on_destroy,
        }

        # Register the window class.
        self.wc = WNDCLASS()
        self.hinst = self.wc.hInstance = GetModuleHandle(None)
        self.wc.lpszClassName = str("PythonTaskbar")  # must be a string
        self.wc.lpfnWndProc = message_map  # could also specify a wndproc.
        try:
            self.classAtom = RegisterClass(self.wc)
        except:
            pass  #not sure of this
        style = WS_OVERLAPPED | WS_SYSMENU
        self.hwnd = CreateWindow(self.classAtom, "Taskbar", style, 0, 0,
                                 CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
                                 self.hinst, None)
        UpdateWindow(self.hwnd)

        # icon
        if icon_path is not None:
            icon_path = path.realpath(icon_path)
        else:
            icon_path = resource_filename(Requirement.parse("win10toast"),
                                          "win10toast/data/python.ico")
        icon_flags = LR_LOADFROMFILE | LR_DEFAULTSIZE
        try:
            hicon = LoadImage(self.hinst, icon_path, IMAGE_ICON, 0, 0,
                              icon_flags)
        except Exception as e:
            logging.error("Some trouble with the icon ({}): {}".format(
                icon_path, e))
            hicon = LoadIcon(0, IDI_APPLICATION)

        # Taskbar icon
        flags = NIF_ICON | NIF_MESSAGE | NIF_TIP
        nid = (self.hwnd, 0, flags, WM_USER + 20, hicon, "Tooltip")
        Shell_NotifyIcon(NIM_ADD, nid)
        Shell_NotifyIcon(NIM_MODIFY,
                         (self.hwnd, 0, NIF_INFO, WM_USER + 20, hicon,
                          "Balloon Tooltip", msg, 200, title))
        # take a rest then destroy
        sleep(duration)
        DestroyWindow(self.hwnd)
        UnregisterClass(self.wc.lpszClassName, None)
        return None
Example #11
0
    def _show_toast(self, title, msg, icon_path, duration, callback_on_click):
        """Notification settings.
        :title: notification title
        :msg: notification message
        :icon_path: path to the .ico file to custom notification
        :duration: delay in seconds before notification self-destruction, None for no-self-destruction
        """

        # Register the window class.
        self.wc = WNDCLASS()
        self.hinst = self.wc.hInstance = GetModuleHandle(None)
        self.wc.lpszClassName = str(self)  # must be a string

        # callback_on_click = self._destroy_wrap(callback_on_click)
        self.wc.lpfnWndProc = self._decorator(
            self.wnd_proc,
            callback_on_click)  # could instead specify simple mapping
        try:
            self.classAtom = RegisterClass(self.wc)
        except Exception as e:
            logging.error("Some trouble with classAtom ({})".format(e))
        style = WS_OVERLAPPED | WS_SYSMENU
        self.hwnd = CreateWindow(self.classAtom, "Taskbar", style, 0, 0,
                                 CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
                                 self.hinst, None)
        UpdateWindow(self.hwnd)

        # icon
        if icon_path is not None:
            icon_path = path.realpath(icon_path)
        else:
            icon_path = resource_filename(Requirement.parse("win10toast"),
                                          "win10toast/data/python.ico")
        icon_flags = LR_LOADFROMFILE | LR_DEFAULTSIZE
        try:
            hicon = LoadImage(self.hinst, icon_path, IMAGE_ICON, 0, 0,
                              icon_flags)
        except Exception as e:
            logging.error("Some trouble with the icon ({}): {}".format(
                icon_path, e))
            hicon = LoadIcon(0, IDI_APPLICATION)

        # Taskbar icon
        flags = NIF_ICON | NIF_MESSAGE | NIF_TIP
        nid = (self.hwnd, 0, flags, WM_USER + 20, hicon, "Tooltip")
        Shell_NotifyIcon(NIM_ADD, nid)
        Shell_NotifyIcon(NIM_MODIFY,
                         (self.hwnd, 0, NIF_INFO, WM_USER + 20, hicon,
                          "Balloon Tooltip", msg, 200, title))
        PumpMessages()
        # take a rest then destroy
        if duration is not None and duration > 0:
            sleep(duration)
            self._destroy_window()

        return None
Example #12
0
 def __init__(self, auto_destroy=True):
     """Initialize."""
     self._thread = None
     self.wc = WNDCLASS()
     self.hinst = self.wc.hInstance = GetModuleHandle(None)
     self.wc.lpszClassName = str("PythonTaskbar")  # must be a string
     if auto_destroy:
         # could also specify a wndproc.
         self.wc.lpfnWndProc = {
             WM_DESTROY: self.on_destroy,
         }
Example #13
0
 def __init__(self, icon_path, msg_q):
     """Initialize."""
     self.visible = 0
     self.log = []
     self._thread = None
     self.msg_q = msg_q
     self.message_box = Mbox()
     message_map = {
         WM_DESTROY: self.onDestroy,
         WM_USER + 20: self.onTaskbarNotify,
     }
     wc = WNDCLASS()
     hinst = wc.hInstance = GetModuleHandle(None)
     icon_flags = LR_LOADFROMFILE | LR_DEFAULTSIZE
     try:
         self.hicon = LoadImage(hinst, os.path.realpath(icon_path),
                                IMAGE_ICON, 0, 0, icon_flags)
     except Exception as e:
         print(str(e))
         self.hicon = LoadIcon(0, IDI_APPLICATION)
     wc.lpszClassName = str("Trustbase_notification")  #lol
     wc.style = CS_VREDRAW | CS_HREDRAW
     #wc.hCursor = win32gui.LoadCursor( 0, win32con.IDC_ARROW )
     wc.hbrBackground = COLOR_WINDOW
     wc.lpfnWndProc = message_map  # could also specify a wndproc.
     classAtom = RegisterClass(wc)
     # Create the Window.
     style = WS_OVERLAPPED | WS_SYSMENU
     self.hwnd = CreateWindow( classAtom, "MITM_alert", style, \
                 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, \
                 0, 0, hinst, None)
     UpdateWindow(self.hwnd)
     self.notification_id = 1
     self.show()
Example #14
0
    def windows_notify(self, title, message, config):
        config = self.prepare_config(config)
        try:
            from win32api import GetModuleHandle, PostQuitMessage
            from win32con import (CW_USEDEFAULT, IMAGE_ICON, IDI_APPLICATION, LR_DEFAULTSIZE, LR_LOADFROMFILE,
                                  WM_DESTROY, WS_OVERLAPPED, WS_SYSMENU, WM_USER)
            from win32gui import (CreateWindow, DestroyWindow, LoadIcon, LoadImage, NIF_ICON, NIF_INFO, NIF_MESSAGE,
                                  NIF_TIP, NIM_ADD, NIM_DELETE, NIM_MODIFY, RegisterClass, Shell_NotifyIcon,
                                  UpdateWindow, WNDCLASS)
        except ImportError:
            raise DependencyError(plugin_name, 'pypiwin32', 'pywin32 module is required for desktop notifications on '
                                                         'windows. You can install it with `pip install pypiwin32`')

        # Register the window class.
        wc = WNDCLASS()
        hinst = wc.hInstance = GetModuleHandle(None)
        wc.lpszClassName = "FlexGetTaskbar"
        if not self.windows_classAtom:
            self.windows_classAtom = RegisterClass(wc)
        style = WS_OVERLAPPED | WS_SYSMENU
        hwnd = CreateWindow(self.windows_classAtom, "Taskbar", style, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hinst,
                            None)
        UpdateWindow(hwnd)

        hicon = LoadIcon(0, IDI_APPLICATION)
        # Hackily grab the icon from the webui if possible
        icon_flags = LR_LOADFROMFILE | LR_DEFAULTSIZE
        try:
            import flexget.ui
            icon_path = os.path.join(flexget.ui.__path__[0], 'src', 'favicon.ico')
            hicon = LoadImage(hinst, icon_path, IMAGE_ICON, 0, 0, icon_flags)
        except Exception as e:
            log.debug('Error trying to get flexget icon from webui folder: %s', e)

        # Taskbar icon
        flags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO
        nid = (hwnd, 0, flags, WM_USER + 20, hicon, "FlexGet Notification", message, config['timeout'] * 1000, title)
        Shell_NotifyIcon(NIM_ADD, nid)
Example #15
0
    def _show_toast(self, title, msg, icon_path, duration):
        """Notification settings.

        :title: notification title
        :msg: notification message
        :icon_path: path to the .ico file to custom notification
        :duration: delay in seconds before notification self-destruction
        """
        message_map = {
            WM_DESTROY: self.on_destroy,
        }

        # Register the window class.
        self.wc = WNDCLASS()
        self.hinst = self.wc.hInstance = GetModuleHandle(None)
        self.wc.lpszClassName = str("PythonTaskbar")  # must be a string
        self.wc.style = self.wc.cbWndExtra = 0
        # self.wc.lpfnWndProc = message_map  # could also specify a wndproc.
        try:
            self.classAtom = RegisterClass(self.wc)
        except:
            pass  # not sure of this
        style = WS_OVERLAPPED | WS_SYSMENU
        self.hwnd = CreateWindowEx(0, "PythonTaskbar", "555", style, 0, 0,
                                   CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
                                   self.hinst, None)
        UpdateWindow(self.hwnd)

        hicon = LoadIcon(0, IDI_APPLICATION)

        # Taskbar icon
        flags = NIF_ICON | NIF_TIP
        nid = (self.hwnd, 0, flags, WM_USER + 20, hicon, "66666")
        Shell_NotifyIcon(NIM_ADD, nid)
        Shell_NotifyIcon(NIM_MODIFY, (self.hwnd, 0, NIF_INFO, WM_USER + 20,
                                      hicon, "289347293874", msg, 0, title))
        # # take a rest then destroy
        sleep(duration)
        DestroyWindow(self.hwnd)
        UnregisterClass(self.wc.lpszClassName, None)
        return None
Example #16
0
    def _show_toast(
        self,
        title: str,
        msg: str = "No msg",
        icon_path: Path = None,
        duration: float = None,
        sound_path=None,
        callback_on_click: callable = None,
        tooltip: Optional[str] = None,
    ) -> None:
        """Notification settings.

        :param title:     notification title
        :param msg:       notification message
        :param icon_path: path to the .ico file to custom notification
        :param duration:  delay in seconds before notification self-destruction, None for no-self-destruction
        :param sound_path: path to the .wav file to custom notification
        """

        self.duration = duration

        def callback():
            """ """
            self.duration = 0

            if callback_on_click is not None:
                callback_on_click()

        if tooltip is None:
            tooltip = PROJECT_NAME

        # Register the window class.
        self.window_class = WNDCLASS()
        self.instance_handle = self.window_class.hInstance = GetModuleHandle(
            None)
        self.window_class.lpszClassName = f"{PROJECT_NAME}-{title}"  # must be a string
        self.window_class.lpfnWndProc = self._decorator(
            self.wnd_proc, callback)  # could instead specify simple mapping
        try:
            self.classAtom = RegisterClass(self.window_class)
        except Exception as e:
            logging.error("Some trouble with classAtom (%s)", e)
        style = WS_OVERLAPPED | WS_SYSMENU
        button_style = WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON  # TODO: Unused for now
        self.window_handle = CreateWindow(
            self.classAtom,
            "Taskbar",
            style,
            0,
            0,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            0,
            0,
            self.instance_handle,
            None,
        )
        UpdateWindow(self.window_handle)

        # icon
        new_name = ""
        if icon_path is not None:
            icon_path = path.realpath(icon_path)
            converted = False
            if Image is not None and icon_path.split(".")[-1] != ".ico":
                img = Image.open(icon_path)
                new_name = f'{str(icon_path.split(".")[:-1])}.ico'
                img.save(new_name)
                icon_path = new_name
                converted = True
        else:
            icon_path = resource_filename(
                Requirement.parse(PROJECT_NAME),
                str(Path(PROJECT_NAME) / "data" / "python.ico"),
            )
            converted = False
        try:
            hicon = LoadImage(
                self.instance_handle,
                icon_path,
                IMAGE_ICON,
                0,
                0,
                LR_LOADFROMFILE | LR_DEFAULTSIZE,
            )
            if Image and path.exists(new_name and converted):
                remove(new_name)
        except Exception as e:
            logging.error("Some trouble with the icon (%s): %s", icon_path, e)
            hicon = LoadIcon(0, IDI_APPLICATION)

        # Set the duration
        """
buff = create_unicode_buffer(10)
windll.user32.SystemParametersInfoW(SPI_GETMESSAGEDURATION, 0, buff, 0)
try:
  oldlength = int(buff.value.encode("unicode_escape").decode().replace("\\", "0"), 16)
except ValueError:
  oldlength = 5  # Default notification length

duration_output = windll.user32.SystemParametersInfoW(SPI_SETMESSAGEDURATION, 0, self.duration, SPIF_SENDCHANGE)
windll.user32.SystemParametersInfoW(SPI_GETMESSAGEDURATION, 0, buff, 0)

duration_error = False
try:
  int(buff.value.encode("unicode_escape").decode().replace("\\", "0"), 16)
except ValueError:
  duration_error = True

if duration_output == 0 or self.duration > 255 or duration_error:
  windll.user32.SystemParametersInfoW(SPI_SETMESSAGEDURATION, 0, oldlength, SPIF_SENDCHANGE)
  self.active = False
  raise RuntimeError(f"Some trouble with the duration ({self.duration})"          ": Invalid duration length")
"""

        title += " " * randint(0, 63 - len(title))
        msg += " " * randint(0, 128 - len(msg))

        Shell_NotifyIcon(
            NIM_ADD,
            (
                self.window_handle,
                0,
                NIF_ICON | NIF_MESSAGE | NIF_TIP,
                WM_USER + 20,
                hicon,
                tooltip,
            ),
        )
        Shell_NotifyIcon(
            NIM_MODIFY,
            (
                self.window_handle,
                0,
                NIF_INFO,
                WM_USER + 20,
                hicon,
                tooltip,
                msg,
                200,
                title,
                0 if sound_path is None else NIIF_NOSOUND,
            ),
        )

        if sound_path is not None:  # play the custom sound
            sound_path = path.realpath(sound_path)
            if not path.exists(sound_path):
                logging.error(
                    f"Some trouble with the sound file ({sound_path}): [Errno 2] No such file"
                )

            try:
                PlaySound(sound_path, SND_FILENAME)
            except Exception as e:
                logging.error(
                    f"Some trouble with the sound file ({sound_path}): {e}")

        PumpMessages()
        """
# Put the notification duration back to normal
SystemParametersInfoW(SPI_SETMESSAGEDURATION, 0, oldlength, SPIF_SENDCHANGE)
"""

        if duration is not None:  # take a rest then destroy
            # sleep(duration)
            while self.duration > 0:
                sleep(0.1)
                self.duration -= 0.1

            DestroyWindow(self.window_handle)
            UnregisterClass(self.window_class.lpszClassName,
                            self.instance_handle)

            try:  # Sometimes the try icon sticks around until you click it - this should stop that
                Shell_NotifyIcon(NIM_DELETE, (self.window_handle, 0))
            except WinTypesException:
                pass
        self.active = False
Example #17
0
from abc import ABC
from typing import final

from win32api import GetModuleHandle
from win32con import CW_USEDEFAULT, IMAGE_ICON, LR_DEFAULTSIZE, LR_LOADFROMFILE, WM_USER, \
    WS_OVERLAPPED, WS_SYSMENU
from win32gui import CreateWindow, DestroyWindow, LoadImage, NIF_ICON, NIF_INFO, NIF_MESSAGE, NIF_TIP, NIM_ADD, \
    NIM_MODIFY, NIM_DELETE, RegisterClass, Shell_NotifyIcon, UpdateWindow, WNDCLASS

from i18n import I18N_RESOURCES

_wnd_class = WNDCLASS()
_wnd_class.hInstance = GetModuleHandle(None)
_wnd_class.lpszClassName = 'Railway Station Simulator'
_wnd_class.lpfnWndProc = {}
_wnd_class_instance = RegisterClass(_wnd_class)


class Notification(ABC):
    def __init__(self,
                 logger,
                 caption_key,
                 message_key,
                 current_locale,
                 caption_args=(),
                 message_args=()):
        self.logger = logger
        self.handler = CreateWindow(_wnd_class_instance, "Taskbar",
                                    WS_OVERLAPPED | WS_SYSMENU, 0, 0,
                                    CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
                                    _wnd_class.hInstance, None)
Example #18
0
    def __call__(self, summary, message="", timeout=2000, **kwargs):
        tip = kwargs.get("tip", "Balloon tooltip")

        # Register the Window class.
        wc = WNDCLASS()
        hinst = wc.hInstance = GetModuleHandle(None)
        wc.lpszClassName = "PythonTaskbar"
        wc.lpfnWndProc = self.message_map  # could also specify a wndproc.
        classAtom = RegisterClass(wc)

        # Create the Window.
        style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU
        self.hwnd = CreateWindow(
            classAtom,
            "Taskbar",
            style,
            0,
            0,
            win32con.CW_USEDEFAULT,
            win32con.CW_USEDEFAULT,
            0,
            0,
            hinst,
            None,
        )
        UpdateWindow(self.hwnd)

        # Icons managment
        iconPathName = os.path.abspath(
            os.path.join(sys.path[0], "balloontip.ico"))
        icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE

        try:
            hicon = LoadImage(hinst, iconPathName, win32con.IMAGE_ICON, 0, 0,
                              icon_flags)
        except Exception:
            hicon = LoadIcon(0, win32con.IDI_APPLICATION)

        flags = NIF_ICON | NIF_MESSAGE | NIF_TIP
        nid = (self.hwnd, 0, flags, win32con.WM_USER + 20, hicon, "tooltip")

        # Notify
        Shell_NotifyIcon(NIM_ADD, nid)
        Shell_NotifyIcon(
            NIM_MODIFY,
            (
                self.hwnd,
                0,
                NIF_INFO,
                win32con.WM_USER + 20,
                hicon,
                tip,
                message,
                timeout,
                summary,
            ),
        )
        # Destroy
        DestroyWindow(self.hwnd)
        classAtom = UnregisterClass(classAtom, hinst)
        return True
    def _show_toast(self, title, msg, icon_path, duration, callback_on_click):
        '''Notification settings.

        :param title:     notification title
        :param msg:       notification message
        :param icon_path: path to the .ico file to custom notification
        :para mduration:  delay in seconds before notification self-destruction, None for no-self-destruction
        '''

        # Register the window class.
        self.wc = WNDCLASS()
        self.hinst = self.wc.hInstance = GetModuleHandle(None)
        # must be a string
        self.wc.lpszClassName = str(f"PythonTaskbar{title}")
        # could instead specify simple mapping
        self.wc.lpfnWndProc = self._decorator(self.wnd_proc, callback_on_click)
        try:
            self.classAtom = RegisterClass(self.wc)
        except Exception as e:
            #logging.error('Some trouble with classAtom (%s)', e)
            self.classAtom = self.wc
        style = WS_OVERLAPPED | WS_SYSMENU
        self.hwnd = CreateWindow(self.classAtom, 'Taskbar', style, 0, 0,
                                 CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
                                 self.hinst, None)
        UpdateWindow(self.hwnd)

        # icon
        if icon_path is not None:
            icon_path = path.realpath(icon_path)
            converted = False
            if Image is not None and icon_path.split('.')[-1] != '.ico':
                img = Image.open(icon_path)
                new_name = icon_path.split('.')[:-1] + '.ico'
                img.save(new_name)
                icon_path = new_name
                converted = True
        else:
            icon_path = resource_filename(Requirement.parse('win10toast'),
                                          'win10toast/data/python.ico')
            converted = False
        icon_flags = LR_LOADFROMFILE | LR_DEFAULTSIZE
        try:
            hicon = LoadImage(self.hinst, icon_path, IMAGE_ICON, 0, 0,
                              icon_flags)
            if Image and path.exists(new_name and converted):
                remove(new_name)
        except Exception as e:
            logging.error('Some trouble with the icon (%s): %s', icon_path, e)
            hicon = LoadIcon(0, IDI_APPLICATION)

        # Taskbar icon
        flags = NIF_ICON | NIF_MESSAGE | NIF_TIP
        nid = self.hwnd, 0, flags, WM_USER + 20, hicon, 'Tooltip'
        Shell_NotifyIcon(NIM_ADD, nid)
        Shell_NotifyIcon(NIM_MODIFY,
                         (self.hwnd, 0, NIF_INFO, WM_USER + 20, hicon,
                          'Balloon Tooltip', msg, 200, title))
        PumpMessages()
        # take a rest then destroy
        if duration is not None:
            sleep(duration)
            DestroyWindow(self.hwnd)
            UnregisterClass(self.wc.lpszClassName, None)
        return None
Example #20
0
    def _show_toast(self):
        """Internal function called by Toast#display to show the toast"""

        self.active = True
        self.destroy_window = self.toast_data["kill_without_click"]

        # Register the window class
        self.toast_data["wnd_class"] = WNDCLASS()
        self.toast_data["hinst"] = self.toast_data[
            "wnd_class"].hInstance = GetModuleHandle(None)
        self.toast_data[
            "wnd_class"].lpszClassName = f"PythonTaskbar{uuid4().hex}"
        self.toast_data["wnd_class"].lpfnWndProc = self._decorator(
            self._wnd_proc, self.toast_data["callback_on_click"])

        self.toast_data["class_atom"] = RegisterClass(
            self.toast_data["wnd_class"])

        style = WS_OVERLAPPED | WS_SYSMENU
        self.toast_data["hwnd"] = CreateWindow(
            self.toast_data["class_atom"],
            self.toast_data["wnd_class"].lpszClassName,
            style,
            0,
            0,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            0,
            0,
            self.toast_data["hinst"],
            None,
        )

        UpdateWindow(self.toast_data["hwnd"])

        icon_flags = LR_LOADFROMFILE | LR_DEFAULTSIZE

        hicon = LoadImage(self.toast_data["hinst"],
                          self.toast_data['icon_path'], IMAGE_ICON, 0, 0,
                          icon_flags)

        # Set the duration
        buff = create_unicode_buffer(10)
        SystemParametersInfoW(SPI_GETMESSAGEDURATION, 0, buff, 0)
        try:
            oldlength = int(
                buff.value.encode("unicode_escape").decode().replace(
                    "\\", "0"), 16)
        except ValueError:
            oldlength = 5  # Default notification length

        SystemParametersInfoW(SPI_SETMESSAGEDURATION, 0,
                              self.toast_data["duration"], SPIF_SENDCHANGE)

        # Taskbar icon
        flags = NIF_ICON | NIF_MESSAGE | NIF_TIP
        nid = (
            self.toast_data["hwnd"],
            0,
            flags,
            WM_USER + 20,
            hicon,
            self.toast_data["tooltip"],
        )

        # Make it so that it won't replace another
        # notification with the same title and message
        title = self.toast_data["title"] + " " * randint(
            0, 63 - len(self.toast_data["title"]))
        message = self.toast_data["msg"] + " " * randint(
            0, 128 - len(self.toast_data["msg"]))

        # Add tray icon and queue message
        Shell_NotifyIcon(NIM_ADD, nid)
        Shell_NotifyIcon(
            NIM_MODIFY,
            (
                self.toast_data["hwnd"],
                0,
                NIF_INFO,
                WM_USER + 20,
                hicon,
                self.toast_data["tooltip"],
                message,
                0,
                title,
                NIIF_NOSOUND if self.toast_data["sound_path"] else 0,
            ),
        )

        # Play the custom sound
        if self.toast_data["sound_path"] is not None:
            sound_path = path.realpath(self.toast_data["sound_path"])
            PlaySound(sound_path, SND_FILENAME)

        # Show the message
        PumpMessages()
        # Put the notification duration back to normal
        SystemParametersInfoW(SPI_SETMESSAGEDURATION, 0, oldlength,
                              SPIF_SENDCHANGE)

        # Take a rest then destroy
        if not self.toast_data["keep_alive"] and self.destroy_window:
            self.destroy()
    def _show_toast(self,
                    title,
                    msg,
                    icon_path,
                    duration,
                    cbFunc=None,
                    cbArgs=None):
        """Notification settings.

        :title: notification title
        :msg: notification message
        :icon_path: path to the .ico file to custom notification
        :duration: delay in seconds before notification self-destruction
        """
        self.user_cbFunc = cbFunc
        self.user_cbArgs = cbArgs

        # Register the window class.
        self.wc = WNDCLASS()
        self.hinst = self.wc.hInstance = GetModuleHandle(None)
        self.wc.lpszClassName = str("PythonTaskbar" +
                                    os.urandom(24).hex())  # must be a string
        self.wc.lpfnWndProc = self._decorator(
            self.wnd_proc, self.user_cbFunc)  # could also specify a wndproc.
        try:
            self.classAtom = RegisterClass(self.wc)
        except:
            pass  #not sure of this
        style = WS_OVERLAPPED | WS_SYSMENU
        self.hwnd = CreateWindow(self.classAtom, "Taskbar", style, 0, 0,
                                 CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
                                 self.hinst, None)
        UpdateWindow(self.hwnd)

        # icon
        hicon = None

        if icon_path is not None:
            icon_path = path.realpath(icon_path)
            icon_flags = LR_LOADFROMFILE

            try:
                hicon = LoadImage(self.hinst, icon_path, IMAGE_ICON, 0, 0,
                                  icon_flags)
            except Exception as e:
                logging.error("Some trouble with the icon ({}): {}".format(
                    icon_path, e))
                hicon = LoadIcon(0, IDI_APPLICATION)

        # Taskbar icon
        flags = NIF_ICON | NIF_MESSAGE | NIF_TIP
        nid = (self.hwnd, 0, flags, WM_USER + 20, hicon, "Tooltip")
        Shell_NotifyIcon(NIM_ADD, nid)
        Shell_NotifyIcon(NIM_MODIFY,
                         (self.hwnd, 0, NIF_INFO, WM_USER + 20, hicon,
                          "Balloon Tooltip", msg, 200, title))
        PumpMessages()
        # take a rest then destroy
        sleep(duration)
        DestroyWindow(self.hwnd)
        UnregisterClass(self.wc.lpszClassName, None)
        return None
Example #22
0
    def _show_toast(self, title, msg, icon_path, delay, sound_path, tooltip,
                    duration, callback_on_click, kill_without_click):
        """Notification settings.

        :title: notification title
        :msg: notification message
        :icon_path: path to the .ico file to custom notification
        :delay: delay in seconds before notification self-destruction, None for no-self-destruction
        :sound_path: path to the .wav file to custom notification
        :duration: how long the notification stays on the screen in seconds
        :callback_on_click: function to run on click
        :kill_without_click: Kill the tray icon after the notification goes away, even if it wasn't clicked
        """
        self.delay = delay
        self.destroy_window = kill_without_click

        # Register the window class.
        self.wc = WNDCLASS()
        self.hinst = self.wc.hInstance = GetModuleHandle(None)
        self.wc.lpszClassName = str(
            f"PythonTaskbar - {uuid4().hex}")  # must be a string
        self.wc.lpfnWndProc = self._decorator(
            self.wnd_proc,
            callback_on_click)  # could instead specify simple mapping
        try:
            self.classAtom = RegisterClass(self.wc)
        except Exception as e:
            raise type(e)(f"Some trouble with classAtom:\n{e}") from None
        style = WS_OVERLAPPED | WS_SYSMENU
        self.hwnd = CreateWindow(self.classAtom, "Python Taskbar", style, 0, 0,
                                 CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
                                 self.hinst, None)
        UpdateWindow(self.hwnd)

        # icon
        if icon_path is not None:
            icon_path = path.realpath(icon_path)
        else:
            icon_path = resource_filename(Requirement.parse("win10toast"),
                                          "win10toast/data/python.ico")
        icon_flags = LR_LOADFROMFILE | LR_DEFAULTSIZE
        try:
            hicon = LoadImage(self.hinst, icon_path, IMAGE_ICON, 0, 0,
                              icon_flags)
        except Exception as e:
            raise type(e)(
                f"Some trouble with the icon ({icon_path}):\n{e}") from None
            hicon = LoadIcon(0, IDI_APPLICATION)

        # set the duration
        buff = create_unicode_buffer(10)
        SystemParametersInfoW(SPI_GETMESSAGEDURATION, 0, buff, 0)
        try:
            oldlength = int(
                buff.value.encode('unicode_escape').decode().replace(
                    "\\", "0"), 16)
        except ValueError:
            oldlength = 5  # default notification length

        durationOutput = SystemParametersInfoW(SPI_SETMESSAGEDURATION, 0,
                                               duration, SPIF_SENDCHANGE)
        SystemParametersInfoW(SPI_GETMESSAGEDURATION, 0, buff, 0)

        durationError = False
        try:
            int(
                buff.value.encode('unicode_escape').decode().replace(
                    "\\", "0"), 16)
        except ValueError:
            durationError = True
        if durationOutput == 0 or duration > 255 or durationError:
            SystemParametersInfoW(SPI_SETMESSAGEDURATION, 0, oldlength,
                                  SPIF_SENDCHANGE)
            raise RuntimeError(
                f"Some trouble with the duration ({duration}): Invalid duration length"
            )

        # Taskbar icon
        flags = NIF_ICON | NIF_MESSAGE | NIF_TIP
        nid = (self.hwnd, 0, flags, WM_USER + 20, hicon, tooltip)

        Shell_NotifyIcon(NIM_ADD, nid)
        Shell_NotifyIcon(
            NIM_MODIFY,
            (self.hwnd, 0, NIF_INFO, WM_USER + 20, hicon, tooltip, msg, 0,
             title, 0 if sound_path == None else NIIF_NOSOUND))

        # play the custom sound
        if sound_path is not None:
            sound_path = path.realpath(sound_path)
            if not path.exists(sound_path):
                raise IOError(
                    "Some trouble with the sound file ({sound_path}): [Errno 2] No such file"
                )

            try:
                PlaySound(sound_path, SND_FILENAME)
            except Exception as e:
                raise type(
                    e)(f"Some trouble with the sound file ({sound_path}): {e}"
                       ) from None

        PumpMessages()
        # put the notification duration back to normal
        SystemParametersInfoW(SPI_SETMESSAGEDURATION, 0, oldlength,
                              SPIF_SENDCHANGE)

        # take a rest then destroy
        if self.delay is not None and self.destroy_window:
            while self.delay > 0:
                sleep(0.1)
                self.delay -= 0.1

            DestroyWindow(self.hwnd)
            UnregisterClass(self.wc.lpszClassName, self.hinst)
            try:  # sometimes the tray icon sticks around until you click it - this should stop it
                self.remove_window(self.hwnd)
            except WinTypesException:
                pass
        return