def set_icon_from_data(self, pixels, has_alpha, w, h, rowstride, options=None): #this is convoluted but it works.. log("set_icon_from_data%s", ("%s pixels" % len(pixels), has_alpha, w, h, rowstride, options)) from PIL import Image #@UnresolvedImport if has_alpha: img_format = "RGBA" else: img_format = "RGBX" rgb_format = typedict(options or {}).strget("rgb_format", "RGBA") img = Image.frombuffer(img_format, (w, h), pixels, "raw", rgb_format, rowstride, 1) assert img, "failed to load image from buffer (%i bytes for %ix%i %s)" % ( len(pixels), w, h, rgb_format) #apparently, we have to use SM_CXSMICON (small icon) and not SM_CXICON (regular size): icon_w = GetSystemMetrics(win32con.SM_CXSMICON) icon_h = GetSystemMetrics(win32con.SM_CYSMICON) if w != icon_w or h != icon_h: log("resizing tray icon to %ix%i", icon_w, icon_h) img = img.resize((icon_w, icon_h), Image.ANTIALIAS) rowstride = w * 4 hicon = image_to_ICONINFO(img) self.do_set_icon(hicon, DestroyIcon) UpdateWindow(self.hwnd) self.reset_function = (self.set_icon_from_data, pixels, has_alpha, w, h, rowstride)
def create_window(self): style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU window_name = u"%s StatusIcon Window" % bytestostr(self.title) self.hwnd = CreateWindowExA(0, NIclassAtom, window_name, style, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, 0, 0, \ 0, 0, NIwc.hInstance, None) if self.hwnd == 0: raise ctypes.WinError(ctypes.get_last_error()) log("hwnd=%#x", self.hwnd) UpdateWindow(self.hwnd)
def set_icon_from_data(self, pixels, has_alpha, w, h, rowstride, options={}): #this is convoluted but it works.. log("set_icon_from_data%s", ("%s pixels" % len(pixels), has_alpha, w, h, rowstride, options)) from PIL import Image #@UnresolvedImport if has_alpha: img_format = "RGBA" else: img_format = "RGBX" rgb_format = options.get("rgb_format", "RGBA") img = Image.frombuffer(img_format, (w, h), pixels, "raw", rgb_format, rowstride, 1) assert img, "failed to load image from buffer (%i bytes for %ix%i %s)" % ( len(pixels), w, h, rgb_format) #apparently, we have to use SM_CXSMICON (small icon) and not SM_CXICON (regular size): icon_w = GetSystemMetrics(win32con.SM_CXSMICON) icon_h = GetSystemMetrics(win32con.SM_CYSMICON) if w != icon_w or h != icon_h: log("resizing tray icon to %ix%i", icon_w, icon_h) img = img.resize((w, h), Image.ANTIALIAS) bitmap = 0 mask = 0 try: from xpra.codecs.argb.argb import rgba_to_bgra #@UnresolvedImport bgra = memoryview_to_bytes(rgba_to_bgra(img.tobytes())) bitmap = rgba_to_bitmap(bgra, icon_w, icon_h) mask = CreateBitmap(icon_w, icon_h, 1, 1, None) iconinfo = ICONINFO() iconinfo.fIcon = True iconinfo.hbmMask = mask iconinfo.hbmColor = bitmap hicon = CreateIconIndirect(byref(iconinfo)) log("CreateIconIndirect()=%s", hicon) if not hicon: raise ctypes.WinError(ctypes.get_last_error()) except Exception: log.error("Error: failed to set tray icon", exc_info=True) hicon = FALLBACK_ICON finally: if mask: DeleteObject(mask) if bitmap: DeleteObject(bitmap) self.do_set_icon(hicon) UpdateWindow(self.hwnd) self.reset_function = (self.set_icon_from_data, pixels, has_alpha, w, h, rowstride)
def create_window(self): style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU window_name = u"%s StatusIcon Window" % bytestostr(self.title) self.hwnd = CreateWindowExA(0, NIclassAtom, window_name, style, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, 0, 0, \ 0, 0, NIwc.hInstance, None) log("create_window() hwnd=%#x", self.hwnd or 0) if not self.hwnd: raise ctypes.WinError(ctypes.get_last_error()) UpdateWindow(self.hwnd) #register callbacks: win32NotifyIcon.instances[self.hwnd] = self
def create_window(self): style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU window_name = "%s StatusIcon Window" % bytestostr(self.title) niwc = get_notifyicon_wnd_class() args = (0, niwc.NIclassAtom, window_name, style, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, 0, 0, 0, 0, niwc.hInstance, 0) log("CreateWindowExA%s", args) self.hwnd = CreateWindowExA(*args) log("create_window() hwnd=%#x", self.hwnd or 0) if not self.hwnd: raise ctypes.WinError(ctypes.get_last_error()) UpdateWindow(self.hwnd) #register callbacks: win32NotifyIcon.instances[self.hwnd] = self
def create_tray_window(self): style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU window_name = (self.title + " StatusIcon Window").decode() self.hwnd = CreateWindowExA(0, NIclassAtom, window_name, style, 0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, \ 0, 0, NIwc.hInstance, None) if self.hwnd == 0: raise ctypes.WinError(ctypes.get_last_error()) log("hwnd=%#x", self.hwnd) UpdateWindow(self.hwnd) r = Shell_NotifyIcon(NIM_ADD, self.make_nid(NIF_ICON | NIF_MESSAGE | NIF_TIP)) log("Shell_NotifyIcon ADD=%i", r) if not r: raise Exception("Shell_NotifyIcon failed to ADD")