I’m doing a 3 part series on using wxPython and PyWin32 to capture output from a running OpenVPN session.

I use OpenVPN to connect to PCs at work. I noticed that our current method of launching OpenVPN was in a console window so that one could monitor the program’s output. If the user happened to close said window, it would end the VPN session. I thought this was dumb, so I decided that I would try wrapping the interface using wxPython in such a way that I can minimize it to the system tray and bring it back up on demand to check the output if I was having an issue. If you want to follow along, then you’ll need the following:

Got all those? Ok. Let’s continue. To begin, create a folder to hold your scripts. We’ll actually need a couple to do this right.

First, we’re going to create a system tray icon.

Step 1: Pick an icon (I used one from the Tamarin set)

Step 2: Once you have the icon, we’ll use a wxPython utility called img2py that will convert the icon or picture into a python file. It can be found in your Python folder after you’ve installed wxPython: \\path\to\Python25\Lib\site-packages\wx-2.8-msw-unicode\wx\tools (adjust as necessary for your system)

Step 3: Move the icon file to the directory in step 2 and open a command window by clicking Start, Run, and type cmd. Navigate to the directory above (using the cd command) and run the following: python img2py.py -i myIcon.ico icon.py

Step 4: Once that’s done, copy the icon.py file to the the folder you created to hold your scripts. This will be coupled with some code that handles the iconization and right-click menus.

Now we’ll create the logic needed for the system tray icon to respond to mouse events. I found some code in the wxPython Demo that did most of what I did. So I copied it and modified it slightly to fit my needs. You can see the end result below:

import wx
from vpnIcon import getIcon
 
class VPNIconCtrl(wx.TaskBarIcon):
    TBMENU_RESTORE = wx.NewId()
    TBMENU_CLOSE   = wx.NewId()
    TBMENU_CHANGE  = wx.NewId()
 
    def __init__(self, frame):
        wx.TaskBarIcon.__init__(self)
        self.frame = frame
 
        # Set the image
        tbIcon = getIcon()
 
        # Give the icon a tooltip
        self.SetIcon(tbIcon, "VPN Status")
        self.imgidx = 1
 
        # bind some events
        self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarActivate)
        self.Bind(wx.EVT_MENU, self.OnTaskBarActivate, id=self.TBMENU_RESTORE)
        self.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=self.TBMENU_CLOSE)
 
    def CreatePopupMenu(self):
        """
        This method is called by the base class when it needs to popup
        the menu for the default EVT_RIGHT_DOWN event.  Just create
        the menu how you want it and return it from this function,
        the base class takes care of the rest.
        """
        menu = wx.Menu()
        menu.Append(self.TBMENU_RESTORE, "View Status")
        menu.AppendSeparator()
        menu.Append(self.TBMENU_CLOSE, "Close Program")
 
        return menu
 
    def OnTaskBarActivate(self, evt):
        if self.frame.IsIconized():
            self.frame.Iconize(False)
        if not self.frame.IsShown():
            self.frame.Show(True)
        self.frame.Raise()
 
    def OnTaskBarClose(self, evt):
        self.Destroy()
        self.frame.Close()

Next time, we’ll go over the win32 code you’ll need to know and in the final piece, we’ll create the GUI and put the rest of the pieces together.

Print Friendly