implemented wxNotificationMessage for wxMSW using wxTaskBarIcon and fallback to generic implementation on older systems; added wxNotificationMessage::SetFlags()
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@50429 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
420
src/msw/notifmsg.cpp
Normal file
420
src/msw/notifmsg.cpp
Normal file
@@ -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
|
Reference in New Issue
Block a user