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"
23 #include "wx/window.h"
29 #include "wx/msw/private.h"
30 #include "wx/msw/winundef.h"
33 #include "wx/taskbar.h"
40 // initialized on demand
41 UINT gs_msgTaskbar
= 0;
42 UINT gs_msgRestartTaskbar
= 0;
45 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon
, wxEvtHandler
)
47 // ============================================================================
49 // ============================================================================
51 // ----------------------------------------------------------------------------
52 // wxTaskBarIconWindow: helper window
53 // ----------------------------------------------------------------------------
55 // NB: this class serves two purposes:
56 // 1. win32 needs a HWND associated with taskbar icon, this provides it
57 // 2. we need wxTopLevelWindow so that the app doesn't exit when
58 // last frame is closed but there still is a taskbar icon
59 class wxTaskBarIconWindow
: public wxFrame
62 wxTaskBarIconWindow(wxTaskBarIcon
*icon
)
63 : wxFrame(NULL
, wxID_ANY
, wxEmptyString
, wxDefaultPosition
, wxDefaultSize
, 0),
68 WXLRESULT
MSWWindowProc(WXUINT msg
,
69 WXWPARAM wParam
, WXLPARAM lParam
)
71 if (msg
== gs_msgRestartTaskbar
|| msg
== gs_msgTaskbar
)
73 return m_icon
->WindowProc(msg
, wParam
, lParam
);
77 return wxFrame::MSWWindowProc(msg
, wParam
, lParam
);
82 wxTaskBarIcon
*m_icon
;
86 // ----------------------------------------------------------------------------
87 // NotifyIconData: wrapper around NOTIFYICONDATA
88 // ----------------------------------------------------------------------------
90 struct NotifyIconData
: public NOTIFYICONDATA
92 NotifyIconData(WXHWND hwnd
)
94 memset(this, 0, sizeof(NOTIFYICONDATA
));
95 cbSize
= sizeof(NOTIFYICONDATA
);
97 uCallbackMessage
= gs_msgTaskbar
;
100 // we use the same id for all taskbar icons as we don't need it to
101 // distinguish between them
106 // ----------------------------------------------------------------------------
108 // ----------------------------------------------------------------------------
110 wxTaskBarIcon::wxTaskBarIcon()
114 RegisterWindowMessages();
117 wxTaskBarIcon::~wxTaskBarIcon()
127 bool wxTaskBarIcon::SetIcon(const wxIcon
& icon
, const wxString
& tooltip
)
129 // NB: we have to create the window lazily because of backward compatibility,
130 // old applications may create a wxTaskBarIcon instance before wxApp
131 // is initialized (as samples/taskbar used to do)
134 m_win
= new wxTaskBarIconWindow(this);
138 m_strTooltip
= tooltip
;
140 NotifyIconData
notifyData(GetHwndOf(m_win
));
144 notifyData
.uFlags
|= NIF_ICON
;
145 notifyData
.hIcon
= GetHiconOf(icon
);
148 // set NIF_TIP even for an empty tooltip: otherwise it would be impossible
149 // to remove an existing tooltip using this function
150 notifyData
.uFlags
|= NIF_TIP
;
151 if ( !tooltip
.empty() )
153 wxStrncpy(notifyData
.szTip
, tooltip
.c_str(), WXSIZEOF(notifyData
.szTip
));
156 bool ok
= Shell_NotifyIcon(m_iconAdded
? NIM_MODIFY
157 : NIM_ADD
, ¬ifyData
) != 0;
159 if ( !m_iconAdded
&& ok
)
165 bool wxTaskBarIcon::RemoveIcon()
172 NotifyIconData
notifyData(GetHwndOf(m_win
));
174 return Shell_NotifyIcon(NIM_DELETE
, ¬ifyData
) != 0;
178 bool wxTaskBarIcon::PopupMenu(wxMenu
*menu
)
180 wxASSERT_MSG( m_win
!= NULL
, _T("taskbar icon not initialized") );
182 static bool s_inPopup
= false;
190 wxGetMousePosition(&x
, &y
);
194 m_win
->PushEventHandler(this);
198 // the SetForegroundWindow() and PostMessage() calls are needed to work
199 // around Win32 bug with the popup menus shown for the notifications as
200 // documented at http://support.microsoft.com/kb/q135788/
201 ::SetForegroundWindow(GetHwndOf(m_win
));
203 bool rval
= m_win
->PopupMenu(menu
, 0, 0);
205 ::PostMessage(GetHwndOf(m_win
), WM_NULL
, 0, 0L);
207 m_win
->PopEventHandler(false);
213 #endif // wxUSE_MENUS
215 void wxTaskBarIcon::RegisterWindowMessages()
217 static bool s_registered
= false;
221 // Taskbar restart msg will be sent to us if the icon needs to be redrawn
222 gs_msgRestartTaskbar
= RegisterWindowMessage(wxT("TaskbarCreated"));
224 // Also register the taskbar message here
225 gs_msgTaskbar
= ::RegisterWindowMessage(wxT("wxTaskBarIconMessage"));
231 // ----------------------------------------------------------------------------
232 // wxTaskBarIcon window proc
233 // ----------------------------------------------------------------------------
235 long wxTaskBarIcon::WindowProc(unsigned int msg
,
236 unsigned int WXUNUSED(wParam
),
239 wxEventType eventType
= 0;
241 if (msg
== gs_msgRestartTaskbar
) // does the icon need to be redrawn?
244 SetIcon(m_icon
, m_strTooltip
);
247 // this function should only be called for gs_msg(Restart)Taskbar messages
248 wxASSERT(msg
== gs_msgTaskbar
);
253 eventType
= wxEVT_TASKBAR_LEFT_DOWN
;
257 eventType
= wxEVT_TASKBAR_LEFT_UP
;
261 eventType
= wxEVT_TASKBAR_RIGHT_DOWN
;
265 eventType
= wxEVT_TASKBAR_RIGHT_UP
;
268 case WM_LBUTTONDBLCLK
:
269 eventType
= wxEVT_TASKBAR_LEFT_DCLICK
;
272 case WM_RBUTTONDBLCLK
:
273 eventType
= wxEVT_TASKBAR_RIGHT_DCLICK
;
277 eventType
= wxEVT_TASKBAR_MOVE
;
286 wxTaskBarIconEvent
event(eventType
, this);
294 #endif // wxUSE_TASKBARICON