[pythonwin] popup menu problems (was: [Pythonwin] Help needed creating a Window)
Dave Kirby
dkirby at bigfoot.com
Mon Jun 14 11:53:03 EDT 1999
Thanks to Mark Hammond's help I now have an app that displays an icon
in the system tray which I can process messages from. However when I
try to create a popup menu menu for it nothing happens. The call to
PyCMenu.TrackPopupMenu doesnt display anything and never returns. I
have tried both using it to send a notify message to the window and
returning a command, but it didnt make any difference. I am unsure
whether it is a failure of my understanding of the way Windows does
these things, a bug in my code, or a problem with pythonwin.
I also have the minor problem that when I destroy the icon it doesnt
disappear until I move the mouse pointer over it. Does anyone know how
to force the system tray to redraw?
Any help would be greatly appreciated.
Dave K
Here is the relevant code:
#--------------- 8< --------------------------------------
class Icon:
#constructor
# param: dll - handle to the dll containing the icon resources
# param: startIcon - the initial icon resource ID to display
# param: tooltip = the string to display when the cursor is over
# the icon
def __init__( self, dll, startIcon, tooltip ):
self.iconMap = {}
self.msgID = win32con.WM_USER+20
launchID = win32con.WM_USER+21
quitID = win32con.WM_USER+22
message_map = {
win32con.WM_DESTROY: self.OnDestroy,
self.msgID : self.OnTaskbarNotify,
win32con.WM_CONTEXTMENU : self.OnContextMenu,
}
#the menu_map contains the information on the popup menu
#entries -
# message ID, callback function, text string
menu_map = (
( launchID, self.OnLaunch, "Launch Browser" ),
( quitID, self.OnExit, "Exit program" )
)
self.dll = dll
#add menu commands to the message_map dictionary
for entry in menu_map:
message_map[entry[0]] = entry[1]
#define a window class for the icon handler
wc = win32gui.WNDCLASS()
hinst = wc.hInstance = win32gui.GetModuleHandle(None)
wc.lpszClassName = "BaxterTaskbar"
wc.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW
wc.hCursor = win32gui.LoadCursor( 0, win32con.IDC_ARROW )
wc.hbrBackground = win32con.COLOR_WINDOW
wc.lpfnWndProc = message_map
classAtom = win32gui.RegisterClass(wc)
#create the window
style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU
self.hwnd = win32gui.CreateWindow( classAtom, "title", style,
0,0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, 0, 0, hinst,
None)
win32gui.UpdateWindow(self.hwnd)
self.cWnd = win32ui.CreateWindowFromHandle( self.hwnd )
#initialise the icon display
icon = win32gui.LoadIcon( 0, win32con.IDI_APPLICATION )
flags = win32gui.NIF_ICON \
| win32gui.NIF_MESSAGE \
| win32gui.NIF_TIP
nid = (self.hwnd, 0, flags, self.msgID, icon, tooltip)
win32gui.Shell_NotifyIcon(win32gui.NIM_ADD, nid)
self.changeIcon( startIcon )
#initialise the popup menu
self.cMenu = win32ui.CreateMenu()
for entry in menu_map:
self.cMenu.AppendMenu( win32con.MF_STRING, entry[0],
entry[2] )
####################################
# this is the bit that actually calls the popup menu
####################################
def OnTaskbarNotify(self, hwnd, msg, wparam, lparam):
if lparam==win32con.WM_LBUTTONDBLCLK:
print "double clicked"
elif lparam==win32con.WM_RBUTTONUP:
pos = win32api.GetCursorPos()
print "opening menu at", pos
self.cMenu.TrackPopupMenu( pos, owner=self.cWnd )
#alternative attempt returning a command:
#cmd = self.cMenu.TrackPopupMenu( pos,
# win32con.TPM_LEFTALIGN
# |win32.TPM_LEFTBUTTON
# |win32con.TPM_NONOTIFY
# |win32con.TPM_RETURNCMD, None )
print "finished popup menu"
return 1
#the following methods are included for completeness, but are not
# part of the problem
#change to a new icon - if hasnt been loaded then do so, otherwise
#use cached icon
def changeIcon( self, iconResource ):
if self.iconMap.has_key( iconResource ):
icon = self.iconMap[iconResource]
else:
icon = win32gui.LoadIcon(self.dll, iconResource)
self.iconMap[iconResource] = icon
flags = win32gui.NIF_ICON
nid = (self.hwnd, 0, flags, 0, icon)
win32gui.Shell_NotifyIcon(win32gui.NIM_MODIFY, nid)
def changeTooltip( self, tip ):
flags = win32gui.NIF_TIP
nid = (self.hwnd, 0, flags, 0, 0, tip)
win32gui.Shell_NotifyIcon(win32gui.NIM_MODIFY, nid)
#destructor - remove icon
def __del__( self ):
nid = (self.hwnd, 0, win32gui.NIF_MESSAGE, self.msgID )
win32gui.Shell_NotifyIcon(NIM_DELETE, nid)
win32gui.UpdateWindow(self.hwnd)
def OnDestroy(self, hwnd, msg, wparam, lparam):
nid = (self.hwnd, 0, win32gui.NIF_MESSAGE, self.msgID )
win32gui.Shell_NotifyIcon(NIM_DELETE, nid)
win32gui.UpdateWindow(self.hwnd)
def OnContextMenu(self, *args):
print "Icon.OnContextMenu", args
def OnLaunch(self, *args ):
print "Icon.OnLaunch", args
def OnExit(self, *args ):
print "Icon.OnExit", args
More information about the Python-list
mailing list