Windows OSにおいて、アプリケーションのタスクトレイアイコンは非常に重要な役割を果たします。Pythonを使ってアプリケーションのタスクトレイアイコンを表示する方法を紹介します。
pystrayを使った方法
pystrayはPythonでタスクトレイアイコンを簡単に表示できるライブラリです。以下は、pystrayを使ったアプリケーションのタスクトレイアイコンの表示方法です。
-
pystrayをインストールします。
pip install pystray -
以下のコードを実行して、アプリケーションのタスクトレイアイコンを表示します。
import pystray from PIL import Image def on_exit(): print('exit') image = Image.open('icon.png') menu = pystray.Menu(pystray.MenuItem('Exit', on_exit)) tray_icon = pystray.Icon('name', image, 'title', menu) tray_icon.run()icon.pngはアプリケーションのアイコン画像、nameはアプリケーションの名前、titleはタスクトレイアイコンのツールチップに表示するテキストです。on_exitは、タスクトレイアイコンのコンテキストメニューからExitを選択したときに実行される関数です。
win32apiを使った方法
win32apiを使って、Windows APIを直接呼び出してタスクトレイアイコンを表示することもできます。以下は、win32apiを使ったアプリケーションのタスクトレイアイコンの表示方法です。
-
win32apiをインストールします。
pip install pypiwin32 -
以下のコードを実行して、アプリケーションのタスクトレイアイコンを表示します。
import os import win32api import win32gui import win32con from ctypes import windll class SysTrayIcon: def __init__(self, icon, hover_text, menu_options, on_quit=None, default_menu_index=None, window_class_name=None): self.icon = icon self.hover_text = hover_text self.on_quit = on_quit menu_options = menu_options + (('Quit', None, self.quit),) self._next_action_id = 1 self.menu_actions_by_id = set() self.menu_options = self._add_ids_to_menu_options(list(menu_options)) self.menu_actions_by_id = dict(self.menu_actions_by_id) del self._next_action_id self.default_menu_index = (default_menu_index or 0) self.window_class_name = window_class_name or "SysTrayIconPy " message_map = { win32gui.RegisterWindowMessage("TaskbarCreated"): self.restart, win32con.WM_DESTROY: self.destroy, win32con.WM_COMMAND: self.command, win32con.WM_USER + 20: self.notify, } # Register the Window Class self.wc = win32gui.WNDCLASS() self.hinst = self.wc.hInstance = win32api.GetModuleHandle(None) self.wc.lpszClassName = self.window_class_name self.wc.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW self.wc.hCursor = win32api.LoadCursor(0, win32con.IDC_ARROW) self.wc.hbrBackground = win32con.COLOR_WINDOW self.wc.lpfnWndProc = message_map # could also specify a wndproc. self.classAtom = win32gui.RegisterClass(self.wc) def _add_ids_to_menu_options(self, menu_options): result = [] for menu_option in menu_options: option_text, option_icon, option_action = menu_option if callable(option_action) or option_action is None: action_id = self._next_action_id self._next_action_id += 1 self.menu_actions_by_id.add((action_id, option_action)) else: action_id = option_action result.append((option_text, option_icon, action_id)) return result def run(self): # Create the Window style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU self.hwnd = win32gui.CreateWindow(self.classAtom, self.window_class_name, style, 0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, 0, 0, self.hinst, None) win32gui.UpdateWindow(self.hwnd) self.notify_id = None self.refresh_icon() win32gui.PumpMessages() def refresh_icon(self): # Try and find a custom icon hinst = win32api.GetModuleHandle(None) if os.path.isfile(self.icon): icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE hicon = win32gui.LoadImage(hinst, self.icon, win32con.IMAGE_ICON, 0, 0, icon_flags) else: hicon = win32gui.LoadIcon(0, win32con.IDI_APPLICATION) if self.notify_id: message = win32gui.NIM_MODIFY else: message = win32gui.NIM_ADD self.notify_id = (self.hwnd, 0, win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP, win32con.WM_USER + 20, hicon, self.hover_text) win32gui.Shell_NotifyIcon(message, self.notify_id) def restart(self, hwnd, msg, wparam, lparam): self.refresh_icon() def destroy(self, hwnd, msg, wparam, lparam): if self.on_quit: self.on_quit(self) nid = (self.hwnd, 0) win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, nid) win32gui.PostQuitMessage(0) # Terminate the app. def notify(self, hwnd, msg, wparam, lparam): if l