April 22, 2005
Windows system tray icons with Python
Two or three years ago, I put together a little Python app that provided shortcuts to useful places in our gruesome internal timesheet system. (The URLs aren't static, so I needed a script.) I used PyWin32 to enable you to launch these from the Windows systems tray, based on demo code by Mark Hammond. My script was a bit of a bodge, though; the UI code and the logic code were all mixed up. I always intended to go back and separate everything out, but I never got around to it...
Until now. I had a couple of changes that needed making, so I grasped the nettle and put together a general purpose module; SysTrayIcon.py. It still needs documentation, but you can see basically how to use it from the demo code at the bottom.
There is one problem with it, though - on XP, if you set up a menu item with an icon, the menu item text overlaps the icon image by a few pixels, and I can't work out how to fix it. Any pointers?
Oh, and yes, yes, I know it's not called the system tray really. But that's what everyone calls it anyway.
Posted to Python by Simon Brunning at April 22, 2005 01:16 PM
Thanks a bunch. I can find this rather useful.
Thanks for this nice script.
I had to sligthly modify it to make it working on Python 2.3
I add the line:
from sets import Set
and modify the line:
self.menu_actions_by_id = set()
self.menu_actions_by_id = Set()
So if someone have the same problem it could solve it slightly faster I suppose.
Vivian De Smedt.
win32gui in python seems quite useful. I didn't know python could be so tightly integrated with Windows.
Simon, thanks a bunch for posting this! You've wrapped it up nicely and it makes it look simple, but I'm sure it would have taken me days or hours to dig through the docs to figure this out.
Another way to do it would be to use Jython + Java Desktop Integration Components (JDIC)
The pixel overlap looks to be the way XP's systray displays things. I notice that every other text popup on the system tray does the same thing.
In reply to Vivian De Smedt's comment, I have this alternate suggestion.
from sets import Set
except ImportError, why:
print 'Error. `set\' was not defined, and we could not import the sets module as required.'
print 'Error returned was: '+str(why)
#assuming that sys was imported
sys.exit((-1,'`Set` was unavailable, so we cannot continue'))
set = Set
Hopefully that would be a widely compatible method of resolving the `set` function.
Thanx to your good work, I didn't have to reinvent the wheel here.
I've also wrapped this up into a more General Application Framework I call pysystray-win32 at http://datavibe.net/~essiene/pysystray
This has save me a lot of time too, than using SysTrayIcon in the raw.
Do you have any particular licensing requirements? As i've released this on sourceforge. If you want to reach me, i'm at essiene _at_ datavibe _dot_ net
Hmmm. I've emailed you at that address a couple of times, Essien, but clearly you aren't getting my mails. I wonder what's up?
Any road up, help yourself. Consider SysTrayIcon.py to be under an "Aleister Crowley" style license - "Do what thou wilt shall be the only law".
Err, but don't sue me if it doesn't work. ;-)
I really wonder what's up with the funky email anyways, it works mostly, maybe a grumpy Elephant is sitting infront of the SMTP server :)
> Any road up, help yourself. Consider
> SysTrayIcon.py to be under an "Aleister Crowley"
> style license - "Do what thou wilt shall be the
> only law".
> Err, but don't sue me if it doesn't work. ;-)
This is quite buggy. When I minimize my window, the window is then hidden with window.withdraw(). It then unhides the icon like it should, but when I double click on the icon, to trigger a window.deiconify(), the whole program locks up and I get no traceback. Any ideas?
Nice little script, and well done Essian for doing a nice little wrapper & installer.
It looks as if the icons could be shifted to the left another 10-15 pixels as there's a gap on the left side of the menu. So in other words the icons are currently appearing with the text label, and not in the designated icon location..
Looking at the menus of my other system tray icons, their icons are 1-2px from the left border. Maybe there's another way to specify how to load an icon into the menu via the win32 library?
I'll have a tinker and see if I can figure it out, though if anybody else has achieved it, please post it up :)