]> 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
 %% 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
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% Copyright:   (c) 2007 Vadim Zeitlin <vadim@wxwidgets.org>
 %% License:     wxWindows license
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -39,10 +39,15 @@ Default constructor, use \helpref{SetParent}{wxnotificationmessagesetparent},
 before showing it.
 
 
 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}
 
 
 \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)
 
 
 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}}
 
 \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}
 
 
 \membersection{wxNotificationMessage::SetParent}\label{wxnotificationmessagesetparent}
@@ -75,7 +94,7 @@ main application window by default
 
 \func{void}{SetTitle}{\param{const wxString\& }{title}}
 
 
 \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.
 
 \helpref{SetMessage}{wxnotificationmessagesetmessage} to give the user more
 details.
 
index e4beca030ea756fea6e1a7a4709250ea0b92072f..bfa2d7214e361978f7376e786142952a71086985 100644 (file)
@@ -1,6 +1,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // Name:        wx/generic/notifmsg.h
 ///////////////////////////////////////////////////////////////////////////////
 // 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$
 // Author:      Vadim Zeitlin
 // Created:     2007-11-24
 // RCS-ID:      $Id$
 class wxNotificationMessageDialog;
 
 // ----------------------------------------------------------------------------
 class wxNotificationMessageDialog;
 
 // ----------------------------------------------------------------------------
-// wxNotificationMessage
+// wxGenericNotificationMessage
 // ----------------------------------------------------------------------------
 
 // ----------------------------------------------------------------------------
 
-class WXDLLIMPEXP_ADV wxNotificationMessage : public wxNotificationMessageBase
+class WXDLLIMPEXP_ADV wxGenericNotificationMessage : public wxNotificationMessageBase
 {
 public:
 {
 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();
     }
 
         : wxNotificationMessageBase(title, message, parent)
     {
         Init();
     }
 
-    virtual ~wxNotificationMessage();
+    virtual ~wxGenericNotificationMessage();
 
 
     virtual bool Show(int timeout = Timeout_Auto);
 
 
     virtual bool Show(int timeout = Timeout_Auto);
@@ -53,7 +53,7 @@ private:
     wxNotificationMessageDialog *m_dialog;
 
 
     wxNotificationMessageDialog *m_dialog;
 
 
-    DECLARE_NO_COPY_CLASS(wxNotificationMessage)
+    DECLARE_NO_COPY_CLASS(wxGenericNotificationMessage)
 };
 
 #endif // _WX_GENERIC_NOTIFMSG_H_
 };
 
 #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
     // ----------------------
 
     // 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(),
 
     // 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)
     {
         : m_title(title),
           m_message(message),
           m_parent(parent)
     {
+        SetFlags(flags);
     }
 
     // note that the setters must be called before Show()
     }
 
     // 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; }
 
     // 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
     // ------------------
 
     // 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; }
     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
 
     // 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;
 
 
     wxWindow *m_parent;
 
+    int m_flags;
+
     DECLARE_NO_COPY_CLASS(wxNotificationMessageBase)
 };
 
     DECLARE_NO_COPY_CLASS(wxNotificationMessageBase)
 };
 
-#define wxUSE_GENERIC_NOTIFICATION_MESSAGE 1
-
 #if defined(__WXGTK__) && wxUSE_LIBHILDON
 #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)
     #include "wx/gtk/hildon/notifmsg.h"
 /*
     TODO: provide support for
         - libnotify (Gnome)
-        - Snarl (http://www.fullphat.net/, Win32)
         - Growl (http://growl.info/, OS X)
  */
         - Growl (http://growl.info/, OS X)
  */
+#elif defined(__WXMSW__) && wxUSE_TASKBARICON
+    #include "wx/msw/notifmsg.h"
 #else
     #include "wx/generic/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
 #endif
 
 #endif // wxUSE_NOTIFICATION_MESSAGE
index 2f95e1ca7659fcd420fd12561e4a9eb60ff25490..4bc3ecf1aefe17623c13c5070e1143610afc7fdc 100644 (file)
@@ -1,6 +1,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // Name:        src/generic/notifmsgg.cpp
 ///////////////////////////////////////////////////////////////////////////////
 // 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$
 // Author:      Vadim Zeitlin
 // Created:     2007-11-24
 // RCS-ID:      $Id$
     #pragma hdrstop
 #endif
 
     #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
 
 
 #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
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // wxNotificationMessageDialog
 // ----------------------------------------------------------------------------
@@ -100,7 +109,7 @@ wxNotificationMessageDialog::Set(wxWindow * WXUNUSED(parent),
     wxSizer *sizer = CreateTextSizer(text);
     SetSizerAndFit(sizer);
 
     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 */);
     {
         // 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" );
 {
     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;
 }
 
     ms_timeout = timeout;
 }
 
-void wxNotificationMessage::Init()
+void wxGenericNotificationMessage::Init()
 {
     m_dialog = NULL;
 }
 
 {
     m_dialog = NULL;
 }
 
-wxNotificationMessage::~wxNotificationMessage()
+wxGenericNotificationMessage::~wxGenericNotificationMessage()
 {
     if ( m_dialog->IsAutomatic() )
     {
         // we want to allow the user to create an automatically hidden
 {
     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();
         // 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 )
     {
 {
     if ( timeout == Timeout_Auto )
     {
@@ -198,7 +207,7 @@ bool wxNotificationMessage::Show(int timeout)
     return true;
 }
 
     return true;
 }
 
-bool wxNotificationMessage::Close()
+bool wxGenericNotificationMessage::Close()
 {
     if ( !m_dialog )
         return false;
 {
     if ( !m_dialog )
         return false;
@@ -208,4 +217,4 @@ bool wxNotificationMessage::Close()
     return true;
 }
 
     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