1 /////////////////////////////////////////////////////////////////////////
2 // File: src/msw/taskbar.cpp
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 // For compilers that support precompilation, includes "wx.h".
14 #include "wx/wxprec.h"
21 #include "wx/window.h"
27 #include "wx/msw/private.h"
28 #include "wx/msw/winundef.h"
31 #include "wx/taskbar.h"
38 // initialized on demand
39 UINT gs_msgTaskbar
= 0;
40 UINT gs_msgRestartTaskbar
= 0;
42 #if WXWIN_COMPATIBILITY_2_4
43 BEGIN_EVENT_TABLE(wxTaskBarIcon
, wxTaskBarIconBase
)
44 EVT_TASKBAR_MOVE (wxTaskBarIcon::_OnMouseMove
)
45 EVT_TASKBAR_LEFT_DOWN (wxTaskBarIcon::_OnLButtonDown
)
46 EVT_TASKBAR_LEFT_UP (wxTaskBarIcon::_OnLButtonUp
)
47 EVT_TASKBAR_RIGHT_DOWN (wxTaskBarIcon::_OnRButtonDown
)
48 EVT_TASKBAR_RIGHT_UP (wxTaskBarIcon::_OnRButtonUp
)
49 EVT_TASKBAR_LEFT_DCLICK (wxTaskBarIcon::_OnLButtonDClick
)
50 EVT_TASKBAR_RIGHT_DCLICK (wxTaskBarIcon::_OnRButtonDClick
)
55 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon
, wxEvtHandler
)
57 // ============================================================================
59 // ============================================================================
61 // ----------------------------------------------------------------------------
62 // wxTaskBarIconWindow: helper window
63 // ----------------------------------------------------------------------------
65 // NB: this class serves two purposes:
66 // 1. win32 needs a HWND associated with taskbar icon, this provides it
67 // 2. we need wxTopLevelWindow so that the app doesn't exit when
68 // last frame is closed but there still is a taskbar icon
69 class wxTaskBarIconWindow
: public wxFrame
72 wxTaskBarIconWindow(wxTaskBarIcon
*icon
)
73 : wxFrame(NULL
, wxID_ANY
, wxEmptyString
, wxDefaultPosition
, wxDefaultSize
, 0),
78 WXLRESULT
MSWWindowProc(WXUINT msg
,
79 WXWPARAM wParam
, WXLPARAM lParam
)
81 if (msg
== gs_msgRestartTaskbar
|| msg
== gs_msgTaskbar
)
83 return m_icon
->WindowProc(msg
, wParam
, lParam
);
87 return wxFrame::MSWWindowProc(msg
, wParam
, lParam
);
92 wxTaskBarIcon
*m_icon
;
96 // ----------------------------------------------------------------------------
97 // NotifyIconData: wrapper around NOTIFYICONDATA
98 // ----------------------------------------------------------------------------
100 struct NotifyIconData
: public NOTIFYICONDATA
102 NotifyIconData(WXHWND hwnd
)
104 memset(this, 0, sizeof(NOTIFYICONDATA
));
105 cbSize
= sizeof(NOTIFYICONDATA
);
107 uCallbackMessage
= gs_msgTaskbar
;
108 uFlags
= NIF_MESSAGE
;
110 // we use the same id for all taskbar icons as we don't need it to
111 // distinguish between them
116 // ----------------------------------------------------------------------------
118 // ----------------------------------------------------------------------------
120 wxTaskBarIcon::wxTaskBarIcon()
124 RegisterWindowMessages();
127 wxTaskBarIcon::~wxTaskBarIcon()
137 bool wxTaskBarIcon::SetIcon(const wxIcon
& icon
, const wxString
& tooltip
)
139 // NB: we have to create the window lazily because of backward compatibility,
140 // old applications may create a wxTaskBarIcon instance before wxApp
141 // is initialized (as samples/taskbar used to do)
144 m_win
= new wxTaskBarIconWindow(this);
148 m_strTooltip
= tooltip
;
150 NotifyIconData
notifyData(GetHwndOf(m_win
));
154 notifyData
.uFlags
|= NIF_ICON
;
155 notifyData
.hIcon
= GetHiconOf(icon
);
158 if ( !tooltip
.empty() )
160 notifyData
.uFlags
|= NIF_TIP
;
161 // lstrcpyn(notifyData.szTip, tooltip.c_str(), WXSIZEOF(notifyData.szTip));
162 wxStrncpy(notifyData
.szTip
, tooltip
.c_str(), WXSIZEOF(notifyData
.szTip
));
165 bool ok
= Shell_NotifyIcon(m_iconAdded
? NIM_MODIFY
166 : NIM_ADD
, ¬ifyData
) != 0;
168 if ( !m_iconAdded
&& ok
)
174 bool wxTaskBarIcon::RemoveIcon()
181 NotifyIconData
notifyData(GetHwndOf(m_win
));
183 return Shell_NotifyIcon(NIM_DELETE
, ¬ifyData
) != 0;
186 bool wxTaskBarIcon::PopupMenu(wxMenu
*menu
)
188 wxASSERT_MSG( m_win
!= NULL
, _T("taskbar icon not initialized") );
190 static bool s_inPopup
= false;
198 wxGetMousePosition(&x
, &y
);
202 m_win
->PushEventHandler(this);
206 // the SetForegroundWindow() and PostMessage() calls are needed to work
207 // around Win32 bug with the popup menus shown for the notifications as
208 // documented at http://support.microsoft.com/kb/q135788/
209 ::SetForegroundWindow(GetHwndOf(m_win
));
211 bool rval
= m_win
->PopupMenu(menu
, 0, 0);
213 ::PostMessage(GetHwndOf(m_win
), WM_NULL
, 0, 0L);
215 m_win
->PopEventHandler(false);
222 #if WXWIN_COMPATIBILITY_2_4
224 void wxTaskBarIcon::OnMouseMove(wxEvent
& e
) { e
.Skip(); }
225 void wxTaskBarIcon::OnLButtonDown(wxEvent
& e
) { e
.Skip(); }
226 void wxTaskBarIcon::OnLButtonUp(wxEvent
& e
) { e
.Skip(); }
227 void wxTaskBarIcon::OnRButtonDown(wxEvent
& e
) { e
.Skip(); }
228 void wxTaskBarIcon::OnRButtonUp(wxEvent
& e
) { e
.Skip(); }
229 void wxTaskBarIcon::OnLButtonDClick(wxEvent
& e
) { e
.Skip(); }
230 void wxTaskBarIcon::OnRButtonDClick(wxEvent
& e
) { e
.Skip(); }
232 void wxTaskBarIcon::_OnMouseMove(wxTaskBarIconEvent
& e
)
234 void wxTaskBarIcon::_OnLButtonDown(wxTaskBarIconEvent
& e
)
235 { OnLButtonDown(e
); }
236 void wxTaskBarIcon::_OnLButtonUp(wxTaskBarIconEvent
& e
)
238 void wxTaskBarIcon::_OnRButtonDown(wxTaskBarIconEvent
& e
)
239 { OnRButtonDown(e
); }
240 void wxTaskBarIcon::_OnRButtonUp(wxTaskBarIconEvent
& e
)
242 void wxTaskBarIcon::_OnLButtonDClick(wxTaskBarIconEvent
& e
)
243 { OnLButtonDClick(e
); }
244 void wxTaskBarIcon::_OnRButtonDClick(wxTaskBarIconEvent
& e
)
245 { OnRButtonDClick(e
); }
248 void wxTaskBarIcon::RegisterWindowMessages()
250 static bool s_registered
= false;
254 // Taskbar restart msg will be sent to us if the icon needs to be redrawn
255 gs_msgRestartTaskbar
= RegisterWindowMessage(wxT("TaskbarCreated"));
257 // Also register the taskbar message here
258 gs_msgTaskbar
= ::RegisterWindowMessage(wxT("wxTaskBarIconMessage"));
264 // ----------------------------------------------------------------------------
265 // wxTaskBarIcon window proc
266 // ----------------------------------------------------------------------------
268 long wxTaskBarIcon::WindowProc(unsigned int msg
,
269 unsigned int WXUNUSED(wParam
),
272 wxEventType eventType
= 0;
274 if (msg
== gs_msgRestartTaskbar
) // does the icon need to be redrawn?
277 SetIcon(m_icon
, m_strTooltip
);
280 // this function should only be called for gs_msg(Restart)Taskbar messages
281 wxASSERT(msg
== gs_msgTaskbar
);
286 eventType
= wxEVT_TASKBAR_LEFT_DOWN
;
290 eventType
= wxEVT_TASKBAR_LEFT_UP
;
294 eventType
= wxEVT_TASKBAR_RIGHT_DOWN
;
298 eventType
= wxEVT_TASKBAR_RIGHT_UP
;
301 case WM_LBUTTONDBLCLK
:
302 eventType
= wxEVT_TASKBAR_LEFT_DCLICK
;
305 case WM_RBUTTONDBLCLK
:
306 eventType
= wxEVT_TASKBAR_RIGHT_DCLICK
;
310 eventType
= wxEVT_TASKBAR_MOVE
;
319 wxTaskBarIconEvent
event(eventType
, this);