]> git.saurik.com Git - wxWidgets.git/commitdiff
unified wxTaskBarIcon behaviour: wxMSW version is not removed automatically when...
authorVáclav Slavík <vslavik@fastmail.fm>
Tue, 23 Mar 2004 23:20:16 +0000 (23:20 +0000)
committerVáclav Slavík <vslavik@fastmail.fm>
Tue, 23 Mar 2004 23:20:16 +0000 (23:20 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@26318 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/changes.txt
include/wx/msw/taskbar.h
samples/taskbar/tbtest.cpp
samples/taskbar/tbtest.h
src/msw/taskbar.cpp

index de361734a98e25e37256f213c47cb0924ad89407..7d1104091575c528d73062083eaf22eb7d75dbf5 100644 (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:
 
index 9aa9bd1b33117c17fc798b1e6fd1b1e89602adce..d36e055b5c91aceae109254ff25d774caca190eb 100644 (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
 #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_
-
-
-
-
-
index c989143edc84cdb593bae2c594cace138a0fc576..240abe59ff3984d413d5c308f47044c13e0a241c 100644 (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."));
 }
 
 
index a3ce1b2940e9f1aba33db24202a9a33fb5ce34f5..24ab1de7c8fce69ebc19de0b0f64bf8f0b0d0f13 100644 (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()
 };
 
index 90bb7742c78af3d80412b7631e6d4c4e57c29d90..f6512bba8bb4103a82f36ca2f92d1786b5e7c91c 100644 (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)
     #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;
-
-    // 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"));
-
-    // 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;
+    if ( !s_registered )
+    {   
+        // Taskbar restart msg will be sent to us if the icon needs to be redrawn
+        gs_msgRestartTaskbar = RegisterWindowMessage(wxT("TaskbarCreated"));
 
-    return true;
-}
+        // Also register the taskbar message here
+        gs_msgTaskbar = ::RegisterWindowMessage(wxT("wxTaskBarIconMessage"));
 
-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;
+        s_registered = true;
+    }
 }
 
 // ----------------------------------------------------------------------------
@@ -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__