1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/msw/notifmsg.cpp 
   3 // Purpose:     implementation of wxNotificationMessage for Windows 
   4 // Author:      Vadim Zeitlin 
   7 // Copyright:   (c) 2007 Vadim Zeitlin <vadim@wxwindows.org> 
   8 // Licence:     wxWindows licence 
   9 /////////////////////////////////////////////////////////////////////////////// 
  11 // ============================================================================ 
  13 // ============================================================================ 
  15 // ---------------------------------------------------------------------------- 
  17 // ---------------------------------------------------------------------------- 
  19 // for compilers that support precompilation, includes "wx.h". 
  20 #include "wx/wxprec.h" 
  26 // we can only use the native implementation if we have a working 
  27 // wxTaskBarIcon::ShowBalloon() method 
  28 #if wxUSE_NOTIFICATION_MESSAGE && \ 
  29         wxUSE_TASKBARICON && wxUSE_TASKBARICON_BALLOONS 
  31 #include "wx/notifmsg.h" 
  34     #include "wx/toplevel.h" 
  36     #include "wx/string.h" 
  39 #include "wx/generic/notifmsg.h" 
  41 #include "wx/taskbar.h" 
  43 // ---------------------------------------------------------------------------- 
  44 // different implementations used by wxNotificationMessage 
  45 // ---------------------------------------------------------------------------- 
  47 // base class for all available implementations 
  52     virtual ~wxNotifMsgImpl() { } 
  54     virtual bool DoShow(const wxString
& title
, 
  55                         const wxString
& message
, 
  58     virtual bool DoClose() = 0; 
  61     DECLARE_NO_COPY_CLASS(wxNotifMsgImpl
) 
  64 // implementation which is simply a bridge to wxGenericNotificationMessage 
  65 class wxGenericNotifMsgImpl 
: public wxNotifMsgImpl
 
  68     wxGenericNotifMsgImpl() : m_notif(new wxGenericNotificationMessage
) { } 
  69     virtual ~wxGenericNotifMsgImpl() { delete m_notif
; } 
  71     virtual bool DoShow(const wxString
& title
, 
  72                         const wxString
& message
, 
  76         m_notif
->SetTitle(title
); 
  77         m_notif
->SetMessage(message
); 
  78         m_notif
->SetFlags(flags
); 
  79         return m_notif
->Show(timeout
); 
  82     virtual bool DoClose() 
  84         return m_notif
->Close(); 
  88     wxGenericNotificationMessage 
* const m_notif
; 
  91 // common base class for implementations using a taskbar icon and balloons 
  92 class wxBalloonNotifMsgImpl 
: public wxNotifMsgImpl
 
  95     // ctor sets up m_icon (using the icon of the top level parent of the given 
  96     // window) which can be used to show an attached balloon later by the 
  98     wxBalloonNotifMsgImpl(wxWindow 
*win
) { SetUpIcon(win
); } 
 100     // implementation of wxNotificationMessage method with the same name 
 101     static wxTaskBarIcon 
*UseTaskBarIcon(wxTaskBarIcon 
*icon
); 
 103     virtual bool DoShow(const wxString
& title
, 
 104                         const wxString
& message
, 
 109     // sets up m_icon (doesn't do anything with the old value, caller beware) 
 110     void SetUpIcon(wxWindow 
*win
); 
 113     static wxTaskBarIcon 
*ms_iconToUse
; 
 115     // the icon we attach our notification to, either ms_iconToUse or a 
 116     // temporary one which we will destroy when done 
 117     wxTaskBarIcon 
*m_icon
; 
 119     // should be only used if m_icon != NULL and indicates whether we should 
 124 // implementation for automatically hidden notifications 
 125 class wxAutoNotifMsgImpl 
: public wxBalloonNotifMsgImpl
 
 128     wxAutoNotifMsgImpl(wxWindow 
*win
); 
 130     virtual bool DoShow(const wxString
& title
, 
 131                         const wxString
& message
, 
 135     // can't close automatic notification [currently] 
 136     virtual bool DoClose() { return false; } 
 139     // custom event handler connected to m_icon which will receive the icon 
 140     // close event and delete it and itself when it happens 
 141     wxEvtHandler 
* const m_iconEvtHandler
; 
 144 // implementation for manually closed notifications 
 145 class wxManualNotifMsgImpl 
: public wxBalloonNotifMsgImpl
 
 148     wxManualNotifMsgImpl(wxWindow 
*win
); 
 149     virtual ~wxManualNotifMsgImpl(); 
 151     virtual bool DoShow(const wxString
& title
, 
 152                         const wxString
& message
, 
 155     virtual bool DoClose(); 
 158     // store ctor parameter as we need it to recreate the icon later if we're 
 159     // closed and shown again 
 160     wxWindow 
* const m_win
; 
 163 // ---------------------------------------------------------------------------- 
 164 // custom event handler for task bar icons 
 165 // ---------------------------------------------------------------------------- 
 167 // normally we'd just use a custom taskbar icon class but this is impossible 
 168 // because we can be asked to attach the notifications to an existing icon 
 169 // which we didn't create, hence we install a special event handler allowing us 
 170 // to get the events we need (and, crucially, to delete the icon when it's not 
 171 // needed any more) in any case 
 173 class wxNotificationIconEvtHandler 
: public wxEvtHandler
 
 176     wxNotificationIconEvtHandler(wxTaskBarIcon 
*icon
); 
 179     void OnTimeout(wxTaskBarIconEvent
& event
); 
 180     void OnClick(wxTaskBarIconEvent
& event
); 
 185     wxTaskBarIcon 
* const m_icon
; 
 187     DECLARE_NO_COPY_CLASS(wxNotificationIconEvtHandler
) 
 190 // ============================================================================ 
 192 // ============================================================================ 
 194 // ---------------------------------------------------------------------------- 
 195 // wxNotificationIconEvtHandler 
 196 // ---------------------------------------------------------------------------- 
 198 wxNotificationIconEvtHandler::wxNotificationIconEvtHandler(wxTaskBarIcon 
*icon
) 
 203               wxEVT_TASKBAR_BALLOON_TIMEOUT
, 
 204               wxTaskBarIconEventHandler(wxNotificationIconEvtHandler::OnTimeout
), 
 211               wxEVT_TASKBAR_BALLOON_CLICK
, 
 212               wxTaskBarIconEventHandler(wxNotificationIconEvtHandler::OnClick
), 
 218 void wxNotificationIconEvtHandler::OnIconHidden() 
 226 wxNotificationIconEvtHandler::OnTimeout(wxTaskBarIconEvent
& WXUNUSED(event
)) 
 231 void wxNotificationIconEvtHandler::OnClick(wxTaskBarIconEvent
& WXUNUSED(event
)) 
 233     // TODO: generate an event notifying the user code? 
 238 // ---------------------------------------------------------------------------- 
 239 // wxBalloonNotifMsgImpl 
 240 // ---------------------------------------------------------------------------- 
 242 wxTaskBarIcon 
*wxBalloonNotifMsgImpl::ms_iconToUse 
= NULL
; 
 245 wxTaskBarIcon 
*wxBalloonNotifMsgImpl::UseTaskBarIcon(wxTaskBarIcon 
*icon
) 
 247     wxTaskBarIcon 
* const iconOld 
= ms_iconToUse
; 
 252 void wxBalloonNotifMsgImpl::SetUpIcon(wxWindow 
*win
) 
 256         // use an existing icon 
 258         m_icon 
= ms_iconToUse
; 
 260     else // no user-specified icon to attach to 
 262         // create our own one 
 264         m_icon 
= new wxTaskBarIcon
; 
 266         // use the icon of the associated (or main, if none) frame 
 269             win 
= wxGetTopLevelParent(win
); 
 271             win 
= wxTheApp
->GetTopWindow(); 
 274             const wxTopLevelWindow 
* const 
 275                 tlw 
= wxDynamicCast(win
, wxTopLevelWindow
); 
 277                 icon 
= tlw
->GetIcon(); 
 282             // we really must have some icon 
 283             icon 
= wxIcon(_T("wxICON_AAA")); 
 286         m_icon
->SetIcon(icon
); 
 291 wxBalloonNotifMsgImpl::DoShow(const wxString
& title
, 
 292                               const wxString
& message
, 
 296     timeout 
*= 1000; // Windows expresses timeout in milliseconds 
 298     return m_icon
->ShowBalloon(title
, message
, timeout
, flags
); 
 301 // ---------------------------------------------------------------------------- 
 302 // wxManualNotifMsgImpl 
 303 // ---------------------------------------------------------------------------- 
 305 wxManualNotifMsgImpl::wxManualNotifMsgImpl(wxWindow 
*win
) 
 306                     : wxBalloonNotifMsgImpl(win
), 
 311 wxManualNotifMsgImpl::~wxManualNotifMsgImpl() 
 318 wxManualNotifMsgImpl::DoShow(const wxString
& title
, 
 319                              const wxString
& message
, 
 320                              int WXUNUSED_UNLESS_DEBUG(timeout
), 
 323     wxASSERT_MSG( timeout 
== wxNotificationMessage::Timeout_Never
, 
 324                     _T("shouldn't be used") ); 
 326     // base class creates the icon for us initially but we could have destroyed 
 327     // it in DoClose(), recreate it if this was the case 
 331     // use maximal (in current Windows versions) timeout (but it will still 
 332     // disappear on its own) 
 333     return wxBalloonNotifMsgImpl::DoShow(title
, message
, 30, flags
); 
 336 bool wxManualNotifMsgImpl::DoClose() 
 340         // we don't need the icon any more 
 343     else // using an existing icon 
 345         // just hide the balloon 
 346         m_icon
->ShowBalloon("", ""); 
 354 // ---------------------------------------------------------------------------- 
 355 // wxAutoNotifMsgImpl 
 356 // ---------------------------------------------------------------------------- 
 358 wxAutoNotifMsgImpl::wxAutoNotifMsgImpl(wxWindow 
*win
) 
 359                   : wxBalloonNotifMsgImpl(win
), 
 360                     m_iconEvtHandler(new wxNotificationIconEvtHandler(m_icon
)) 
 365 wxAutoNotifMsgImpl::DoShow(const wxString
& title
, 
 366                            const wxString
& message
, 
 370     wxASSERT_MSG( timeout 
!= wxNotificationMessage::Timeout_Never
, 
 371                     _T("shouldn't be used") ); 
 373     if ( timeout 
== wxNotificationMessage::Timeout_Auto 
) 
 375         // choose a value more or less in the middle of the allowed range 
 379     return wxBalloonNotifMsgImpl::DoShow(title
, message
, timeout
, flags
); 
 382 // ---------------------------------------------------------------------------- 
 383 // wxNotificationMessage 
 384 // ---------------------------------------------------------------------------- 
 387 bool wxNotificationMessage::ms_alwaysUseGeneric 
= false; 
 390 wxTaskBarIcon 
*wxNotificationMessage::UseTaskBarIcon(wxTaskBarIcon 
*icon
) 
 392     return wxBalloonNotifMsgImpl::UseTaskBarIcon(icon
); 
 395 bool wxNotificationMessage::Show(int timeout
) 
 399         if ( !ms_alwaysUseGeneric 
&& wxTheApp
->GetShell32Version() >= 500 ) 
 401             if ( timeout 
== Timeout_Never 
) 
 402                 m_impl 
= new wxManualNotifMsgImpl(GetParent()); 
 404                 m_impl 
= new wxAutoNotifMsgImpl(GetParent()); 
 406         else // no support for balloon tooltips 
 408             m_impl 
= new wxGenericNotifMsgImpl
; 
 411     //else: reuse the same implementation for the subsequent calls, it would 
 412     //      be too confusing if it changed 
 414     return m_impl
->DoShow(GetTitle(), GetMessage(), timeout
, GetFlags()); 
 417 bool wxNotificationMessage::Close() 
 419     wxCHECK_MSG( m_impl
, false, "must show the notification first" ); 
 421     return m_impl
->DoClose(); 
 424 wxNotificationMessage::~wxNotificationMessage() 
 429 #endif // wxUSE_NOTIFICATION_MESSAGE && wxUSE_TASKBARICON