Construct a tray (system tray) based on pywin32 + tkinter)

Source: Internet
Author: User

Source code from http://www.brunningonline.net/simon/blog/archives/SysTrayIcon.py.html

In fact, this source code can be used directly, but it does not take into account the combination of the tray and other programs, but a separate tray. Most of the cases where pallets are used are GUI programs. I use tkinter. Therefore, some modifications were made:

#-*-Coding: GBK-*-# module: javasrayicon. PY # Synopsis: Windows System Tray Icon. # programmer: Simon brunning-simon@brunningonline.net # Date: 11 sort l 2005 # Notes: Based on (I. e. ripped off from) Mark Hammond's # win32gui_taskbar.py and win32gui_menu.py demos from pywin32 ''' todofor now, the demo at the bottom shows how to use it... '''import osimport win32apiimport win32conimport win32gui_str Ucttry: Import winxpgui as win32guistmt importerror: Import win32guiclass javasrayicon (object ): '''todo ''' 'Quit = 'quit' special_actions = [quit] first_id = 1023 def _ init _ (self, icon, Gui, hover_text, menu_options, on_quit = none, default_menu_index = none, window_class_name = none,): Self. gui = GUI # added this parameter, which is an instance of the GUI class that generates the tray. See the code self. icon = icon self. hover_text = hover_text self. on_quit = on_quit me Nu_options = menu_options + ('exit Project', none, self. quit),) # change the option text and replace 'quit' with the text self that you want to use to represent 'exited. _ next_action_id = self. first_id 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 "rayrayiconpy" message_map = {win32gui. registerwindowmessage ("taskbarcreated"): Self. restart, win32con. wm_destroy: Self. destroy, win32con. wm_command: Self. command, win32con. wm_user + 20: Self. using Y,} # register the window class. self. window_class = win32gui. wndclass () # change the local variable window_class to the class attribute. In fact, window_class does not have to be changed to self. hinst = self. window_class.hinstance = win32gui. getmodulehandle (none) SEL F. window_class.lpszclassname = self. window_class_name # Change hinst to the class attribute. This must be changed because unregister uses self. window_class.style = win32con. cs_vredraw | win32con. cs_hredraw; self. window_class.hcursor = win32gui. loadcursor (0, win32con. idc_arrow) self. window_class.hbrbackground = win32con. color_window self. window_class.lpfnwndproc = message_map # cocould also specify a wndproc. self. classatom = win32gui. registerc Lass (self. window_class) # classatom is also changed to the attribute, which is passed in when unregister is later # 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. policy_id = none self. refresh_icon () win32gui. pumpmessages () def _ add_ids _ Resolve (self, menu_options): Result = [] for menu_option in menu_options: option_text, option_icon, option_action = menu_option # meaning of option items if callable (option_action) or option_action in self. special_actions: Self. menu_actions_by_id.add (self. _ next_action_id, option_action) result. append (menu_option + (self. _ next_action_id,) Elif non_string_iterable (option_action): result. append (optio N_text, option_icon, self. _ add_ids_to_menu_options (option_action), self. _ next_action_id) else: Print ('unknown item', option_text, option_icon, option_action) self. _ next_action_id + = 1 return result def refresh_icon (Self): # Try and find a custom icon self. hinst = win32gui. getmodulehandle (none) If OS. path. isfile (self. icon): icon_flags = win32con. lr_loadfromfile | win32con. lr_defaultsize hicon = wi N32gui. loadImage (self. hinst, self. icon, win32con. image_icon, 0, 0, icon_flags) else: Print ("can't find icon file-using default. ") hicon = win32gui. loadicon (0, win32con. idi_application) If self. policy_id: Message = win32gui. nim_modify else: Message = win32gui. nim_add self. policy_id = (self. hwnd, 0, win32gui. nif_icon | win32gui. nif_message | win32gui. nif_tip, win32con. wm_user + 20, hicon, self. hover _ Text) win32gui. shell_policyicon (message, self. policy_id) def restart (self, hwnd, MSG, wparam, lparam): Self. refresh_icon () def destroy (self, hwnd, MSG, wparam, lparam): ''' destroy corresponds to wm_destroy, meaning that once the tray is destroy (because win32gui. destroywindow (self. (hwnd), then a wm_destroy message is generated. The message processing function is the destroy function. note that the first sentence should be removed because the tray should be destroyed when the main window is restored, but this is not like calling the on_quit function. on_quit is only used when the main window is exited. the original code is written because there is no main window. If the tray is destroyed, the program wants to exit ''' # If self. on_quit: Self. on_quit (Self) Comment out, otherwise the on_quit function nid = (self. hwnd, 0) win32gui. shell_policyicon (win32gui. nim_delete, NID) win32gui. postquitmessage (0) # terminate the app. def icon_exit_show_window (Self): ''' the function I added is used to cancel the tray icon and display ''' self in the original window. gui. TK. deiconify () win32gui. destroywindow (self. hwnd) # destroy the tray win32gui. unregisterclass (self. classatom, self. hinst) # deregister def Policy (self, hwnd, MSG, WP Aram, lparam): ''' this function defines what will happen when double-clicking, left-clicking, or right-clicking on the tray icon. When double-clicking, I want to restore the main window, modify the default operation '''if lparam = win32con. wm_lbuttondblclk: #self.exe cute_menu_option (self. default_menu_index + self. first_id) Comment out its self. icon_exit_show_window () # I added Elif lparam = win32con. wm_rbuttonup: Self. show_menu () Elif lparam = win32con. wm_lbuttonup: Pass return true def show_menu (Self): menu = win32gui. createpopupmenu () self. create_menu (Me Nu, self. menu_options) # win32gui. setmenudefaultitem (menu, 1000, 0) Pos = win32gui. getcursorpos () # See http://msdn.microsoft.com/library/default.asp? Url =/library/en-US/winui/menus_0hdi.asp win32gui. setforegroundwindow (self. hwnd) win32gui. trackpopupmenu (menu, win32con. tpm_leftalign, POS [0], POS [1], 0, self. hwnd, none) win32gui. postmessage (self. hwnd, win32con. wm_null, 0, 0) def create_menu (self, menu, menu_options): For option_text, option_icon, option_action, option_id in menu_options [:-1]: If option_icon: option_icon = self. prep_menu_icon (option_icon) If option_id in self. menu_actions_by_id: item, extras = win32gui_struct.packmenuiteminfo (text = option_text, hbmpitem = option_icon, WID = option_id) win32gui. insertmenuitem (menu, 0, 1, item) else: submenu = win32gui. createpopupmenu () self. create_menu (submenu, option_action) item, extras = win32gui_struct.packmenuiteminfo (text = option_text, hbmpitem = option_icon, hsubmenu = submenu) win32gui. insertmenuitem (menu, 0, 1, item) def prep_menu_icon (self, icon): # first load the icon. ico_x = WIN32API. getsystemmetrics (win32con. sm_cxsmicon) ico_y = WIN32API. getsystemmetrics (win32con. sm_cysmicon) hicon = win32gui. loadImage (0, icon, win32con. image_icon, ico_x, ico_y, win32con. lr_loadfromfile) hdcbitmap = win32gui. createcompatibledc (0) hdcscreen = win32gui. getdc (0) HBM = win32gui. createcompatiblebitmap (hdcscreen, ico_x, ico_y) hbmold = win32gui. selectObject (hdcbitmap, HBM) # Fill the background. brush = win32gui. getsyscolorbrush (win32con. color_menu) win32gui. fillrect (hdcbitmap, (0, 0, 16, 16), brush) # unclear if brush needs to be feed. best clue I can find is: # "getsyscolorbrush returns a cached brush instead of allocating a new # One. "-implies no deleteobject # Draw the icon win32gui. drawiconex (hdcbitmap, 0, 0, hicon, ico_x, ico_y, 0, 0, win32con. di_normal) win32gui. selectObject (hdcbitmap, hbmold) win32gui. deletedc (hdcbitmap) return HBM def command (self, hwnd, MSG, wparam, lparam): Id = win32gui. loword (wparam) self.exe cute_menu_option (ID) def execute_menu_option (self, ID): menu_action = self. menu_actions_by_id [ID] If menu_action = self. quit: # Run the following code win32gui when you click 'exit. destroywindow (self. hwnd) self. on_quit () # The on_quit function is passed in from outside. See the following code else: menu_action (Self) def non_string_iterable (OBJ): Try: ITER (OBJ) handle T typeerror: return false else: return not (isinstance (OBJ, STR) or isinstance (OBJ, bytes) or isinstance (OBJ, bytearray ))

Note: The description of the modification.

The javasrayicon class is used in the main function:

Import into rayicondef winclose (Self): def quit (): # If you want to use the class as a parameter, you just need to pass the name directly without adding the module name if MessageBox. askokcancel ("quit", "Exit 131 cartoon download? "): If OS .path.exists('cover.jpg '): OS .remove('cover.jpg') # Delete the previously saved cover image self. TK. destroy () icon = 'img/tray. ICO 'self. TK. withdraw () def show (systrayicon): systrayicon. icon_exit_show_window () hover_text = "131 cartoon player" + STR (self. edition) # move the mouse over tray, and the displayed text menu_options = ('recovery Windows', none, show), # The exit option is automatically added to audit Ray) # Pass in the on_quit function, if you click the default exit option in the menu, run on_quit first, and then run the default tray exit process mongoray. explorrayicon (icon, self, hover_text, menu_options, on_quit = quit, default_menu_index = 0)

This function is in the class GUI class, And self represents the GUI class itself.

Note that if you write a function to menu_options as a processing function for an option, you can call the function in the explorrayicon class with the self parameter, which is called by the explorrayicon class. So this should be taken into account during definition. Show has this parameter (it is good to use the name when passing in the class ). On_quit does not require parameters.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.