]> git.saurik.com Git - wxWidgets.git/blame - src/msw/taskbar.cpp
correction to last commit: don't test unsetenv() return value, it's void under Darwin
[wxWidgets.git] / src / msw / taskbar.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////
a71d815b 2// File: src/msw/taskbar.cpp
c42404a5 3// Purpose: Implements wxTaskBarIcon class for manipulating icons on
2bda0e17
KB
4// the Windows task bar.
5// Author: Julian Smart
1e6d9c20 6// Modified by: Vaclav Slavik
2bda0e17
KB
7// Created: 24/3/98
8// RCS-ID: $Id$
9// Copyright: (c)
65571936 10// Licence: wxWindows licence
2bda0e17
KB
11/////////////////////////////////////////////////////////////////////////
12
2bda0e17
KB
13// For compilers that support precompilation, includes "wx.h".
14#include "wx/wxprec.h"
15
16#ifdef __BORLANDC__
7520f3da 17 #pragma hdrstop
2bda0e17
KB
18#endif
19
4f167b46
VZ
20#if wxUSE_TASKBARICON
21
2bda0e17 22#ifndef WX_PRECOMP
7520f3da
WS
23 #include "wx/window.h"
24 #include "wx/frame.h"
25 #include "wx/utils.h"
26 #include "wx/menu.h"
2bda0e17
KB
27#endif
28
4676948b 29#include "wx/msw/private.h"
c25a510b
JS
30#include "wx/msw/winundef.h"
31
2bda0e17 32#include <string.h>
6af507f7 33#include "wx/taskbar.h"
2bda0e17 34
4676948b
JS
35#ifdef __WXWINCE__
36 #include <winreg.h>
c42404a5 37 #include <shellapi.h>
ce3ed50d
JS
38#endif
39
4d0d77af
VZ
40// initialized on demand
41UINT gs_msgTaskbar = 0;
42UINT gs_msgRestartTaskbar = 0;
2bda0e17 43
56194595
RD
44
45IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
56194595 46
4d0d77af
VZ
47// ============================================================================
48// implementation
49// ============================================================================
50
1e6d9c20
VS
51// ----------------------------------------------------------------------------
52// wxTaskBarIconWindow: helper window
53// ----------------------------------------------------------------------------
54
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
59class wxTaskBarIconWindow : public wxFrame
60{
61public:
62 wxTaskBarIconWindow(wxTaskBarIcon *icon)
bfbb0b4c 63 : wxFrame(NULL, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0),
1e6d9c20
VS
64 m_icon(icon)
65 {
66 }
bfbb0b4c 67
1e6d9c20
VS
68 WXLRESULT MSWWindowProc(WXUINT msg,
69 WXWPARAM wParam, WXLPARAM lParam)
70 {
71 if (msg == gs_msgRestartTaskbar || msg == gs_msgTaskbar)
72 {
dda36afd 73 return m_icon->WindowProc(msg, wParam, lParam);
1e6d9c20
VS
74 }
75 else
76 {
77 return wxFrame::MSWWindowProc(msg, wParam, lParam);
78 }
79 }
80
81private:
82 wxTaskBarIcon *m_icon;
83};
84
bfbb0b4c 85
4d0d77af
VZ
86// ----------------------------------------------------------------------------
87// NotifyIconData: wrapper around NOTIFYICONDATA
88// ----------------------------------------------------------------------------
56194595 89
4d0d77af
VZ
90struct NotifyIconData : public NOTIFYICONDATA
91{
92 NotifyIconData(WXHWND hwnd)
93 {
94 memset(this, 0, sizeof(NOTIFYICONDATA));
95 cbSize = sizeof(NOTIFYICONDATA);
96 hWnd = (HWND) hwnd;
97 uCallbackMessage = gs_msgTaskbar;
98 uFlags = NIF_MESSAGE;
99
100 // we use the same id for all taskbar icons as we don't need it to
101 // distinguish between them
102 uID = 99;
103 }
104};
105
106// ----------------------------------------------------------------------------
107// wxTaskBarIcon
108// ----------------------------------------------------------------------------
109
110wxTaskBarIcon::wxTaskBarIcon()
2bda0e17 111{
1e6d9c20 112 m_win = NULL;
04cd30de 113 m_iconAdded = false;
1e6d9c20 114 RegisterWindowMessages();
2bda0e17
KB
115}
116
4d0d77af 117wxTaskBarIcon::~wxTaskBarIcon()
2bda0e17 118{
2bda0e17 119 if (m_iconAdded)
2bda0e17 120 RemoveIcon();
2bda0e17 121
1e6d9c20
VS
122 if (m_win)
123 m_win->Destroy();
2bda0e17
KB
124}
125
126// Operations
127bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
128{
3103e8a9
JS
129 // NB: we have to create the window lazily because of backward compatibility,
130 // old applications may create a wxTaskBarIcon instance before wxApp
1e6d9c20
VS
131 // is initialized (as samples/taskbar used to do)
132 if (!m_win)
133 {
134 m_win = new wxTaskBarIconWindow(this);
135 }
2bda0e17 136
4d0d77af
VZ
137 m_icon = icon;
138 m_strTooltip = tooltip;
139
63b3dc58 140 NotifyIconData notifyData(GetHwndOf(m_win));
2bda0e17 141
e96360ef 142 if (icon.Ok())
2bda0e17 143 {
e96360ef 144 notifyData.uFlags |= NIF_ICON;
4d0d77af 145 notifyData.hIcon = GetHiconOf(icon);
2bda0e17
KB
146 }
147
b2057360
VZ
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;
4d0d77af 151 if ( !tooltip.empty() )
2bda0e17 152 {
4676948b 153 wxStrncpy(notifyData.szTip, tooltip.c_str(), WXSIZEOF(notifyData.szTip));
2bda0e17
KB
154 }
155
4d0d77af
VZ
156 bool ok = Shell_NotifyIcon(m_iconAdded ? NIM_MODIFY
157 : NIM_ADD, &notifyData) != 0;
2bda0e17 158
4d0d77af
VZ
159 if ( !m_iconAdded && ok )
160 m_iconAdded = true;
161
162 return ok;
2bda0e17
KB
163}
164
4d0d77af 165bool wxTaskBarIcon::RemoveIcon()
2bda0e17
KB
166{
167 if (!m_iconAdded)
04cd30de 168 return false;
2bda0e17 169
04cd30de 170 m_iconAdded = false;
2bda0e17 171
63b3dc58 172 NotifyIconData notifyData(GetHwndOf(m_win));
4d0d77af
VZ
173
174 return Shell_NotifyIcon(NIM_DELETE, &notifyData) != 0;
2bda0e17
KB
175}
176
53a118d6 177#if wxUSE_MENUS
4d0d77af 178bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
69ecd30f 179{
1e6d9c20
VS
180 wxASSERT_MSG( m_win != NULL, _T("taskbar icon not initialized") );
181
04cd30de 182 static bool s_inPopup = false;
c7527e3f
JS
183
184 if (s_inPopup)
04cd30de 185 return false;
c7527e3f 186
04cd30de 187 s_inPopup = true;
c7527e3f 188
69ecd30f
RD
189 int x, y;
190 wxGetMousePosition(&x, &y);
191
1e6d9c20 192 m_win->Move(x, y);
bfbb0b4c 193
1e6d9c20 194 m_win->PushEventHandler(this);
d66d9d5b 195
50bcd1ae
JS
196 menu->UpdateUI();
197
63b3dc58
VZ
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));
f6bcfd97 202
1e6d9c20 203 bool rval = m_win->PopupMenu(menu, 0, 0);
69ecd30f 204
63b3dc58 205 ::PostMessage(GetHwndOf(m_win), WM_NULL, 0, 0L);
f6bcfd97 206
1e6d9c20 207 m_win->PopEventHandler(false);
c7527e3f 208
04cd30de 209 s_inPopup = false;
d66d9d5b 210
69ecd30f
RD
211 return rval;
212}
53a118d6 213#endif // wxUSE_MENUS
69ecd30f 214
1e6d9c20 215void wxTaskBarIcon::RegisterWindowMessages()
2bda0e17 216{
4d0d77af 217 static bool s_registered = false;
2bda0e17 218
1e6d9c20 219 if ( !s_registered )
bfbb0b4c 220 {
1e6d9c20
VS
221 // Taskbar restart msg will be sent to us if the icon needs to be redrawn
222 gs_msgRestartTaskbar = RegisterWindowMessage(wxT("TaskbarCreated"));
2bda0e17 223
1e6d9c20
VS
224 // Also register the taskbar message here
225 gs_msgTaskbar = ::RegisterWindowMessage(wxT("wxTaskBarIconMessage"));
2bda0e17 226
1e6d9c20
VS
227 s_registered = true;
228 }
2bda0e17
KB
229}
230
4d0d77af
VZ
231// ----------------------------------------------------------------------------
232// wxTaskBarIcon window proc
233// ----------------------------------------------------------------------------
234
dda36afd
VS
235long wxTaskBarIcon::WindowProc(unsigned int msg,
236 unsigned int WXUNUSED(wParam),
4d0d77af 237 long lParam)
2bda0e17 238{
56194595
RD
239 wxEventType eventType = 0;
240
4d0d77af
VZ
241 if (msg == gs_msgRestartTaskbar) // does the icon need to be redrawn?
242 {
243 m_iconAdded = false;
244 SetIcon(m_icon, m_strTooltip);
245 }
246
1e6d9c20
VS
247 // this function should only be called for gs_msg(Restart)Taskbar messages
248 wxASSERT(msg == gs_msgTaskbar);
2bda0e17
KB
249
250 switch (lParam)
251 {
c42404a5 252 case WM_LBUTTONDOWN:
56194595
RD
253 eventType = wxEVT_TASKBAR_LEFT_DOWN;
254 break;
2bda0e17 255
c42404a5 256 case WM_LBUTTONUP:
56194595
RD
257 eventType = wxEVT_TASKBAR_LEFT_UP;
258 break;
2bda0e17 259
c42404a5 260 case WM_RBUTTONDOWN:
56194595
RD
261 eventType = wxEVT_TASKBAR_RIGHT_DOWN;
262 break;
2bda0e17 263
c42404a5 264 case WM_RBUTTONUP:
56194595
RD
265 eventType = wxEVT_TASKBAR_RIGHT_UP;
266 break;
2bda0e17 267
c42404a5 268 case WM_LBUTTONDBLCLK:
56194595
RD
269 eventType = wxEVT_TASKBAR_LEFT_DCLICK;
270 break;
2bda0e17 271
c42404a5 272 case WM_RBUTTONDBLCLK:
56194595
RD
273 eventType = wxEVT_TASKBAR_RIGHT_DCLICK;
274 break;
2bda0e17 275
c42404a5 276 case WM_MOUSEMOVE:
56194595
RD
277 eventType = wxEVT_TASKBAR_MOVE;
278 break;
2bda0e17 279
c42404a5 280 default:
56194595 281 break;
4d0d77af 282 }
56194595 283
4d0d77af
VZ
284 if (eventType)
285 {
fa1c12bd 286 wxTaskBarIconEvent event(eventType, this);
56194595
RD
287
288 ProcessEvent(event);
289 }
4d0d77af 290
2bda0e17
KB
291 return 0;
292}
4f167b46
VZ
293
294#endif // wxUSE_TASKBARICON
295