unified wxTaskBarIcon behaviour: wxMSW version is not removed automatically when all frames are closed, it must be destroyed explicitly

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@26318 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Václav Slavík 2004-03-23 23:20:16 +00:00
parent 814e9c24c2
commit 1e6d9c20fd
5 changed files with 107 additions and 163 deletions

View File

@ -39,6 +39,12 @@ INCOMPATIBLE CHANGES SINCE 2.4.x
- wxChoice and wxCombobox now handle their size in the same way as in all the
other ports under MSW, new code is actually correct but different from weird
stuff they were doing before so the behaviour of your programs might change
- wxTaskBarIcon objects must now be destroyed before the application can exit.
Previously, the application terminated if there were no top level windows;
now it terminates if there are no top level windows or taskbar icons left.
wxTaskBarIcon must be explicitly destroyed now, otherwise the application
won't exit even though there are no top level windows
DEPRECATED METHODS SINCE 2.4.x
@ -92,6 +98,8 @@ wxMSW:
- wxMenuBar::GetLabelTop() doesn't include '&'s in the label any more
- wxRegConf couldn't read global settings without admin privileges and didn't
even try to do it by default -- now it does
- wxTaskBarIcon must be explicitly destroyed now, otherwise the application
won't exit even though there are no top level windows
wxMotif:

View File

@ -3,7 +3,7 @@
// Purpose: Defines wxTaskBarIcon class for manipulating icons on the
// Windows task bar.
// Author: Julian Smart
// Modified by:
// Modified by: Vaclav Slavik
// Created: 24/3/98
// RCS-ID: $Id$
// Copyright: (c) Julian Smart
@ -17,24 +17,20 @@
#pragma interface "taskbar.h"
#endif
#include "wx/list.h"
#include "wx/icon.h"
class WXDLLIMPEXP_ADV wxTaskBarIcon;
WX_DECLARE_LIST_WITH_DECL(wxTaskBarIcon, wxTaskBarIconList,
class WXDLLIMPEXP_ADV);
// private helper class:
class WXDLLIMPEXP_ADV wxTaskBarIconWindow;
class WXDLLIMPEXP_ADV wxTaskBarIcon: public wxTaskBarIconBase
{
DECLARE_DYNAMIC_CLASS_NO_COPY(wxTaskBarIcon)
public:
wxTaskBarIcon(void);
virtual ~wxTaskBarIcon(void);
wxTaskBarIcon();
virtual ~wxTaskBarIcon();
// Accessors
inline WXHWND GetHWND() const { return m_hWnd; }
inline bool IsOk() const { return (m_hWnd != 0) ; }
inline bool IsOk() const { return true; }
inline bool IsIconInstalled() const { return m_iconAdded; }
// Operations
@ -56,21 +52,18 @@ public:
#endif
// Implementation
static wxTaskBarIcon* FindObjectForHWND(WXHWND hWnd);
static void AddObject(wxTaskBarIcon* obj);
static void RemoveObject(wxTaskBarIcon* obj);
static bool RegisterWindowClass();
static WXHWND CreateTaskBarWindow();
long WindowProc( WXHWND hWnd, unsigned int msg, unsigned int wParam, long lParam );
protected:
friend class wxTaskBarIconWindow;
long WindowProc(WXHWND hWnd, unsigned int msg,
unsigned int wParam, long lParam);
void RegisterWindowMessages();
// Data members
protected:
WXHWND m_hWnd;
bool m_iconAdded;
wxIcon m_icon;
wxString m_strTooltip;
static wxTaskBarIconList sm_taskBarIcons;
wxTaskBarIconWindow *m_win;
bool m_iconAdded;
wxIcon m_icon;
wxString m_strTooltip;
#if WXWIN_COMPATIBILITY_2_4
// non-virtual default event handlers to forward events to the virtuals
@ -92,8 +85,3 @@ inline bool wxTaskBarIcon::IsOK() const { return IsOk(); }
#endif
// _TASKBAR_H_

View File

@ -22,7 +22,7 @@
// the application icon (under Windows and OS/2 it is in resources)
#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
#include "mondrian.xpm"
#include "../sample.xpm"
#endif
#include "wx/taskbar.h"
@ -35,9 +35,6 @@ IMPLEMENT_APP(MyApp)
bool MyApp::OnInit(void)
{
if (!m_taskBarIcon.SetIcon(wxICON(mondrian), wxT("wxTaskBarIcon Sample")))
wxMessageBox(wxT("Could not set icon."));
// Create the main frame window
dialog = new MyDialog(NULL, -1, wxT("wxTaskBarIcon Test Dialog"), wxPoint(-1, -1), wxSize(365, 290), wxDIALOG_MODELESS|wxDEFAULT_DIALOG_STYLE);
@ -62,6 +59,11 @@ MyDialog::MyDialog(wxWindow* parent, const wxWindowID id, const wxString& title,
Init();
}
MyDialog::~MyDialog()
{
delete m_taskBarIcon;
}
void MyDialog::OnOK(wxCommandEvent& WXUNUSED(event))
{
Show(FALSE);
@ -88,6 +90,11 @@ void MyDialog::Init(void)
(void)new wxButton(this, wxID_EXIT, _T("Exit"), wxPoint(185, 230), wxSize(80, 25));
(new wxButton(this, wxID_OK, _T("OK"), wxPoint(100, 230), wxSize(80, 25)))->SetDefault();
Centre(wxBOTH);
m_taskBarIcon = new MyTaskBarIcon();
if (!m_taskBarIcon->SetIcon(wxICON(sample), wxT("wxTaskBarIcon Sample")))
wxMessageBox(wxT("Could not set icon."));
}

View File

@ -29,8 +29,6 @@ class MyApp: public wxApp
{
public:
bool OnInit(void);
protected:
MyTaskBarIcon m_taskBarIcon;
};
class MyDialog: public wxDialog
@ -38,12 +36,16 @@ class MyDialog: public wxDialog
public:
MyDialog(wxWindow* parent, const wxWindowID id, const wxString& title,
const wxPoint& pos, const wxSize& size, const long windowStyle = wxDEFAULT_DIALOG_STYLE);
~MyDialog();
void OnOK(wxCommandEvent& event);
void OnExit(wxCommandEvent& event);
void OnCloseWindow(wxCloseEvent& event);
void Init(void);
protected:
MyTaskBarIcon *m_taskBarIcon;
DECLARE_EVENT_TABLE()
};

View File

@ -3,7 +3,7 @@
// Purpose: Implements wxTaskBarIcon class for manipulating icons on
// the Windows task bar.
// Author: Julian Smart
// Modified by:
// Modified by: Vaclav Slavik
// Created: 24/3/98
// RCS-ID: $Id$
// Copyright: (c)
@ -46,16 +46,6 @@
#include <shellapi.h>
#endif
#include "wx/listimpl.cpp"
WX_DEFINE_LIST(wxTaskBarIconList);
LRESULT APIENTRY _EXPORT
wxTaskBarIconWindowProc( HWND hWnd, unsigned msg, UINT wParam, LONG lParam );
wxChar *wxTaskBarWindowClass = (wxChar*) wxT("wxTaskBarWindowClass");
wxTaskBarIconList wxTaskBarIcon::sm_taskBarIcons;
// initialized on demand
UINT gs_msgTaskbar = 0;
UINT gs_msgRestartTaskbar = 0;
@ -79,6 +69,41 @@ IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// wxTaskBarIconWindow: helper window
// ----------------------------------------------------------------------------
// NB: this class serves two purposes:
// 1. win32 needs a HWND associated with taskbar icon, this provides it
// 2. we need wxTopLevelWindow so that the app doesn't exit when
// last frame is closed but there still is a taskbar icon
class wxTaskBarIconWindow : public wxFrame
{
public:
wxTaskBarIconWindow(wxTaskBarIcon *icon)
: wxFrame(NULL, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0),
m_icon(icon)
{
}
WXLRESULT MSWWindowProc(WXUINT msg,
WXWPARAM wParam, WXLPARAM lParam)
{
if (msg == gs_msgRestartTaskbar || msg == gs_msgTaskbar)
{
return m_icon->WindowProc(GetHWND(), msg, wParam, lParam);
}
else
{
return wxFrame::MSWWindowProc(msg, wParam, lParam);
}
}
private:
wxTaskBarIcon *m_icon;
};
// ----------------------------------------------------------------------------
// NotifyIconData: wrapper around NOTIFYICONDATA
// ----------------------------------------------------------------------------
@ -105,41 +130,35 @@ struct NotifyIconData : public NOTIFYICONDATA
wxTaskBarIcon::wxTaskBarIcon()
{
m_hWnd = 0;
m_win = NULL;
m_iconAdded = false;
AddObject(this);
if (RegisterWindowClass())
m_hWnd = CreateTaskBarWindow();
RegisterWindowMessages();
}
wxTaskBarIcon::~wxTaskBarIcon()
{
RemoveObject(this);
if (m_iconAdded)
{
RemoveIcon();
}
if (m_hWnd)
{
::DestroyWindow((HWND) m_hWnd);
m_hWnd = 0;
}
if (m_win)
m_win->Destroy();
}
// Operations
bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
{
if (!IsOk())
return false;
// NB: we have to create the window lazily because of backward compatiblity,
// old aplications may create wxTaskBarIcon instance before wxApp
// is initialized (as samples/taskbar used to do)
if (!m_win)
{
m_win = new wxTaskBarIconWindow(this);
}
m_icon = icon;
m_strTooltip = tooltip;
NotifyIconData notifyData(m_hWnd);
NotifyIconData notifyData((HWND)m_win->GetHWND());
if (icon.Ok())
{
@ -170,13 +189,15 @@ bool wxTaskBarIcon::RemoveIcon()
m_iconAdded = false;
NotifyIconData notifyData(m_hWnd);
NotifyIconData notifyData((HWND)m_win->GetHWND());
return Shell_NotifyIcon(NIM_DELETE, &notifyData) != 0;
}
bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
{
wxASSERT_MSG( m_win != NULL, _T("taskbar icon not initialized") );
static bool s_inPopup = false;
if (s_inPopup)
@ -184,31 +205,24 @@ bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
s_inPopup = true;
wxWindow* win;
int x, y;
wxGetMousePosition(&x, &y);
// is wxFrame the best window type to use???
win = new wxFrame(NULL, -1, wxEmptyString, wxPoint(x,y), wxSize(-1,-1), 0);
win->PushEventHandler(this);
// Remove from record of top-level windows, or will confuse wxWindows
// if we try to exit right now.
wxTopLevelWindows.DeleteObject(win);
m_win->Move(x, y);
m_win->PushEventHandler(this);
menu->UpdateUI();
// Work around a WIN32 bug
::SetForegroundWindow ((HWND) win->GetHWND ());
::SetForegroundWindow((HWND)m_win->GetHWND());
bool rval = win->PopupMenu(menu, 0, 0);
bool rval = m_win->PopupMenu(menu, 0, 0);
// Work around a WIN32 bug
::PostMessage ((HWND) win->GetHWND(),WM_NULL,0,0L);
::PostMessage((HWND)m_win->GetHWND(), WM_NULL, 0, 0L);
win->PopEventHandler(false);
win->Destroy();
delete win;
m_win->PopEventHandler(false);
s_inPopup = false;
@ -234,84 +248,20 @@ void wxTaskBarIcon::_OnLButtonDClick(wxEvent& e) { OnLButtonDClick(e); }
void wxTaskBarIcon::_OnRButtonDClick(wxEvent& e) { OnRButtonDClick(e); }
#endif
wxTaskBarIcon* wxTaskBarIcon::FindObjectForHWND(WXHWND hWnd)
{
wxTaskBarIconList::compatibility_iterator node = sm_taskBarIcons.GetFirst();
while (node)
{
wxTaskBarIcon *obj = node->GetData();
if (obj->GetHWND() == hWnd)
return obj;
node = node->GetNext();
}
return NULL;
}
void wxTaskBarIcon::AddObject(wxTaskBarIcon* obj)
{
sm_taskBarIcons.Append(obj);
}
void wxTaskBarIcon::RemoveObject(wxTaskBarIcon* obj)
{
sm_taskBarIcons.DeleteObject(obj);
}
bool wxTaskBarIcon::RegisterWindowClass()
void wxTaskBarIcon::RegisterWindowMessages()
{
static bool s_registered = false;
if ( s_registered )
return true;
if ( !s_registered )
{
// Taskbar restart msg will be sent to us if the icon needs to be redrawn
gs_msgRestartTaskbar = RegisterWindowMessage(wxT("TaskbarCreated"));
// Taskbar restart msg will be sent to us if the icon needs to be redrawn
gs_msgRestartTaskbar = RegisterWindowMessage(wxT("TaskbarCreated"));
// Also register the taskbar message here
gs_msgTaskbar = ::RegisterWindowMessage(wxT("wxTaskBarIconMessage"));
// Also register the taskbar message here
gs_msgTaskbar = ::RegisterWindowMessage(wxT("wxTaskBarIconMessage"));
// set up and register window class
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) wxTaskBarIconWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = wxGetInstance();
wc.hIcon = 0;
wc.hCursor = 0;
wc.hbrBackground = 0;
wc.lpszMenuName = NULL;
wc.lpszClassName = wxTaskBarWindowClass;
if ( !::RegisterClass(&wc) )
{
wxLogLastError(_T("RegisterClass(taskbar icon)"));
return false;
s_registered = true;
}
s_registered = true;
return true;
}
WXHWND wxTaskBarIcon::CreateTaskBarWindow()
{
HINSTANCE hInstance = wxGetInstance();
HWND hWnd = CreateWindowEx (0, wxTaskBarWindowClass,
wxT("wxTaskBarWindow"),
WS_OVERLAPPED,
0,
0,
10,
10,
NULL,
(HMENU) 0,
hInstance,
NULL);
return (WXHWND) hWnd;
}
// ----------------------------------------------------------------------------
@ -331,8 +281,8 @@ long wxTaskBarIcon::WindowProc(WXHWND hWnd,
SetIcon(m_icon, m_strTooltip);
}
if (msg != gs_msgTaskbar)
return DefWindowProc((HWND) hWnd, msg, wParam, lParam);
// this function should only be called for gs_msg(Restart)Taskbar messages
wxASSERT(msg == gs_msgTaskbar);
switch (lParam)
{
@ -378,15 +328,4 @@ long wxTaskBarIcon::WindowProc(WXHWND hWnd,
return 0;
}
LRESULT APIENTRY _EXPORT
wxTaskBarIconWindowProc(HWND hWnd, unsigned msg, UINT wParam, LONG lParam)
{
wxTaskBarIcon *obj = wxTaskBarIcon::FindObjectForHWND((WXHWND) hWnd);
if (obj)
return obj->WindowProc((WXHWND) hWnd, msg, wParam, lParam);
else
return DefWindowProc(hWnd, msg, wParam, lParam);
}
#endif
// __WIN95__
#endif // __WIN95__