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;
43 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon
, wxEvtHandler
)
45 // ============================================================================
47 // ============================================================================
49 // ----------------------------------------------------------------------------
50 // wxTaskBarIconWindow: helper window
51 // ----------------------------------------------------------------------------
53 // NB: this class serves two purposes:
54 // 1. win32 needs a HWND associated with taskbar icon, this provides it
55 // 2. we need wxTopLevelWindow so that the app doesn't exit when
56 // last frame is closed but there still is a taskbar icon
57 class wxTaskBarIconWindow
: public wxFrame
60 wxTaskBarIconWindow(wxTaskBarIcon
*icon
)
61 : wxFrame(NULL
, wxID_ANY
, wxEmptyString
, wxDefaultPosition
, wxDefaultSize
, 0),
66 WXLRESULT
MSWWindowProc(WXUINT msg
,
67 WXWPARAM wParam
, WXLPARAM lParam
)
69 if (msg
== gs_msgRestartTaskbar
|| msg
== gs_msgTaskbar
)
71 return m_icon
->WindowProc(msg
, wParam
, lParam
);
75 return wxFrame::MSWWindowProc(msg
, wParam
, lParam
);
80 wxTaskBarIcon
*m_icon
;
84 // ----------------------------------------------------------------------------
85 // NotifyIconData: wrapper around NOTIFYICONDATA
86 // ----------------------------------------------------------------------------
88 struct NotifyIconData
: public NOTIFYICONDATA
90 NotifyIconData(WXHWND hwnd
)
92 memset(this, 0, sizeof(NOTIFYICONDATA
));
93 cbSize
= sizeof(NOTIFYICONDATA
);
95 uCallbackMessage
= gs_msgTaskbar
;
98 // we use the same id for all taskbar icons as we don't need it to
99 // distinguish between them
104 // ----------------------------------------------------------------------------
106 // ----------------------------------------------------------------------------
108 wxTaskBarIcon::wxTaskBarIcon()
112 RegisterWindowMessages();
115 wxTaskBarIcon::~wxTaskBarIcon()
125 bool wxTaskBarIcon::SetIcon(const wxIcon
& icon
, const wxString
& tooltip
)
127 // NB: we have to create the window lazily because of backward compatibility,
128 // old applications may create a wxTaskBarIcon instance before wxApp
129 // is initialized (as samples/taskbar used to do)
132 m_win
= new wxTaskBarIconWindow(this);
136 m_strTooltip
= tooltip
;
138 NotifyIconData
notifyData(GetHwndOf(m_win
));
142 notifyData
.uFlags
|= NIF_ICON
;
143 notifyData
.hIcon
= GetHiconOf(icon
);
146 if ( !tooltip
.empty() )
148 notifyData
.uFlags
|= NIF_TIP
;
149 // lstrcpyn(notifyData.szTip, tooltip.c_str(), WXSIZEOF(notifyData.szTip));
150 wxStrncpy(notifyData
.szTip
, tooltip
.c_str(), WXSIZEOF(notifyData
.szTip
));
153 bool ok
= Shell_NotifyIcon(m_iconAdded
? NIM_MODIFY
154 : NIM_ADD
, ¬ifyData
) != 0;
156 if ( !m_iconAdded
&& ok
)
162 bool wxTaskBarIcon::RemoveIcon()
169 NotifyIconData
notifyData(GetHwndOf(m_win
));
171 return Shell_NotifyIcon(NIM_DELETE
, ¬ifyData
) != 0;
175 bool wxTaskBarIcon::PopupMenu(wxMenu
*menu
)
177 wxASSERT_MSG( m_win
!= NULL
, _T("taskbar icon not initialized") );
179 static bool s_inPopup
= false;
187 wxGetMousePosition(&x
, &y
);
191 m_win
->PushEventHandler(this);
195 // the SetForegroundWindow() and PostMessage() calls are needed to work
196 // around Win32 bug with the popup menus shown for the notifications as
197 // documented at http://support.microsoft.com/kb/q135788/
198 ::SetForegroundWindow(GetHwndOf(m_win
));
200 bool rval
= m_win
->PopupMenu(menu
, 0, 0);
202 ::PostMessage(GetHwndOf(m_win
), WM_NULL
, 0, 0L);
204 m_win
->PopEventHandler(false);
210 #endif // wxUSE_MENUS
212 void wxTaskBarIcon::RegisterWindowMessages()
214 static bool s_registered
= false;
218 // Taskbar restart msg will be sent to us if the icon needs to be redrawn
219 gs_msgRestartTaskbar
= RegisterWindowMessage(wxT("TaskbarCreated"));
221 // Also register the taskbar message here
222 gs_msgTaskbar
= ::RegisterWindowMessage(wxT("wxTaskBarIconMessage"));
228 // ----------------------------------------------------------------------------
229 // wxTaskBarIcon window proc
230 // ----------------------------------------------------------------------------
232 long wxTaskBarIcon::WindowProc(unsigned int msg
,
233 unsigned int WXUNUSED(wParam
),
236 wxEventType eventType
= 0;
238 if (msg
== gs_msgRestartTaskbar
) // does the icon need to be redrawn?
241 SetIcon(m_icon
, m_strTooltip
);
244 // this function should only be called for gs_msg(Restart)Taskbar messages
245 wxASSERT(msg
== gs_msgTaskbar
);
250 eventType
= wxEVT_TASKBAR_LEFT_DOWN
;
254 eventType
= wxEVT_TASKBAR_LEFT_UP
;
258 eventType
= wxEVT_TASKBAR_RIGHT_DOWN
;
262 eventType
= wxEVT_TASKBAR_RIGHT_UP
;
265 case WM_LBUTTONDBLCLK
:
266 eventType
= wxEVT_TASKBAR_LEFT_DCLICK
;
269 case WM_RBUTTONDBLCLK
:
270 eventType
= wxEVT_TASKBAR_RIGHT_DCLICK
;
274 eventType
= wxEVT_TASKBAR_MOVE
;
283 wxTaskBarIconEvent
event(eventType
, this);