1 ///////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Implements wxTaskBarIcon class for manipulating icons on 
   4 //              the Windows task bar. 
   5 // Author:      Julian Smart 
   6 // Modified by: Vaclav Slavik 
  10 // Licence:     wxWindows licence 
  11 ///////////////////////////////////////////////////////////////////////// 
  13 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  14 #pragma implementation "taskbar.h" 
  17 // For compilers that support precompilation, includes "wx.h". 
  18 #include "wx/wxprec.h" 
  26 #include "wx/window.h" 
  32 #if defined(__WIN95__) 
  34 #include "wx/msw/private.h" 
  35 #include "wx/msw/winundef.h" 
  38 #include "wx/taskbar.h" 
  40 #ifdef __GNUWIN32_OLD__ 
  41     #include "wx/msw/gnuwin32/extra.h" 
  49 // initialized on demand 
  50 UINT   gs_msgTaskbar 
= 0; 
  51 UINT   gs_msgRestartTaskbar 
= 0; 
  53 #if WXWIN_COMPATIBILITY_2_4 
  54 BEGIN_EVENT_TABLE(wxTaskBarIcon
, wxEvtHandler
) 
  55     EVT_TASKBAR_MOVE         (wxTaskBarIcon::_OnMouseMove
) 
  56     EVT_TASKBAR_LEFT_DOWN    (wxTaskBarIcon::_OnLButtonDown
) 
  57     EVT_TASKBAR_LEFT_UP      (wxTaskBarIcon::_OnLButtonUp
) 
  58     EVT_TASKBAR_RIGHT_DOWN   (wxTaskBarIcon::_OnRButtonDown
) 
  59     EVT_TASKBAR_RIGHT_UP     (wxTaskBarIcon::_OnRButtonUp
) 
  60     EVT_TASKBAR_LEFT_DCLICK  (wxTaskBarIcon::_OnLButtonDClick
) 
  61     EVT_TASKBAR_RIGHT_DCLICK (wxTaskBarIcon::_OnRButtonDClick
) 
  66 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon
, wxEvtHandler
) 
  68 // ============================================================================ 
  70 // ============================================================================ 
  72 // ---------------------------------------------------------------------------- 
  73 // wxTaskBarIconWindow: helper window 
  74 // ---------------------------------------------------------------------------- 
  76 // NB: this class serves two purposes: 
  77 //     1. win32 needs a HWND associated with taskbar icon, this provides it 
  78 //     2. we need wxTopLevelWindow so that the app doesn't exit when 
  79 //        last frame is closed but there still is a taskbar icon 
  80 class wxTaskBarIconWindow 
: public wxFrame
 
  83     wxTaskBarIconWindow(wxTaskBarIcon 
*icon
) 
  84         : wxFrame(NULL
, -1, wxEmptyString
, wxDefaultPosition
, wxDefaultSize
, 0), 
  89     WXLRESULT 
MSWWindowProc(WXUINT msg
, 
  90                             WXWPARAM wParam
, WXLPARAM lParam
) 
  92         if (msg 
== gs_msgRestartTaskbar 
|| msg 
== gs_msgTaskbar
) 
  94             return m_icon
->WindowProc(msg
, wParam
, lParam
); 
  98             return wxFrame::MSWWindowProc(msg
, wParam
, lParam
); 
 103     wxTaskBarIcon 
*m_icon
; 
 107 // ---------------------------------------------------------------------------- 
 108 // NotifyIconData: wrapper around NOTIFYICONDATA 
 109 // ---------------------------------------------------------------------------- 
 111 struct NotifyIconData 
: public NOTIFYICONDATA
 
 113     NotifyIconData(WXHWND hwnd
) 
 115         memset(this, 0, sizeof(NOTIFYICONDATA
)); 
 116         cbSize 
= sizeof(NOTIFYICONDATA
); 
 118         uCallbackMessage 
= gs_msgTaskbar
; 
 119         uFlags 
= NIF_MESSAGE
; 
 121         // we use the same id for all taskbar icons as we don't need it to 
 122         // distinguish between them 
 127 // ---------------------------------------------------------------------------- 
 129 // ---------------------------------------------------------------------------- 
 131 wxTaskBarIcon::wxTaskBarIcon() 
 135     RegisterWindowMessages(); 
 138 wxTaskBarIcon::~wxTaskBarIcon() 
 148 bool wxTaskBarIcon::SetIcon(const wxIcon
& icon
, const wxString
& tooltip
) 
 150     // NB: we have to create the window lazily because of backward compatiblity, 
 151     //     old aplications may create wxTaskBarIcon instance before wxApp 
 152     //     is initialized (as samples/taskbar used to do) 
 155         m_win 
= new wxTaskBarIconWindow(this); 
 159     m_strTooltip 
= tooltip
; 
 161     NotifyIconData 
notifyData((HWND
)m_win
->GetHWND()); 
 165         notifyData
.uFlags 
|= NIF_ICON
; 
 166         notifyData
.hIcon 
= GetHiconOf(icon
); 
 169     if ( !tooltip
.empty() ) 
 171         notifyData
.uFlags 
|= NIF_TIP
; 
 172 //        lstrcpyn(notifyData.szTip, tooltip.c_str(), WXSIZEOF(notifyData.szTip)); 
 173         wxStrncpy(notifyData
.szTip
, tooltip
.c_str(), WXSIZEOF(notifyData
.szTip
)); 
 176     bool ok 
= Shell_NotifyIcon(m_iconAdded 
? NIM_MODIFY
 
 177                                            : NIM_ADD
, ¬ifyData
) != 0; 
 179     if ( !m_iconAdded 
&& ok 
) 
 185 bool wxTaskBarIcon::RemoveIcon() 
 192     NotifyIconData 
notifyData((HWND
)m_win
->GetHWND()); 
 194     return Shell_NotifyIcon(NIM_DELETE
, ¬ifyData
) != 0; 
 197 bool wxTaskBarIcon::PopupMenu(wxMenu 
*menu
) 
 199     wxASSERT_MSG( m_win 
!= NULL
, _T("taskbar icon not initialized") ); 
 201     static bool s_inPopup 
= false; 
 209     wxGetMousePosition(&x
, &y
); 
 213     m_win
->PushEventHandler(this); 
 217     // Work around a WIN32 bug 
 218     ::SetForegroundWindow((HWND
)m_win
->GetHWND()); 
 220     bool rval 
= m_win
->PopupMenu(menu
, 0, 0); 
 222     // Work around a WIN32 bug 
 223     ::PostMessage((HWND
)m_win
->GetHWND(), WM_NULL
, 0, 0L); 
 225     m_win
->PopEventHandler(false); 
 232 #if WXWIN_COMPATIBILITY_2_4 
 234 void wxTaskBarIcon::OnMouseMove(wxEvent
&)         {} 
 235 void wxTaskBarIcon::OnLButtonDown(wxEvent
&)       {} 
 236 void wxTaskBarIcon::OnLButtonUp(wxEvent
&)         {} 
 237 void wxTaskBarIcon::OnRButtonDown(wxEvent
&)       {} 
 238 void wxTaskBarIcon::OnRButtonUp(wxEvent
&)         {} 
 239 void wxTaskBarIcon::OnLButtonDClick(wxEvent
&)     {} 
 240 void wxTaskBarIcon::OnRButtonDClick(wxEvent
&)     {} 
 242 void wxTaskBarIcon::_OnMouseMove(wxEvent
& e
)      { OnMouseMove(e
);     } 
 243 void wxTaskBarIcon::_OnLButtonDown(wxEvent
& e
)    { OnLButtonDown(e
);   } 
 244 void wxTaskBarIcon::_OnLButtonUp(wxEvent
& e
)      { OnLButtonUp(e
);     } 
 245 void wxTaskBarIcon::_OnRButtonDown(wxEvent
& e
)    { OnRButtonDown(e
);   } 
 246 void wxTaskBarIcon::_OnRButtonUp(wxEvent
& e
)      { OnRButtonUp(e
);     } 
 247 void wxTaskBarIcon::_OnLButtonDClick(wxEvent
& e
)  { OnLButtonDClick(e
); } 
 248 void wxTaskBarIcon::_OnRButtonDClick(wxEvent
& e
)  { OnRButtonDClick(e
); } 
 251 void wxTaskBarIcon::RegisterWindowMessages() 
 253     static bool s_registered 
= false; 
 257         // Taskbar restart msg will be sent to us if the icon needs to be redrawn 
 258         gs_msgRestartTaskbar 
= RegisterWindowMessage(wxT("TaskbarCreated")); 
 260         // Also register the taskbar message here 
 261         gs_msgTaskbar 
= ::RegisterWindowMessage(wxT("wxTaskBarIconMessage")); 
 267 // ---------------------------------------------------------------------------- 
 268 // wxTaskBarIcon window proc 
 269 // ---------------------------------------------------------------------------- 
 271 long wxTaskBarIcon::WindowProc(unsigned int msg
, 
 272                                unsigned int WXUNUSED(wParam
), 
 275     wxEventType eventType 
= 0; 
 277     if (msg 
== gs_msgRestartTaskbar
)   // does the icon need to be redrawn? 
 280         SetIcon(m_icon
, m_strTooltip
); 
 283     // this function should only be called for gs_msg(Restart)Taskbar messages 
 284     wxASSERT(msg 
== gs_msgTaskbar
); 
 289             eventType 
= wxEVT_TASKBAR_LEFT_DOWN
; 
 293             eventType 
= wxEVT_TASKBAR_LEFT_UP
; 
 297             eventType 
= wxEVT_TASKBAR_RIGHT_DOWN
; 
 301             eventType 
= wxEVT_TASKBAR_RIGHT_UP
; 
 304         case WM_LBUTTONDBLCLK
: 
 305             eventType 
= wxEVT_TASKBAR_LEFT_DCLICK
; 
 308         case WM_RBUTTONDBLCLK
: 
 309             eventType 
= wxEVT_TASKBAR_RIGHT_DCLICK
; 
 313             eventType 
= wxEVT_TASKBAR_MOVE
; 
 322         wxTaskBarIconEvent 
event(eventType
, this);