问题
I recently upgraded to the development release of wxPython (wxPython 2.9.2.4) since I needed the functionality of wx.NotificationMessage within my application. I have been trying unsuccessfully to create notification bubbles on certain user events due to something I think might be a possible bug. Before submitting such bug, I wanted to go ahead and ask the people of the mailing list what they think might be the problem and hopefully find a solution from within my code.
Here is the code I have used:
import wx, sys
app = wx.PySimpleApp()
class TestTaskBarIcon(wx.TaskBarIcon):
def __init__(self):
wx.TaskBarIcon.__init__(self)
# create a test icon
bmp = wx.EmptyBitmap(16, 16)
dc = wx.MemoryDC(bmp)
dc.SetBrush(wx.RED_BRUSH)
dc.Clear()
dc.SelectObject(wx.NullBitmap)
testicon = wx.EmptyIcon()
testicon.CopyFromBitmap(bmp)
self.SetIcon(testicon)
self.Bind(wx.EVT_TASKBAR_LEFT_UP, lambda e: (self.RemoveIcon(),sys.exit()))
wx.NotificationMessage("", "Hello world!").Show()
icon = TestTaskBarIcon()
app.MainLoop()
On my Windows 7 computer, the code creates a small white task bar icon and creates a popup with the phrase "Hello World!". The problem? The message is not on my icon. Another icon is being created and the message is being placed there. See this image: http://www.pasteall.org/pic/18068">
What I thought was that this is probably due to the fact that I have passed no parent parameter on line 22:
wx.NotificationMessage("", "Hello world!").Show()
Here is what I changed it to:
wx.NotificationMessage("", "Hello world!", self).Show()
Where 'self' refers to the task bar icon. When I do that, I get an error:
Traceback (most recent call last):
File "C:\Python27\testnotificationmessage.py", line 24, in <module>
icon = TestTaskBarIcon()
File "C:\Python27\testnotificationmessage.py", line 22, in __init__
wx.NotificationMessage("", "Hello world!", self).Show()
File "C:\Python27\lib\site-packages\wx-2.9.2-msw\wx\_misc.py", line 1213, in __init__
_misc_.NotificationMessage_swiginit(self,_misc_.new_NotificationMessage(*args))
TypeError: in method 'new_NotificationMessage', expected argument 3 of type 'wxWindow *'
What's going on? If I remove that argument, I don't get my result, if I add the argument, I get an error! How am I supposed to use wx.NotificationMessage with a wx.TaskBarIcon!
Please help! I hope I've provided enough details. Please comment if you need more!
回答1:
I would not recommend using 2.9 just yet. I have encountered some strange bugs when trying it out.
You can have the same functionality in 2.8. I am using somewhat modified code that I have found some time ago.
import wx, sys
try:
import win32gui #, win32con
WIN32 = True
except:
WIN32 = False
class BalloonTaskBarIcon(wx.TaskBarIcon):
"""
Base Taskbar Icon Class
"""
def __init__(self):
wx.TaskBarIcon.__init__(self)
self.icon = None
self.tooltip = ""
def ShowBalloon(self, title, text, msec = 0, flags = 0):
"""
Show Balloon tooltip
@param title - Title for balloon tooltip
@param msg - Balloon tooltip text
@param msec - Timeout for balloon tooltip, in milliseconds
@param flags - one of wx.ICON_INFORMATION, wx.ICON_WARNING, wx.ICON_ERROR
"""
if WIN32 and self.IsIconInstalled():
try:
self.__SetBalloonTip(self.icon.GetHandle(), title, text, msec, flags)
except Exception:
pass # print(e) Silent error
def __SetBalloonTip(self, hicon, title, msg, msec, flags):
# translate flags
infoFlags = 0
if flags & wx.ICON_INFORMATION:
infoFlags |= win32gui.NIIF_INFO
elif flags & wx.ICON_WARNING:
infoFlags |= win32gui.NIIF_WARNING
elif flags & wx.ICON_ERROR:
infoFlags |= win32gui.NIIF_ERROR
# Show balloon
lpdata = (self.__GetIconHandle(), # hWnd
99, # ID
win32gui.NIF_MESSAGE|win32gui.NIF_INFO|win32gui.NIF_ICON, # flags: Combination of NIF_* flags
0, # CallbackMessage: Message id to be pass to hWnd when processing messages
hicon, # hIcon: Handle to the icon to be displayed
'', # Tip: Tooltip text
msg, # Info: Balloon tooltip text
msec, # Timeout: Timeout for balloon tooltip, in milliseconds
title, # InfoTitle: Title for balloon tooltip
infoFlags # InfoFlags: Combination of NIIF_* flags
)
win32gui.Shell_NotifyIcon(win32gui.NIM_MODIFY, lpdata)
self.SetIcon(self.icon, self.tooltip) # Hack: because we have no access to the real CallbackMessage value
def __GetIconHandle(self):
"""
Find the icon window.
This is ugly but for now there is no way to find this window directly from wx
"""
if not hasattr(self, "_chwnd"):
try:
for handle in wx.GetTopLevelWindows():
if handle.GetWindowStyle():
continue
handle = handle.GetHandle()
if len(win32gui.GetWindowText(handle)) == 0:
self._chwnd = handle
break
if not hasattr(self, "_chwnd"):
raise Exception
except:
raise Exception, "Icon window not found"
return self._chwnd
def SetIcon(self, icon, tooltip = ""):
self.icon = icon
self.tooltip = tooltip
wx.TaskBarIcon.SetIcon(self, icon, tooltip)
def RemoveIcon(self):
self.icon = None
self.tooltip = ""
wx.TaskBarIcon.RemoveIcon(self)
# ===================================================================
app = wx.PySimpleApp()
class TestTaskBarIcon(BalloonTaskBarIcon):
def __init__(self):
wx.TaskBarIcon.__init__(self)
# create a test icon
bmp = wx.EmptyBitmap(16, 16)
dc = wx.MemoryDC(bmp)
dc.SetBrush(wx.RED_BRUSH)
dc.Clear()
dc.SelectObject(wx.NullBitmap)
testicon = wx.EmptyIcon()
testicon.CopyFromBitmap(bmp)
self.SetIcon(testicon)
self.Bind(wx.EVT_TASKBAR_LEFT_UP, lambda e: (self.RemoveIcon(),sys.exit()))
self.ShowBalloon("", "Hello world!")
icon = TestTaskBarIcon()
app.MainLoop()
回答2:
There is an undocumented hidden method in TaskBarIcon
called ShowBalloon
which is only implemented for Windows.
From the source:
def ShowBalloon(*args, **kwargs):
"""
ShowBalloon(self, String title, String text, unsigned int msec=0, int flags=0) -> bool
Show a balloon notification (the icon must have been already
initialized using SetIcon). Only implemented for Windows.
title and text are limited to 63 and 255 characters respectively, msec
is the timeout, in milliseconds, before the balloon disappears (will
be clamped down to the allowed 10-30s range by Windows if it's outside
it) and flags can include wxICON_ERROR/INFO/WARNING to show a
corresponding icon
Returns True if balloon was shown, False on error (incorrect parameters
or function unsupported by OS)
"""
return _windows_.TaskBarIcon_ShowBalloon(*args, **kwargs)
I tested it on Windows with wxPython 2.9.4.0 and it works well.
来源:https://stackoverflow.com/questions/7523511/unable-to-use-wx-notificationmessage-properly-with-wxpython