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
28 #include "wx/notifmsg.h"
31 #include "wx/toplevel.h"
33 #include "wx/string.h"
36 #include "wx/generic/notifmsg.h"
38 #include "wx/taskbar.h"
40 // ----------------------------------------------------------------------------
41 // different implementations used by wxNotificationMessage
42 // ----------------------------------------------------------------------------
44 // base class for all available implementations
49 virtual ~wxNotifMsgImpl() { }
51 virtual bool DoShow(const wxString
& title
,
52 const wxString
& message
,
55 virtual bool DoClose() = 0;
58 DECLARE_NO_COPY_CLASS(wxNotifMsgImpl
)
61 // implementation which is simply a bridge to wxGenericNotificationMessage
62 class wxGenericNotifMsgImpl
: public wxNotifMsgImpl
65 wxGenericNotifMsgImpl() : m_notif(new wxGenericNotificationMessage
) { }
66 virtual ~wxGenericNotifMsgImpl() { delete m_notif
; }
68 virtual bool DoShow(const wxString
& title
,
69 const wxString
& message
,
73 m_notif
->SetTitle(title
);
74 m_notif
->SetMessage(message
);
75 m_notif
->SetFlags(flags
);
76 return m_notif
->Show(timeout
);
79 virtual bool DoClose()
81 return m_notif
->Close();
85 wxGenericNotificationMessage
* const m_notif
;
88 // common base class for implementations using a taskbar icon and balloons
89 class wxBalloonNotifMsgImpl
: public wxNotifMsgImpl
92 // ctor sets up m_icon (using the icon of the top level parent of the given
93 // window) which can be used to show an attached balloon later by the
95 wxBalloonNotifMsgImpl(wxWindow
*win
) { SetUpIcon(win
); }
97 // implementation of wxNotificationMessage method with the same name
98 static wxTaskBarIcon
*UseTaskBarIcon(wxTaskBarIcon
*icon
);
100 virtual bool DoShow(const wxString
& title
,
101 const wxString
& message
,
106 // sets up m_icon (doesn't do anything with the old value, caller beware)
107 void SetUpIcon(wxWindow
*win
);
110 static wxTaskBarIcon
*ms_iconToUse
;
112 // the icon we attach our notification to, either ms_iconToUse or a
113 // temporary one which we will destroy when done
114 wxTaskBarIcon
*m_icon
;
116 // should be only used if m_icon != NULL and indicates whether we should
121 // implementation for automatically hidden notifications
122 class wxAutoNotifMsgImpl
: public wxBalloonNotifMsgImpl
125 wxAutoNotifMsgImpl(wxWindow
*win
);
127 virtual bool DoShow(const wxString
& title
,
128 const wxString
& message
,
132 // can't close automatic notification [currently]
133 virtual bool DoClose() { return false; }
136 // custom event handler connected to m_icon which will receive the icon
137 // close event and delete it and itself when it happens
138 wxEvtHandler
* const m_iconEvtHandler
;
141 // implementation for manually closed notifications
142 class wxManualNotifMsgImpl
: public wxBalloonNotifMsgImpl
145 wxManualNotifMsgImpl(wxWindow
*win
);
146 virtual ~wxManualNotifMsgImpl();
148 virtual bool DoShow(const wxString
& title
,
149 const wxString
& message
,
152 virtual bool DoClose();
155 // store ctor parameter as we need it to recreate the icon later if we're
156 // closed and shown again
157 wxWindow
* const m_win
;
160 // ----------------------------------------------------------------------------
161 // custom event handler for task bar icons
162 // ----------------------------------------------------------------------------
164 // normally we'd just use a custom taskbar icon class but this is impossible
165 // because we can be asked to attach the notifications to an existing icon
166 // which we didn't create, hence we install a special event handler allowing us
167 // to get the events we need (and, crucially, to delete the icon when it's not
168 // needed any more) in any case
170 class wxNotificationIconEvtHandler
: public wxEvtHandler
173 wxNotificationIconEvtHandler(wxTaskBarIcon
*icon
);
176 void OnTimeout(wxTaskBarIconEvent
& event
);
177 void OnClick(wxTaskBarIconEvent
& event
);
182 wxTaskBarIcon
* const m_icon
;
184 DECLARE_NO_COPY_CLASS(wxNotificationIconEvtHandler
)
187 // ============================================================================
189 // ============================================================================
191 // ----------------------------------------------------------------------------
192 // wxNotificationIconEvtHandler
193 // ----------------------------------------------------------------------------
195 wxNotificationIconEvtHandler::wxNotificationIconEvtHandler(wxTaskBarIcon
*icon
)
200 wxEVT_TASKBAR_BALLOON_TIMEOUT
,
201 wxTaskBarIconEventHandler(wxNotificationIconEvtHandler::OnTimeout
),
208 wxEVT_TASKBAR_BALLOON_CLICK
,
209 wxTaskBarIconEventHandler(wxNotificationIconEvtHandler::OnClick
),
215 void wxNotificationIconEvtHandler::OnIconHidden()
223 wxNotificationIconEvtHandler::OnTimeout(wxTaskBarIconEvent
& WXUNUSED(event
))
228 void wxNotificationIconEvtHandler::OnClick(wxTaskBarIconEvent
& WXUNUSED(event
))
230 // TODO: generate an event notifying the user code?
235 // ----------------------------------------------------------------------------
236 // wxBalloonNotifMsgImpl
237 // ----------------------------------------------------------------------------
239 wxTaskBarIcon
*wxBalloonNotifMsgImpl::ms_iconToUse
= NULL
;
242 wxTaskBarIcon
*wxBalloonNotifMsgImpl::UseTaskBarIcon(wxTaskBarIcon
*icon
)
244 wxTaskBarIcon
* const iconOld
= ms_iconToUse
;
249 void wxBalloonNotifMsgImpl::SetUpIcon(wxWindow
*win
)
253 // use an existing icon
255 m_icon
= ms_iconToUse
;
257 else // no user-specified icon to attach to
259 // create our own one
261 m_icon
= new wxTaskBarIcon
;
263 // use the icon of the associated (or main, if none) frame
266 win
= wxGetTopLevelParent(win
);
268 win
= wxTheApp
->GetTopWindow();
271 const wxTopLevelWindow
* const
272 tlw
= wxDynamicCast(win
, wxTopLevelWindow
);
274 icon
= tlw
->GetIcon();
279 // we really must have some icon
280 icon
= wxIcon(_T("wxICON_AAA"));
283 m_icon
->SetIcon(icon
);
288 wxBalloonNotifMsgImpl::DoShow(const wxString
& title
,
289 const wxString
& message
,
293 timeout
*= 1000; // Windows expresses timeout in milliseconds
295 return m_icon
->ShowBalloon(title
, message
, timeout
, flags
);
298 // ----------------------------------------------------------------------------
299 // wxManualNotifMsgImpl
300 // ----------------------------------------------------------------------------
302 wxManualNotifMsgImpl::wxManualNotifMsgImpl(wxWindow
*win
)
303 : wxBalloonNotifMsgImpl(win
),
308 wxManualNotifMsgImpl::~wxManualNotifMsgImpl()
315 wxManualNotifMsgImpl::DoShow(const wxString
& title
,
316 const wxString
& message
,
320 wxASSERT_MSG( timeout
== wxNotificationMessage::Timeout_Never
,
321 _T("shouldn't be used") );
323 // base class creates the icon for us initially but we could have destroyed
324 // it in DoClose(), recreate it if this was the case
328 // use maximal (in current Windows versions) timeout (but it will still
329 // disappear on its own)
330 return wxBalloonNotifMsgImpl::DoShow(title
, message
, 30, flags
);
333 bool wxManualNotifMsgImpl::DoClose()
337 // we don't need the icon any more
340 else // using an existing icon
342 // just hide the balloon
343 m_icon
->ShowBalloon("", "");
351 // ----------------------------------------------------------------------------
352 // wxAutoNotifMsgImpl
353 // ----------------------------------------------------------------------------
355 wxAutoNotifMsgImpl::wxAutoNotifMsgImpl(wxWindow
*win
)
356 : wxBalloonNotifMsgImpl(win
),
357 m_iconEvtHandler(new wxNotificationIconEvtHandler(m_icon
))
362 wxAutoNotifMsgImpl::DoShow(const wxString
& title
,
363 const wxString
& message
,
367 wxASSERT_MSG( timeout
!= wxNotificationMessage::Timeout_Never
,
368 _T("shouldn't be used") );
370 if ( timeout
== wxNotificationMessage::Timeout_Auto
)
372 // choose a value more or less in the middle of the allowed range
376 return wxBalloonNotifMsgImpl::DoShow(title
, message
, timeout
, flags
);
379 // ----------------------------------------------------------------------------
380 // wxNotificationMessage
381 // ----------------------------------------------------------------------------
384 bool wxNotificationMessage::ms_alwaysUseGeneric
= false;
387 wxTaskBarIcon
*wxNotificationMessage::UseTaskBarIcon(wxTaskBarIcon
*icon
)
389 return wxBalloonNotifMsgImpl::UseTaskBarIcon(icon
);
392 bool wxNotificationMessage::Show(int timeout
)
396 if ( !ms_alwaysUseGeneric
&& wxTheApp
->GetShell32Version() >= 500 )
398 if ( timeout
== Timeout_Never
)
399 m_impl
= new wxManualNotifMsgImpl(GetParent());
401 m_impl
= new wxAutoNotifMsgImpl(GetParent());
403 else // no support for balloon tooltips
405 m_impl
= new wxGenericNotifMsgImpl
;
408 //else: reuse the same implementation for the subsequent calls, it would
409 // be too confusing if it changed
411 return m_impl
->DoShow(GetTitle(), GetMessage(), timeout
, GetFlags());
414 bool wxNotificationMessage::Close()
416 wxCHECK_MSG( m_impl
, false, "must show the notification first" );
418 return m_impl
->DoClose();
421 wxNotificationMessage::~wxNotificationMessage()
426 #endif // wxUSE_NOTIFICATION_MESSAGE && wxUSE_TASKBARICON