]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/taskbar.cpp
Move wxCocoa's wxFontRefData from the header to the implementation file.
[wxWidgets.git] / src / msw / taskbar.cpp
... / ...
CommitLineData
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
7// Created: 24/3/98
8// RCS-ID: $Id$
9// Copyright: (c)
10// Licence: wxWindows licence
11/////////////////////////////////////////////////////////////////////////
12
13// For compilers that support precompilation, includes "wx.h".
14#include "wx/wxprec.h"
15
16#ifdef __BORLANDC__
17 #pragma hdrstop
18#endif
19
20#if wxUSE_TASKBARICON
21
22#ifndef WX_PRECOMP
23 #include "wx/window.h"
24 #include "wx/frame.h"
25 #include "wx/utils.h"
26 #include "wx/menu.h"
27#endif
28
29#include "wx/msw/wrapshl.h"
30
31#include <string.h>
32#include "wx/taskbar.h"
33#include "wx/dynlib.h"
34
35// initialized on demand
36static UINT gs_msgTaskbar = 0;
37static UINT gs_msgRestartTaskbar = 0;
38
39
40IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
41
42// ============================================================================
43// implementation
44// ============================================================================
45
46// wrapper around Shell_NotifyIcon(): this function is not present in Win95
47// shell32.dll so load it dynamically to allow programs using wxTaskBarIcon to
48// start under this OS
49static BOOL wxShellNotifyIcon(DWORD dwMessage, NOTIFYICONDATA *pData)
50{
51#if wxUSE_DYNLIB_CLASS
52 typedef BOOL (WINAPI *Shell_NotifyIcon_t)(DWORD, NOTIFYICONDATA *);
53
54 static Shell_NotifyIcon_t s_pfnShell_NotifyIcon = NULL;
55 static bool s_initialized = false;
56 if ( !s_initialized )
57 {
58 s_initialized = true;
59
60 wxLogNull noLog;
61 wxDynamicLibrary dllShell("shell32.dll");
62 if ( dllShell.IsLoaded() )
63 {
64 wxDL_INIT_FUNC_AW(s_pfn, Shell_NotifyIcon, dllShell);
65 }
66
67 // NB: it's ok to destroy dllShell here, we link to shell32.dll
68 // implicitly so it won't be unloaded
69 }
70
71 return s_pfnShell_NotifyIcon ? (*s_pfnShell_NotifyIcon)(dwMessage, pData)
72 : FALSE;
73#else // !wxUSE_DYNLIB_CLASS
74 return Shell_NotifyIcon(dwMessage, pData);
75#endif // wxUSE_DYNLIB_CLASS/!wxUSE_DYNLIB_CLASS
76}
77
78// ----------------------------------------------------------------------------
79// wxTaskBarIconWindow: helper window
80// ----------------------------------------------------------------------------
81
82// NB: this class serves two purposes:
83// 1. win32 needs a HWND associated with taskbar icon, this provides it
84// 2. we need wxTopLevelWindow so that the app doesn't exit when
85// last frame is closed but there still is a taskbar icon
86class wxTaskBarIconWindow : public wxFrame
87{
88public:
89 wxTaskBarIconWindow(wxTaskBarIcon *icon)
90 : wxFrame(NULL, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0),
91 m_icon(icon)
92 {
93 }
94
95 WXLRESULT MSWWindowProc(WXUINT msg,
96 WXWPARAM wParam, WXLPARAM lParam)
97 {
98 if (msg == gs_msgRestartTaskbar || msg == gs_msgTaskbar)
99 {
100 return m_icon->WindowProc(msg, wParam, lParam);
101 }
102 else
103 {
104 return wxFrame::MSWWindowProc(msg, wParam, lParam);
105 }
106 }
107
108private:
109 wxTaskBarIcon *m_icon;
110};
111
112
113// ----------------------------------------------------------------------------
114// NotifyIconData: wrapper around NOTIFYICONDATA
115// ----------------------------------------------------------------------------
116
117struct NotifyIconData : public NOTIFYICONDATA
118{
119 NotifyIconData(WXHWND hwnd)
120 {
121 memset(this, 0, sizeof(NOTIFYICONDATA));
122 cbSize = sizeof(NOTIFYICONDATA);
123 hWnd = (HWND) hwnd;
124 uCallbackMessage = gs_msgTaskbar;
125 uFlags = NIF_MESSAGE;
126
127 // we use the same id for all taskbar icons as we don't need it to
128 // distinguish between them
129 uID = 99;
130 }
131};
132
133// ----------------------------------------------------------------------------
134// wxTaskBarIcon
135// ----------------------------------------------------------------------------
136
137wxTaskBarIcon::wxTaskBarIcon()
138{
139 m_win = NULL;
140 m_iconAdded = false;
141 RegisterWindowMessages();
142}
143
144wxTaskBarIcon::~wxTaskBarIcon()
145{
146 if (m_iconAdded)
147 RemoveIcon();
148
149 if (m_win)
150 m_win->Destroy();
151}
152
153// Operations
154bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
155{
156 // NB: we have to create the window lazily because of backward compatibility,
157 // old applications may create a wxTaskBarIcon instance before wxApp
158 // is initialized (as samples/taskbar used to do)
159 if (!m_win)
160 {
161 m_win = new wxTaskBarIconWindow(this);
162 }
163
164 m_icon = icon;
165 m_strTooltip = tooltip;
166
167 NotifyIconData notifyData(GetHwndOf(m_win));
168
169 if (icon.Ok())
170 {
171 notifyData.uFlags |= NIF_ICON;
172 notifyData.hIcon = GetHiconOf(icon);
173 }
174
175 // set NIF_TIP even for an empty tooltip: otherwise it would be impossible
176 // to remove an existing tooltip using this function
177 notifyData.uFlags |= NIF_TIP;
178 if ( !tooltip.empty() )
179 {
180 wxStrncpy(notifyData.szTip, tooltip.c_str(), WXSIZEOF(notifyData.szTip));
181 }
182
183 bool ok = wxShellNotifyIcon(m_iconAdded ? NIM_MODIFY
184 : NIM_ADD, &notifyData) != 0;
185
186 if ( !m_iconAdded && ok )
187 m_iconAdded = true;
188
189 return ok;
190}
191
192bool wxTaskBarIcon::RemoveIcon()
193{
194 if (!m_iconAdded)
195 return false;
196
197 m_iconAdded = false;
198
199 NotifyIconData notifyData(GetHwndOf(m_win));
200
201 return wxShellNotifyIcon(NIM_DELETE, &notifyData) != 0;
202}
203
204#if wxUSE_MENUS
205bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
206{
207 wxASSERT_MSG( m_win != NULL, _T("taskbar icon not initialized") );
208
209 static bool s_inPopup = false;
210
211 if (s_inPopup)
212 return false;
213
214 s_inPopup = true;
215
216 int x, y;
217 wxGetMousePosition(&x, &y);
218
219 m_win->Move(x, y);
220
221 m_win->PushEventHandler(this);
222
223 menu->UpdateUI();
224
225 // the SetForegroundWindow() and PostMessage() calls are needed to work
226 // around Win32 bug with the popup menus shown for the notifications as
227 // documented at http://support.microsoft.com/kb/q135788/
228 ::SetForegroundWindow(GetHwndOf(m_win));
229
230 bool rval = m_win->PopupMenu(menu, 0, 0);
231
232 ::PostMessage(GetHwndOf(m_win), WM_NULL, 0, 0L);
233
234 m_win->PopEventHandler(false);
235
236 s_inPopup = false;
237
238 return rval;
239}
240#endif // wxUSE_MENUS
241
242void wxTaskBarIcon::RegisterWindowMessages()
243{
244 static bool s_registered = false;
245
246 if ( !s_registered )
247 {
248 // Taskbar restart msg will be sent to us if the icon needs to be redrawn
249 gs_msgRestartTaskbar = RegisterWindowMessage(wxT("TaskbarCreated"));
250
251 // Also register the taskbar message here
252 gs_msgTaskbar = ::RegisterWindowMessage(wxT("wxTaskBarIconMessage"));
253
254 s_registered = true;
255 }
256}
257
258// ----------------------------------------------------------------------------
259// wxTaskBarIcon window proc
260// ----------------------------------------------------------------------------
261
262long wxTaskBarIcon::WindowProc(unsigned int msg,
263 unsigned int WXUNUSED(wParam),
264 long lParam)
265{
266 wxEventType eventType = 0;
267
268 if (msg == gs_msgRestartTaskbar) // does the icon need to be redrawn?
269 {
270 m_iconAdded = false;
271 SetIcon(m_icon, m_strTooltip);
272 }
273
274 // this function should only be called for gs_msg(Restart)Taskbar messages
275 wxASSERT(msg == gs_msgTaskbar);
276
277 switch (lParam)
278 {
279 case WM_LBUTTONDOWN:
280 eventType = wxEVT_TASKBAR_LEFT_DOWN;
281 break;
282
283 case WM_LBUTTONUP:
284 eventType = wxEVT_TASKBAR_LEFT_UP;
285 break;
286
287 case WM_RBUTTONDOWN:
288 eventType = wxEVT_TASKBAR_RIGHT_DOWN;
289 break;
290
291 case WM_RBUTTONUP:
292 eventType = wxEVT_TASKBAR_RIGHT_UP;
293 break;
294
295 case WM_LBUTTONDBLCLK:
296 eventType = wxEVT_TASKBAR_LEFT_DCLICK;
297 break;
298
299 case WM_RBUTTONDBLCLK:
300 eventType = wxEVT_TASKBAR_RIGHT_DCLICK;
301 break;
302
303 case WM_MOUSEMOVE:
304 eventType = wxEVT_TASKBAR_MOVE;
305 break;
306
307 default:
308 break;
309 }
310
311 if (eventType)
312 {
313 wxTaskBarIconEvent event(eventType, this);
314
315 ProcessEvent(event);
316 }
317
318 return 0;
319}
320
321#endif // wxUSE_TASKBARICON
322