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 #if wxUSE_NOTIFICATION_MESSAGE && wxUSE_TASKBARICON
29 #include "wx/string.h"
32 #include "wx/notifmsg.h"
33 #include "wx/generic/notifmsg.h"
35 #include "wx/taskbar.h"
37 // ----------------------------------------------------------------------------
38 // different implementations used by wxNotificationMessage
39 // ----------------------------------------------------------------------------
41 // base class for all available implementations
46 virtual ~wxNotifMsgImpl() { }
48 virtual bool DoShow(const wxString
& title
,
49 const wxString
& message
,
52 virtual bool DoClose() = 0;
55 DECLARE_NO_COPY_CLASS(wxNotifMsgImpl
)
58 // implementation which is simply a bridge to wxGenericNotificationMessage
59 class wxGenericNotifMsgImpl
: public wxNotifMsgImpl
62 wxGenericNotifMsgImpl() : m_notif(new wxGenericNotificationMessage
) { }
63 virtual ~wxGenericNotifMsgImpl() { delete m_notif
; }
65 virtual bool DoShow(const wxString
& title
,
66 const wxString
& message
,
70 m_notif
->SetTitle(title
);
71 m_notif
->SetMessage(message
);
72 m_notif
->SetFlags(flags
);
73 return m_notif
->Show(timeout
);
76 virtual bool DoClose()
78 return m_notif
->Close();
82 wxGenericNotificationMessage
* const m_notif
;
85 // common base class for implementations using a taskbar icon and balloons
86 class wxBalloonNotifMsgImpl
: public wxNotifMsgImpl
89 // ctor sets up m_icon (using the icon of the top level parent of the given
90 // window) which can be used to show an attached balloon later by the
92 wxBalloonNotifMsgImpl(wxWindow
*win
) { SetUpIcon(win
); }
94 // implementation of wxNotificationMessage method with the same name
95 static wxTaskBarIcon
*UseTaskBarIcon(wxTaskBarIcon
*icon
);
97 virtual bool DoShow(const wxString
& title
,
98 const wxString
& message
,
103 // sets up m_icon (doesn't do anything with the old value, caller beware)
104 void SetUpIcon(wxWindow
*win
);
107 static wxTaskBarIcon
*ms_iconToUse
;
109 // the icon we attach our notification to, either ms_iconToUse or a
110 // temporary one which we will destroy when done
111 wxTaskBarIcon
*m_icon
;
113 // should be only used if m_icon != NULL and indicates whether we should
118 // implementation for automatically hidden notifications
119 class wxAutoNotifMsgImpl
: public wxBalloonNotifMsgImpl
122 wxAutoNotifMsgImpl(wxWindow
*win
);
124 virtual bool DoShow(const wxString
& title
,
125 const wxString
& message
,
129 // can't close automatic notification [currently]
130 virtual bool DoClose() { return false; }
133 // custom event handler connected to m_icon which will receive the icon
134 // close event and delete it and itself when it happens
135 wxEvtHandler
* const m_iconEvtHandler
;
138 // implementation for manually closed notifications
139 class wxManualNotifMsgImpl
: public wxBalloonNotifMsgImpl
142 wxManualNotifMsgImpl(wxWindow
*win
);
143 virtual ~wxManualNotifMsgImpl();
145 virtual bool DoShow(const wxString
& title
,
146 const wxString
& message
,
149 virtual bool DoClose();
152 // store ctor parameter as we need it to recreate the icon later if we're
153 // closed and shown again
154 wxWindow
* const m_win
;
157 // ----------------------------------------------------------------------------
158 // custom event handler for task bar icons
159 // ----------------------------------------------------------------------------
161 // normally we'd just use a custom taskbar icon class but this is impossible
162 // because we can be asked to attach the notifications to an existing icon
163 // which we didn't create, hence we install a special event handler allowing us
164 // to get the events we need (and, crucially, to delete the icon when it's not
165 // needed any more) in any case
167 class wxNotificationIconEvtHandler
: public wxEvtHandler
170 wxNotificationIconEvtHandler(wxTaskBarIcon
*icon
);
173 void OnTimeout(wxTaskBarIconEvent
& event
);
174 void OnClick(wxTaskBarIconEvent
& event
);
179 wxTaskBarIcon
* const m_icon
;
181 DECLARE_NO_COPY_CLASS(wxNotificationIconEvtHandler
)
184 // ============================================================================
186 // ============================================================================
188 // ----------------------------------------------------------------------------
189 // wxNotificationIconEvtHandler
190 // ----------------------------------------------------------------------------
192 wxNotificationIconEvtHandler::wxNotificationIconEvtHandler(wxTaskBarIcon
*icon
)
197 wxEVT_TASKBAR_BALLOON_TIMEOUT
,
198 wxTaskBarIconEventHandler(wxNotificationIconEvtHandler::OnTimeout
),
205 wxEVT_TASKBAR_BALLOON_CLICK
,
206 wxTaskBarIconEventHandler(wxNotificationIconEvtHandler::OnTimeout
),
212 void wxNotificationIconEvtHandler::OnIconHidden()
220 wxNotificationIconEvtHandler::OnTimeout(wxTaskBarIconEvent
& WXUNUSED(event
))
225 void wxNotificationIconEvtHandler::OnClick(wxTaskBarIconEvent
& WXUNUSED(event
))
227 // TODO: generate an event notifying the user code?
232 // ----------------------------------------------------------------------------
233 // wxBalloonNotifMsgImpl
234 // ----------------------------------------------------------------------------
236 wxTaskBarIcon
*wxBalloonNotifMsgImpl::ms_iconToUse
= NULL
;
239 wxTaskBarIcon
*wxBalloonNotifMsgImpl::UseTaskBarIcon(wxTaskBarIcon
*icon
)
241 wxTaskBarIcon
* const iconOld
= ms_iconToUse
;
246 void wxBalloonNotifMsgImpl::SetUpIcon(wxWindow
*win
)
250 // use an existing icon
252 m_icon
= ms_iconToUse
;
254 else // no user-specified icon to attach to
256 // create our own one
258 m_icon
= new wxTaskBarIcon
;
260 // use the icon of the associated (or main, if none) frame
263 win
= wxGetTopLevelParent(win
);
265 win
= wxTheApp
->GetTopWindow();
268 const wxTopLevelWindow
* const
269 tlw
= wxDynamicCast(win
, wxTopLevelWindow
);
271 icon
= tlw
->GetIcon();
276 // we really must have some icon
277 icon
= wxIcon(_T("wxICON_AAA"));
280 m_icon
->SetIcon(icon
);
285 wxBalloonNotifMsgImpl::DoShow(const wxString
& title
,
286 const wxString
& message
,
290 timeout
*= 1000; // Windows expresses timeout in milliseconds
292 return m_icon
->ShowBalloon(title
, message
, timeout
, flags
);
295 // ----------------------------------------------------------------------------
296 // wxManualNotifMsgImpl
297 // ----------------------------------------------------------------------------
299 wxManualNotifMsgImpl::wxManualNotifMsgImpl(wxWindow
*win
)
300 : wxBalloonNotifMsgImpl(win
),
305 wxManualNotifMsgImpl::~wxManualNotifMsgImpl()
312 wxManualNotifMsgImpl::DoShow(const wxString
& title
,
313 const wxString
& message
,
317 wxASSERT_MSG( timeout
== wxNotificationMessage::Timeout_Never
,
318 _T("shouldn't be used") );
320 // base class creates the icon for us initially but we could have destroyed
321 // it in DoClose(), recreate it if this was the case
325 // use maximal (in current Windows versions) timeout (but it will still
326 // disappear on its own)
327 return wxBalloonNotifMsgImpl::DoShow(title
, message
, 30, flags
);
330 bool wxManualNotifMsgImpl::DoClose()
334 // we don't need the icon any more
337 else // using an existing icon
339 // just hide the balloon
340 m_icon
->ShowBalloon("", "");
348 // ----------------------------------------------------------------------------
349 // wxAutoNotifMsgImpl
350 // ----------------------------------------------------------------------------
352 wxAutoNotifMsgImpl::wxAutoNotifMsgImpl(wxWindow
*win
)
353 : wxBalloonNotifMsgImpl(win
),
354 m_iconEvtHandler(new wxNotificationIconEvtHandler(m_icon
))
359 wxAutoNotifMsgImpl::DoShow(const wxString
& title
,
360 const wxString
& message
,
364 wxASSERT_MSG( timeout
!= wxNotificationMessage::Timeout_Never
,
365 _T("shouldn't be used") );
367 if ( timeout
== wxNotificationMessage::Timeout_Auto
)
369 // choose a value more or less in the middle of the allowed range
373 return wxBalloonNotifMsgImpl::DoShow(title
, message
, timeout
, flags
);
376 // ----------------------------------------------------------------------------
377 // wxNotificationMessage
378 // ----------------------------------------------------------------------------
381 wxTaskBarIcon
*wxNotificationMessage::UseTaskBarIcon(wxTaskBarIcon
*icon
)
383 return wxBalloonNotifMsgImpl::UseTaskBarIcon(icon
);
386 bool wxNotificationMessage::Show(int timeout
)
390 if ( wxTheApp
->GetShell32Version() >= 500 )
392 if ( timeout
== Timeout_Never
)
393 m_impl
= new wxManualNotifMsgImpl(GetParent());
395 m_impl
= new wxAutoNotifMsgImpl(GetParent());
397 else // no support for balloon tooltips
399 m_impl
= new wxGenericNotifMsgImpl
;
402 //else: reuse the same implementation for the subsequent calls, it would
403 // be too confusing if it changed
405 return m_impl
->DoShow(GetTitle(), GetMessage(), timeout
, GetFlags());
408 bool wxNotificationMessage::Close()
410 wxCHECK_MSG( m_impl
, false, "must show the notification first" );
412 return m_impl
->DoClose();
415 wxNotificationMessage::~wxNotificationMessage()
420 #endif // wxUSE_NOTIFICATION_MESSAGE && wxUSE_TASKBARICON