]> git.saurik.com Git - wxWidgets.git/commitdiff
implemented wxNotificationMessage for wxMSW using wxTaskBarIcon and fallback to gener...
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 2 Dec 2007 17:02:30 +0000 (17:02 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 2 Dec 2007 17:02:30 +0000 (17:02 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@50429 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/latex/wx/notifmsg.tex
include/wx/generic/notifmsg.h
include/wx/msw/notifmsg.h [new file with mode: 0644]
include/wx/notifmsg.h
src/generic/notifmsgg.cpp
src/msw/notifmsg.cpp [new file with mode: 0644]

index 5c4444260242ce57d2cd7026540ece358b812d52..840c15c29f1747130d984b6e6690a3ff831c0f31 100644 (file)
@@ -3,7 +3,7 @@
 %% Purpose:     wxNotificationMessage documentation
 %% Author:      Vadim Zeitlin
 %% Created:     2007-11-24
-%% RCS-ID:      $Id: cmdlpars.tex 49199 2007-10-17 17:32:16Z VZ $
+%% RCS-ID:      $Id$
 %% Copyright:   (c) 2007 Vadim Zeitlin <vadim@wxwidgets.org>
 %% License:     wxWindows license
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -39,10 +39,15 @@ Default constructor, use \helpref{SetParent}{wxnotificationmessagesetparent},
 before showing it.
 
 
-\func{}{wxNotificationMessage}{\param{const wxString\& }{title}, \param{const wxString\& }{message = wxString()}, \param{wxWindow* }{parent = NULL}}
+\func{}{wxNotificationMessage}{\param{const wxString\& }{title}, \param{const wxString\& }{message = wxString()}, \param{wxWindow* }{parent = NULL}, \parent{int }{flags = \texttt{wxICON\_INFORMATION}}
 
-Create a notification object with the given title and message (the
-latter may be empty in which case only the title will be shown).
+Create a notification object with the given attributes.
+
+See \helpref{SetTitle}{wxnotificationmessagesettitle}, 
+\helpref{SetMessage}{wxnotificationmessagesetmessage}, 
+\helpref{SetParent}{wxnotificationmessagesetparent} and
+\helpref{SetFlags}{wxnotificationmessagesetflags} for the description of the
+corresponding parameters.
 
 
 \membersection{wxNotificationMessage::Close}\label{wxnotificationmessageclose}
@@ -55,11 +60,25 @@ Returns \true if it was hidden or \false if it couldn't be done (e.g. on some
 systems automatically hidden notifications can't be hidden manually)
 
 
+\membersection{wxNotificationMessage::SetFlags}\label{wxnotificationmessagesetflags}
+
+\func{void}{SetFlags}{\param{int }{flags}}
+
+This parameter can be currently used to specify the icon to show in the
+notification. Valid values are \texttt{wxICON\_INFORMATION}, 
+\texttt{wxICON\_WARNING} and \texttt{wxICON\_ERROR} (notice that 
+\texttt{wxICON\_QUESTION} is not allowed here).
+
+Some implementations of this class may not support the icons.
+
+
 \membersection{wxNotificationMessage::SetMessage}\label{wxnotificationmessagesetmessage}
 
 \func{void}{SetMessage}{\param{const wxString\& }{message}}
 
-Set the main text of the notification.
+Set the main text of the notification. This should be a more detailed
+description than the title but still limited to reasonable length (not more
+than 256 characters).
 
 
 \membersection{wxNotificationMessage::SetParent}\label{wxnotificationmessagesetparent}
@@ -75,7 +94,7 @@ main application window by default
 
 \func{void}{SetTitle}{\param{const wxString\& }{title}}
 
-Set the title, it must be a concise string, use 
+Set the title, it must be a concise string (not more than 64 characters), use 
 \helpref{SetMessage}{wxnotificationmessagesetmessage} to give the user more
 details.
 
index e4beca030ea756fea6e1a7a4709250ea0b92072f..bfa2d7214e361978f7376e786142952a71086985 100644 (file)
@@ -1,6 +1,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // Name:        wx/generic/notifmsg.h
-// Purpose:     generic implementation of wxNotificationMessage
+// Purpose:     generic implementation of wxGenericNotificationMessage
 // Author:      Vadim Zeitlin
 // Created:     2007-11-24
 // RCS-ID:      $Id$
 class wxNotificationMessageDialog;
 
 // ----------------------------------------------------------------------------
-// wxNotificationMessage
+// wxGenericNotificationMessage
 // ----------------------------------------------------------------------------
 
-class WXDLLIMPEXP_ADV wxNotificationMessage : public wxNotificationMessageBase
+class WXDLLIMPEXP_ADV wxGenericNotificationMessage : public wxNotificationMessageBase
 {
 public:
-    wxNotificationMessage() { Init(); }
-    wxNotificationMessage(const wxString& title,
-                          const wxString& message = wxString(),
-                          wxWindow *parent = NULL)
+    wxGenericNotificationMessage() { Init(); }
+    wxGenericNotificationMessage(const wxString& title,
+                                 const wxString& message = wxString(),
+                                 wxWindow *parent = NULL)
         : wxNotificationMessageBase(title, message, parent)
     {
         Init();
     }
 
-    virtual ~wxNotificationMessage();
+    virtual ~wxGenericNotificationMessage();
 
 
     virtual bool Show(int timeout = Timeout_Auto);
@@ -53,7 +53,7 @@ private:
     wxNotificationMessageDialog *m_dialog;
 
 
-    DECLARE_NO_COPY_CLASS(wxNotificationMessage)
+    DECLARE_NO_COPY_CLASS(wxGenericNotificationMessage)
 };
 
 #endif // _WX_GENERIC_NOTIFMSG_H_
diff --git a/include/wx/msw/notifmsg.h b/include/wx/msw/notifmsg.h
new file mode 100644 (file)
index 0000000..0928ea7
--- /dev/null
@@ -0,0 +1,64 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        wx/msw/notifmsg.h
+// Purpose:     implementation of wxNotificationMessage for Windows
+// Author:      Vadim Zeitlin
+// Created:     2007-12-01
+// RCS-ID:      $Id$
+// Copyright:   (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
+// Licence:     wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_MSW_NOTIFMSG_H_
+#define _WX_MSW_NOTIFMSG_H_
+
+class WXDLLIMPEXP_FWD_ADV wxTaskBarIcon;
+
+// ----------------------------------------------------------------------------
+// wxNotificationMessage
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_ADV wxNotificationMessage : public wxNotificationMessageBase
+{
+public:
+    wxNotificationMessage() { Init(); }
+    wxNotificationMessage(const wxString& title,
+                          const wxString& message = wxString(),
+                          wxWindow *parent = NULL)
+        : wxNotificationMessageBase(title, message, parent)
+    {
+        Init();
+    }
+
+    virtual ~wxNotificationMessage();
+
+
+    virtual bool Show(int timeout = Timeout_Auto);
+    virtual bool Close();
+
+    // MSW implementation-specific methods
+
+    // by default, wxNotificationMessage under MSW creates a temporary taskbar
+    // icon to which it attaches the notification, if there is an existing
+    // taskbar icon object in the application you may want to call this method
+    // to attach the notification to it instead (we won't take ownership of it
+    // and you can also pass NULL to not use the icon for notifications any
+    // more)
+    //
+    // returns the task bar icon which was used previously (may be NULL)
+    static wxTaskBarIcon *UseTaskBarIcon(wxTaskBarIcon *icon);
+
+private:
+    // common part of all ctors
+    void Init() { m_impl = NULL; }
+
+
+    // the real implementation of this class (selected during run-time because
+    // the balloon task bar icons are not available in all Windows versions)
+    class wxNotifMsgImpl *m_impl;
+
+
+    DECLARE_NO_COPY_CLASS(wxNotificationMessage)
+};
+
+#endif // _WX_MSW_NOTIFMSG_H_
+
index 532b258be2b436c69507da283cd4d212279ed447..08f0672c2fa3202306a4e023abcff521d1693d97 100644 (file)
@@ -28,17 +28,23 @@ public:
     // ----------------------
 
     // default ctor, use setters below to initialize it later
-    wxNotificationMessageBase() { }
+    wxNotificationMessageBase()
+    {
+        m_parent = NULL;
+        m_flags = wxICON_INFORMATION;
+    }
 
     // create a notification object with the given title and message (the
     // latter may be empty in which case only the title will be shown)
     wxNotificationMessageBase(const wxString& title,
                               const wxString& message = wxString(),
-                              wxWindow *parent = NULL)
+                              wxWindow *parent = NULL,
+                              int flags = wxICON_INFORMATION)
         : m_title(title),
           m_message(message),
           m_parent(parent)
     {
+        SetFlags(flags);
     }
 
     // note that the setters must be called before Show()
@@ -55,6 +61,18 @@ public:
     // main application window by default
     void SetParent(wxWindow *parent) { m_parent = parent; }
 
+    // this method can currently be used to choose a standard icon to use: the
+    // parameter may be one of wxICON_INFORMATION, wxICON_WARNING or
+    // wxICON_ERROR only (but not wxICON_QUESTION)
+    void SetFlags(int flags)
+    {
+        wxASSERT_MSG( flags == wxICON_INFORMATION ||
+                        flags == wxICON_WARNING || flags == wxICON_ERROR,
+                            "Invalid icon flags specified" );
+
+        m_flags = flags;
+    }
+
 
     // showing and hiding
     // ------------------
@@ -82,6 +100,7 @@ protected:
     const wxString& GetTitle() const { return m_title; }
     const wxString& GetMessage() const { return m_message; }
     wxWindow *GetParent() const { return m_parent; }
+    int GetFlags() const { return m_flags; }
 
     // return the concatenation of title and message separated by a new line,
     // this is suitable for simple implementation which have no support for
@@ -103,26 +122,35 @@ private:
 
     wxWindow *m_parent;
 
+    int m_flags;
+
     DECLARE_NO_COPY_CLASS(wxNotificationMessageBase)
 };
 
-#define wxUSE_GENERIC_NOTIFICATION_MESSAGE 1
-
 #if defined(__WXGTK__) && wxUSE_LIBHILDON
-    // we always use the native implementation in Hildon while the other ports
-    // will fall back to the generic one even if they have a native version too
-    #undef wxUSE_GENERIC_NOTIFICATION_MESSAGE
-    #define wxUSE_GENERIC_NOTIFICATION_MESSAGE 0
-
     #include "wx/gtk/hildon/notifmsg.h"
 /*
     TODO: provide support for
         - libnotify (Gnome)
-        - Snarl (http://www.fullphat.net/, Win32)
         - Growl (http://growl.info/, OS X)
  */
+#elif defined(__WXMSW__) && wxUSE_TASKBARICON
+    #include "wx/msw/notifmsg.h"
 #else
     #include "wx/generic/notifmsg.h"
+
+    class wxNotificationMessage : public wxGenericNotificationMessage
+    {
+    public:
+        wxNotificationMessage() { }
+        wxNotificationMessage(const wxString& title,
+                              const wxString& message = wxString(),
+                              wxWindow *parent = NULL,
+                              int flags = wxICON_INFORMATION)
+            : wxGenericNotificationMessage(title, message, parent, flags)
+        {
+        }
+    };
 #endif
 
 #endif // wxUSE_NOTIFICATION_MESSAGE
index 2f95e1ca7659fcd420fd12561e4a9eb60ff25490..4bc3ecf1aefe17623c13c5070e1143610afc7fdc 100644 (file)
@@ -1,6 +1,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // Name:        src/generic/notifmsgg.cpp
-// Purpose:     generic implementation of wxNotificationMessage
+// Purpose:     generic implementation of wxGenericNotificationMessage
 // Author:      Vadim Zeitlin
 // Created:     2007-11-24
 // RCS-ID:      $Id$
     #pragma hdrstop
 #endif
 
-// include this before the test below, wxUSE_GENERIC_NOTIFICATION_MESSAGE is
-// defined in this header
-#include "wx/notifmsg.h"
+#ifndef wxUSE_LIBHILDON
+    #define wxUSE_LIBHILDON 0
+#endif
 
-#if wxUSE_GENERIC_NOTIFICATION_MESSAGE
+#if wxUSE_NOTIFICATION_MESSAGE && !wxUSE_LIBHILDON
 
 #ifndef WX_PRECOMP
     #include "wx/dialog.h"
     #include "wx/timer.h"
 #endif //WX_PRECOMP
 
+// even if the platform has the native implementation, we still normally want
+// to use the generic one (unless it's totally unsuitable for the target UI as
+// is the case of Hildon) because it may provide more features, so include
+// wx/generic/notifmsg.h to get wxGenericNotificationMessage declaration even
+// if wx/notifmsg.h only declares wxNotificationMessage itself (if it already
+// uses the generic version, the second inclusion will do no harm)
+#include "wx/notifmsg.h"
+#include "wx/generic/notifmsg.h"
+
 // ----------------------------------------------------------------------------
 // wxNotificationMessageDialog
 // ----------------------------------------------------------------------------
@@ -100,7 +109,7 @@ wxNotificationMessageDialog::Set(wxWindow * WXUNUSED(parent),
     wxSizer *sizer = CreateTextSizer(text);
     SetSizerAndFit(sizer);
 
-    if ( timeout != wxNotificationMessage::Timeout_Never )
+    if ( timeout != wxGenericNotificationMessage::Timeout_Never )
     {
         // wxTimer uses ms, timeout is in seconds
         m_timer.Start(timeout*1000, true /* one shot only */);
@@ -135,12 +144,12 @@ void wxNotificationMessageDialog::OnTimer(wxTimerEvent& WXUNUSED(event))
 }
 
 // ============================================================================
-// wxNotificationMessage implementation
+// wxGenericNotificationMessage implementation
 // ============================================================================
 
-int wxNotificationMessage::ms_timeout = 10;
+int wxGenericNotificationMessage::ms_timeout = 10;
 
-/* static */ void wxNotificationMessage::SetDefaultTimeout(int timeout)
+/* static */ void wxGenericNotificationMessage::SetDefaultTimeout(int timeout)
 {
     wxASSERT_MSG( timeout > 0,
                 "negative or zero default timeout doesn't make sense" );
@@ -148,17 +157,17 @@ int wxNotificationMessage::ms_timeout = 10;
     ms_timeout = timeout;
 }
 
-void wxNotificationMessage::Init()
+void wxGenericNotificationMessage::Init()
 {
     m_dialog = NULL;
 }
 
-wxNotificationMessage::~wxNotificationMessage()
+wxGenericNotificationMessage::~wxGenericNotificationMessage()
 {
     if ( m_dialog->IsAutomatic() )
     {
         // we want to allow the user to create an automatically hidden
-        // notification just by creating a local wxNotificationMessage object
+        // notification just by creating a local wxGenericNotificationMessage object
         // and so we shouldn't hide the notification when this object goes out
         // of scope
         m_dialog->SetDeleteOnHide();
@@ -172,7 +181,7 @@ wxNotificationMessage::~wxNotificationMessage()
     }
 }
 
-bool wxNotificationMessage::Show(int timeout)
+bool wxGenericNotificationMessage::Show(int timeout)
 {
     if ( timeout == Timeout_Auto )
     {
@@ -198,7 +207,7 @@ bool wxNotificationMessage::Show(int timeout)
     return true;
 }
 
-bool wxNotificationMessage::Close()
+bool wxGenericNotificationMessage::Close()
 {
     if ( !m_dialog )
         return false;
@@ -208,4 +217,4 @@ bool wxNotificationMessage::Close()
     return true;
 }
 
-#endif // wxUSE_GENERIC_NOTIFICATION_MESSAGE
+#endif // wxUSE_NOTIFICATION_MESSAGE && !wxUSE_LIBHILDON
diff --git a/src/msw/notifmsg.cpp b/src/msw/notifmsg.cpp
new file mode 100644 (file)
index 0000000..136a1bc
--- /dev/null
@@ -0,0 +1,420 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        src/msw/notifmsg.cpp
+// Purpose:     implementation of wxNotificationMessage for Windows
+// Author:      Vadim Zeitlin
+// Created:     2007-12-01
+// RCS-ID:      $Id$
+// Copyright:   (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
+// Licence:     wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// for compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#if wxUSE_NOTIFICATION_MESSAGE && wxUSE_TASKBARICON
+
+#ifndef WX_PRECOMP
+    #include "wx/string.h"
+#endif // WX_PRECOMP
+
+#include "wx/notifmsg.h"
+#include "wx/generic/notifmsg.h"
+
+#include "wx/taskbar.h"
+
+// ----------------------------------------------------------------------------
+// different implementations used by wxNotificationMessage
+// ----------------------------------------------------------------------------
+
+// base class for all available implementations
+class wxNotifMsgImpl
+{
+public:
+    wxNotifMsgImpl() { }
+    virtual ~wxNotifMsgImpl() { }
+
+    virtual bool DoShow(const wxString& title,
+                        const wxString& message,
+                        int timeout,
+                        int flags) = 0;
+    virtual bool DoClose() = 0;
+
+private:
+    DECLARE_NO_COPY_CLASS(wxNotifMsgImpl)
+};
+
+// implementation which is simply a bridge to wxGenericNotificationMessage
+class wxGenericNotifMsgImpl : public wxNotifMsgImpl
+{
+public:
+    wxGenericNotifMsgImpl() : m_notif(new wxGenericNotificationMessage) { }
+    virtual ~wxGenericNotifMsgImpl() { delete m_notif; }
+
+    virtual bool DoShow(const wxString& title,
+                        const wxString& message,
+                        int timeout,
+                        int flags)
+    {
+        m_notif->SetTitle(title);
+        m_notif->SetMessage(message);
+        m_notif->SetFlags(flags);
+        return m_notif->Show(timeout);
+    }
+
+    virtual bool DoClose()
+    {
+        return m_notif->Close();
+    }
+
+private:
+    wxGenericNotificationMessage * const m_notif;
+};
+
+// common base class for implementations using a taskbar icon and balloons
+class wxBalloonNotifMsgImpl : public wxNotifMsgImpl
+{
+public:
+    // ctor sets up m_icon (using the icon of the top level parent of the given
+    // window) which can be used to show an attached balloon later by the
+    // derived classes
+    wxBalloonNotifMsgImpl(wxWindow *win) { SetUpIcon(win); }
+
+    // implementation of wxNotificationMessage method with the same name
+    static wxTaskBarIcon *UseTaskBarIcon(wxTaskBarIcon *icon);
+
+    virtual bool DoShow(const wxString& title,
+                        const wxString& message,
+                        int timeout,
+                        int flags);
+
+protected:
+    // sets up m_icon (doesn't do anything with the old value, caller beware)
+    void SetUpIcon(wxWindow *win);
+
+
+    static wxTaskBarIcon *ms_iconToUse;
+
+    // the icon we attach our notification to, either ms_iconToUse or a
+    // temporary one which we will destroy when done
+    wxTaskBarIcon *m_icon;
+
+    // should be only used if m_icon != NULL and indicates whether we should
+    // delete it
+    bool m_ownsIcon;
+};
+
+// implementation for automatically hidden notifications
+class wxAutoNotifMsgImpl : public wxBalloonNotifMsgImpl
+{
+public:
+    wxAutoNotifMsgImpl(wxWindow *win);
+
+    virtual bool DoShow(const wxString& title,
+                        const wxString& message,
+                        int timeout,
+                        int flags);
+
+    // can't close automatic notification [currently]
+    virtual bool DoClose() { return false; }
+
+private:
+    // custom event handler connected to m_icon which will receive the icon
+    // close event and delete it and itself when it happens
+    wxEvtHandler * const m_iconEvtHandler;
+};
+
+// implementation for manually closed notifications
+class wxManualNotifMsgImpl : public wxBalloonNotifMsgImpl
+{
+public:
+    wxManualNotifMsgImpl(wxWindow *win);
+    virtual ~wxManualNotifMsgImpl();
+
+    virtual bool DoShow(const wxString& title,
+                        const wxString& message,
+                        int timeout,
+                        int flags);
+    virtual bool DoClose();
+
+private:
+    // store ctor parameter as we need it to recreate the icon later if we're
+    // closed and shown again
+    wxWindow * const m_win;
+};
+
+// ----------------------------------------------------------------------------
+// custom event handler for task bar icons
+// ----------------------------------------------------------------------------
+
+// normally we'd just use a custom taskbar icon class but this is impossible
+// because we can be asked to attach the notifications to an existing icon
+// which we didn't create, hence we install a special event handler allowing us
+// to get the events we need (and, crucially, to delete the icon when it's not
+// needed any more) in any case
+
+class wxNotificationIconEvtHandler : public wxEvtHandler
+{
+public:
+    wxNotificationIconEvtHandler(wxTaskBarIcon *icon);
+
+private:
+    void OnTimeout(wxTaskBarIconEvent& event);
+    void OnClick(wxTaskBarIconEvent& event);
+
+    void OnIconHidden();
+
+
+    wxTaskBarIcon * const m_icon;
+
+    DECLARE_NO_COPY_CLASS(wxNotificationIconEvtHandler)
+};
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxNotificationIconEvtHandler
+// ----------------------------------------------------------------------------
+
+wxNotificationIconEvtHandler::wxNotificationIconEvtHandler(wxTaskBarIcon *icon)
+                            : m_icon(icon)
+{
+    m_icon->Connect
+            (
+              wxEVT_TASKBAR_BALLOON_TIMEOUT,
+              wxTaskBarIconEventHandler(wxNotificationIconEvtHandler::OnTimeout),
+              NULL,
+              this
+            );
+
+    m_icon->Connect
+            (
+              wxEVT_TASKBAR_BALLOON_CLICK,
+              wxTaskBarIconEventHandler(wxNotificationIconEvtHandler::OnTimeout),
+              NULL,
+              this
+            );
+}
+
+void wxNotificationIconEvtHandler::OnIconHidden()
+{
+    delete m_icon;
+
+    delete this;
+}
+
+void
+wxNotificationIconEvtHandler::OnTimeout(wxTaskBarIconEvent& WXUNUSED(event))
+{
+    OnIconHidden();
+}
+
+void wxNotificationIconEvtHandler::OnClick(wxTaskBarIconEvent& WXUNUSED(event))
+{
+    // TODO: generate an event notifying the user code?
+
+    OnIconHidden();
+}
+
+// ----------------------------------------------------------------------------
+// wxBalloonNotifMsgImpl
+// ----------------------------------------------------------------------------
+
+wxTaskBarIcon *wxBalloonNotifMsgImpl::ms_iconToUse = NULL;
+
+/* static */
+wxTaskBarIcon *wxBalloonNotifMsgImpl::UseTaskBarIcon(wxTaskBarIcon *icon)
+{
+    wxTaskBarIcon * const iconOld = ms_iconToUse;
+    ms_iconToUse = icon;
+    return iconOld;
+}
+
+void wxBalloonNotifMsgImpl::SetUpIcon(wxWindow *win)
+{
+    if ( ms_iconToUse )
+    {
+        // use an existing icon
+        m_ownsIcon = false;
+        m_icon = ms_iconToUse;
+    }
+    else // no user-specified icon to attach to
+    {
+        // create our own one
+        m_ownsIcon = true;
+        m_icon = new wxTaskBarIcon;
+
+        // use the icon of the associated (or main, if none) frame
+        wxIcon icon;
+        if ( win )
+            win = wxGetTopLevelParent(win);
+        if ( !win )
+            win = wxTheApp->GetTopWindow();
+        if ( win )
+        {
+            const wxTopLevelWindow * const
+                tlw = wxDynamicCast(win, wxTopLevelWindow);
+            if ( tlw )
+                icon = tlw->GetIcon();
+        }
+
+        if ( !icon.IsOk() )
+        {
+            // we really must have some icon
+            icon = wxIcon(_T("wxICON_AAA"));
+        }
+
+        m_icon->SetIcon(icon);
+    }
+}
+
+bool
+wxBalloonNotifMsgImpl::DoShow(const wxString& title,
+                              const wxString& message,
+                              int timeout,
+                              int flags)
+{
+    timeout *= 1000; // Windows expresses timeout in milliseconds
+
+    return m_icon->ShowBalloon(title, message, timeout, flags);
+}
+
+// ----------------------------------------------------------------------------
+// wxManualNotifMsgImpl
+// ----------------------------------------------------------------------------
+
+wxManualNotifMsgImpl::wxManualNotifMsgImpl(wxWindow *win)
+                    : wxBalloonNotifMsgImpl(win),
+                      m_win(win)
+{
+}
+
+wxManualNotifMsgImpl::~wxManualNotifMsgImpl()
+{
+    if ( m_icon )
+        DoClose();
+}
+
+bool
+wxManualNotifMsgImpl::DoShow(const wxString& title,
+                             const wxString& message,
+                             int timeout,
+                             int flags)
+{
+    wxASSERT_MSG( timeout == wxNotificationMessage::Timeout_Never,
+                    _T("shouldn't be used") );
+
+    // base class creates the icon for us initially but we could have destroyed
+    // it in DoClose(), recreate it if this was the case
+    if ( !m_icon )
+        SetUpIcon(m_win);
+
+    // use maximal (in current Windows versions) timeout (but it will still
+    // disappear on its own)
+    return wxBalloonNotifMsgImpl::DoShow(title, message, 30, flags);
+}
+
+bool wxManualNotifMsgImpl::DoClose()
+{
+    if ( m_ownsIcon )
+    {
+        // we don't need the icon any more
+        delete m_icon;
+    }
+    else // using an existing icon
+    {
+        // just hide the balloon
+        m_icon->ShowBalloon("", "");
+    }
+
+    m_icon = NULL;
+
+    return true;
+}
+
+// ----------------------------------------------------------------------------
+// wxAutoNotifMsgImpl
+// ----------------------------------------------------------------------------
+
+wxAutoNotifMsgImpl::wxAutoNotifMsgImpl(wxWindow *win)
+                  : wxBalloonNotifMsgImpl(win),
+                    m_iconEvtHandler(new wxNotificationIconEvtHandler(m_icon))
+{
+}
+
+bool
+wxAutoNotifMsgImpl::DoShow(const wxString& title,
+                           const wxString& message,
+                           int timeout,
+                           int flags)
+{
+    wxASSERT_MSG( timeout != wxNotificationMessage::Timeout_Never,
+                    _T("shouldn't be used") );
+
+    if ( timeout == wxNotificationMessage::Timeout_Auto )
+    {
+        // choose a value more or less in the middle of the allowed range
+        timeout = 1;
+    }
+
+    return wxBalloonNotifMsgImpl::DoShow(title, message, timeout, flags);
+}
+
+// ----------------------------------------------------------------------------
+// wxNotificationMessage
+// ----------------------------------------------------------------------------
+
+/* static */
+wxTaskBarIcon *wxNotificationMessage::UseTaskBarIcon(wxTaskBarIcon *icon)
+{
+    return wxBalloonNotifMsgImpl::UseTaskBarIcon(icon);
+}
+
+bool wxNotificationMessage::Show(int timeout)
+{
+    if ( !m_impl )
+    {
+        if ( wxTheApp->GetShell32Version() >= 500 )
+        {
+            if ( timeout == Timeout_Never )
+                m_impl = new wxManualNotifMsgImpl(GetParent());
+            else
+                m_impl = new wxAutoNotifMsgImpl(GetParent());
+        }
+        else // no support for balloon tooltips
+        {
+            m_impl = new wxGenericNotifMsgImpl;
+        }
+    }
+    //else: reuse the same implementation for the subsequent calls, it would
+    //      be too confusing if it changed
+
+    return m_impl->DoShow(GetTitle(), GetMessage(), timeout, GetFlags());
+}
+
+bool wxNotificationMessage::Close()
+{
+    wxCHECK_MSG( m_impl, false, "must show the notification first" );
+
+    return m_impl->DoClose();
+}
+
+wxNotificationMessage::~wxNotificationMessage()
+{
+    delete m_impl;
+}
+
+#endif // wxUSE_NOTIFICATION_MESSAGE && wxUSE_TASKBARICON