]> git.saurik.com Git - wxWidgets.git/blame - src/msw/taskbar.cpp
fix to last custom draw fix: only leave space for the image in the first column
[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__
17#pragma hdrstop
18#endif
19
20#ifndef WX_PRECOMP
21#include "wx/defs.h"
ad5c34f3
JS
22#include "wx/window.h"
23#include "wx/frame.h"
24#include "wx/utils.h"
0ae2df30 25#include "wx/menu.h"
2bda0e17
KB
26#endif
27
4676948b 28#include "wx/msw/private.h"
c25a510b
JS
29#include "wx/msw/winundef.h"
30
2bda0e17 31#include <string.h>
6af507f7 32#include "wx/taskbar.h"
2bda0e17 33
4676948b
JS
34#ifdef __WXWINCE__
35 #include <winreg.h>
c42404a5 36 #include <shellapi.h>
ce3ed50d
JS
37#endif
38
4d0d77af
VZ
39// initialized on demand
40UINT gs_msgTaskbar = 0;
41UINT gs_msgRestartTaskbar = 0;
2bda0e17 42
6af507f7 43#if WXWIN_COMPATIBILITY_2_4
41819cbe 44BEGIN_EVENT_TABLE(wxTaskBarIcon, wxTaskBarIconBase)
69ecd30f
RD
45 EVT_TASKBAR_MOVE (wxTaskBarIcon::_OnMouseMove)
46 EVT_TASKBAR_LEFT_DOWN (wxTaskBarIcon::_OnLButtonDown)
47 EVT_TASKBAR_LEFT_UP (wxTaskBarIcon::_OnLButtonUp)
48 EVT_TASKBAR_RIGHT_DOWN (wxTaskBarIcon::_OnRButtonDown)
49 EVT_TASKBAR_RIGHT_UP (wxTaskBarIcon::_OnRButtonUp)
50 EVT_TASKBAR_LEFT_DCLICK (wxTaskBarIcon::_OnLButtonDClick)
51 EVT_TASKBAR_RIGHT_DCLICK (wxTaskBarIcon::_OnRButtonDClick)
56194595 52END_EVENT_TABLE()
6af507f7 53#endif
56194595
RD
54
55
56IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
56194595 57
4d0d77af
VZ
58// ============================================================================
59// implementation
60// ============================================================================
61
1e6d9c20
VS
62// ----------------------------------------------------------------------------
63// wxTaskBarIconWindow: helper window
64// ----------------------------------------------------------------------------
65
66// NB: this class serves two purposes:
67// 1. win32 needs a HWND associated with taskbar icon, this provides it
68// 2. we need wxTopLevelWindow so that the app doesn't exit when
69// last frame is closed but there still is a taskbar icon
70class wxTaskBarIconWindow : public wxFrame
71{
72public:
73 wxTaskBarIconWindow(wxTaskBarIcon *icon)
bfbb0b4c 74 : wxFrame(NULL, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0),
1e6d9c20
VS
75 m_icon(icon)
76 {
77 }
bfbb0b4c 78
1e6d9c20
VS
79 WXLRESULT MSWWindowProc(WXUINT msg,
80 WXWPARAM wParam, WXLPARAM lParam)
81 {
82 if (msg == gs_msgRestartTaskbar || msg == gs_msgTaskbar)
83 {
dda36afd 84 return m_icon->WindowProc(msg, wParam, lParam);
1e6d9c20
VS
85 }
86 else
87 {
88 return wxFrame::MSWWindowProc(msg, wParam, lParam);
89 }
90 }
91
92private:
93 wxTaskBarIcon *m_icon;
94};
95
bfbb0b4c 96
4d0d77af
VZ
97// ----------------------------------------------------------------------------
98// NotifyIconData: wrapper around NOTIFYICONDATA
99// ----------------------------------------------------------------------------
56194595 100
4d0d77af
VZ
101struct NotifyIconData : public NOTIFYICONDATA
102{
103 NotifyIconData(WXHWND hwnd)
104 {
105 memset(this, 0, sizeof(NOTIFYICONDATA));
106 cbSize = sizeof(NOTIFYICONDATA);
107 hWnd = (HWND) hwnd;
108 uCallbackMessage = gs_msgTaskbar;
109 uFlags = NIF_MESSAGE;
110
111 // we use the same id for all taskbar icons as we don't need it to
112 // distinguish between them
113 uID = 99;
114 }
115};
116
117// ----------------------------------------------------------------------------
118// wxTaskBarIcon
119// ----------------------------------------------------------------------------
120
121wxTaskBarIcon::wxTaskBarIcon()
2bda0e17 122{
1e6d9c20 123 m_win = NULL;
04cd30de 124 m_iconAdded = false;
1e6d9c20 125 RegisterWindowMessages();
2bda0e17
KB
126}
127
4d0d77af 128wxTaskBarIcon::~wxTaskBarIcon()
2bda0e17 129{
2bda0e17 130 if (m_iconAdded)
2bda0e17 131 RemoveIcon();
2bda0e17 132
1e6d9c20
VS
133 if (m_win)
134 m_win->Destroy();
2bda0e17
KB
135}
136
137// Operations
138bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
139{
3103e8a9
JS
140 // NB: we have to create the window lazily because of backward compatibility,
141 // old applications may create a wxTaskBarIcon instance before wxApp
1e6d9c20
VS
142 // is initialized (as samples/taskbar used to do)
143 if (!m_win)
144 {
145 m_win = new wxTaskBarIconWindow(this);
146 }
2bda0e17 147
4d0d77af
VZ
148 m_icon = icon;
149 m_strTooltip = tooltip;
150
1e6d9c20 151 NotifyIconData notifyData((HWND)m_win->GetHWND());
2bda0e17 152
e96360ef 153 if (icon.Ok())
2bda0e17 154 {
e96360ef 155 notifyData.uFlags |= NIF_ICON;
4d0d77af 156 notifyData.hIcon = GetHiconOf(icon);
2bda0e17
KB
157 }
158
4d0d77af 159 if ( !tooltip.empty() )
2bda0e17 160 {
4d0d77af 161 notifyData.uFlags |= NIF_TIP;
4676948b
JS
162// lstrcpyn(notifyData.szTip, tooltip.c_str(), WXSIZEOF(notifyData.szTip));
163 wxStrncpy(notifyData.szTip, tooltip.c_str(), WXSIZEOF(notifyData.szTip));
2bda0e17
KB
164 }
165
4d0d77af
VZ
166 bool ok = Shell_NotifyIcon(m_iconAdded ? NIM_MODIFY
167 : NIM_ADD, &notifyData) != 0;
2bda0e17 168
4d0d77af
VZ
169 if ( !m_iconAdded && ok )
170 m_iconAdded = true;
171
172 return ok;
2bda0e17
KB
173}
174
4d0d77af 175bool wxTaskBarIcon::RemoveIcon()
2bda0e17
KB
176{
177 if (!m_iconAdded)
04cd30de 178 return false;
2bda0e17 179
04cd30de 180 m_iconAdded = false;
2bda0e17 181
1e6d9c20 182 NotifyIconData notifyData((HWND)m_win->GetHWND());
4d0d77af
VZ
183
184 return Shell_NotifyIcon(NIM_DELETE, &notifyData) != 0;
2bda0e17
KB
185}
186
4d0d77af 187bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
69ecd30f 188{
1e6d9c20
VS
189 wxASSERT_MSG( m_win != NULL, _T("taskbar icon not initialized") );
190
04cd30de 191 static bool s_inPopup = false;
c7527e3f
JS
192
193 if (s_inPopup)
04cd30de 194 return false;
c7527e3f 195
04cd30de 196 s_inPopup = true;
c7527e3f 197
69ecd30f
RD
198 int x, y;
199 wxGetMousePosition(&x, &y);
200
1e6d9c20 201 m_win->Move(x, y);
bfbb0b4c 202
1e6d9c20 203 m_win->PushEventHandler(this);
d66d9d5b 204
50bcd1ae
JS
205 menu->UpdateUI();
206
f6bcfd97 207 // Work around a WIN32 bug
1e6d9c20 208 ::SetForegroundWindow((HWND)m_win->GetHWND());
f6bcfd97 209
1e6d9c20 210 bool rval = m_win->PopupMenu(menu, 0, 0);
69ecd30f 211
f6bcfd97 212 // Work around a WIN32 bug
1e6d9c20 213 ::PostMessage((HWND)m_win->GetHWND(), WM_NULL, 0, 0L);
f6bcfd97 214
1e6d9c20 215 m_win->PopEventHandler(false);
c7527e3f 216
04cd30de 217 s_inPopup = false;
d66d9d5b 218
69ecd30f
RD
219 return rval;
220}
221
6af507f7 222#if WXWIN_COMPATIBILITY_2_4
2bda0e17 223// Overridables
41819cbe
VS
224void wxTaskBarIcon::OnMouseMove(wxEvent& e) { e.Skip(); }
225void wxTaskBarIcon::OnLButtonDown(wxEvent& e) { e.Skip(); }
226void wxTaskBarIcon::OnLButtonUp(wxEvent& e) { e.Skip(); }
227void wxTaskBarIcon::OnRButtonDown(wxEvent& e) { e.Skip(); }
228void wxTaskBarIcon::OnRButtonUp(wxEvent& e) { e.Skip(); }
229void wxTaskBarIcon::OnLButtonDClick(wxEvent& e) { e.Skip(); }
230void wxTaskBarIcon::OnRButtonDClick(wxEvent& e) { e.Skip(); }
2bda0e17 231
6466d41e
VS
232void wxTaskBarIcon::_OnMouseMove(wxTaskBarIconEvent& e)
233 { OnMouseMove(e); }
234void wxTaskBarIcon::_OnLButtonDown(wxTaskBarIconEvent& e)
235 { OnLButtonDown(e); }
236void wxTaskBarIcon::_OnLButtonUp(wxTaskBarIconEvent& e)
237 { OnLButtonUp(e); }
238void wxTaskBarIcon::_OnRButtonDown(wxTaskBarIconEvent& e)
239 { OnRButtonDown(e); }
240void wxTaskBarIcon::_OnRButtonUp(wxTaskBarIconEvent& e)
241 { OnRButtonUp(e); }
242void wxTaskBarIcon::_OnLButtonDClick(wxTaskBarIconEvent& e)
243 { OnLButtonDClick(e); }
244void wxTaskBarIcon::_OnRButtonDClick(wxTaskBarIconEvent& e)
245 { OnRButtonDClick(e); }
6af507f7 246#endif
69ecd30f 247
1e6d9c20 248void wxTaskBarIcon::RegisterWindowMessages()
2bda0e17 249{
4d0d77af 250 static bool s_registered = false;
2bda0e17 251
1e6d9c20 252 if ( !s_registered )
bfbb0b4c 253 {
1e6d9c20
VS
254 // Taskbar restart msg will be sent to us if the icon needs to be redrawn
255 gs_msgRestartTaskbar = RegisterWindowMessage(wxT("TaskbarCreated"));
2bda0e17 256
1e6d9c20
VS
257 // Also register the taskbar message here
258 gs_msgTaskbar = ::RegisterWindowMessage(wxT("wxTaskBarIconMessage"));
2bda0e17 259
1e6d9c20
VS
260 s_registered = true;
261 }
2bda0e17
KB
262}
263
4d0d77af
VZ
264// ----------------------------------------------------------------------------
265// wxTaskBarIcon window proc
266// ----------------------------------------------------------------------------
267
dda36afd
VS
268long wxTaskBarIcon::WindowProc(unsigned int msg,
269 unsigned int WXUNUSED(wParam),
4d0d77af 270 long lParam)
2bda0e17 271{
56194595
RD
272 wxEventType eventType = 0;
273
4d0d77af
VZ
274 if (msg == gs_msgRestartTaskbar) // does the icon need to be redrawn?
275 {
276 m_iconAdded = false;
277 SetIcon(m_icon, m_strTooltip);
278 }
279
1e6d9c20
VS
280 // this function should only be called for gs_msg(Restart)Taskbar messages
281 wxASSERT(msg == gs_msgTaskbar);
2bda0e17
KB
282
283 switch (lParam)
284 {
c42404a5 285 case WM_LBUTTONDOWN:
56194595
RD
286 eventType = wxEVT_TASKBAR_LEFT_DOWN;
287 break;
2bda0e17 288
c42404a5 289 case WM_LBUTTONUP:
56194595
RD
290 eventType = wxEVT_TASKBAR_LEFT_UP;
291 break;
2bda0e17 292
c42404a5 293 case WM_RBUTTONDOWN:
56194595
RD
294 eventType = wxEVT_TASKBAR_RIGHT_DOWN;
295 break;
2bda0e17 296
c42404a5 297 case WM_RBUTTONUP:
56194595
RD
298 eventType = wxEVT_TASKBAR_RIGHT_UP;
299 break;
2bda0e17 300
c42404a5 301 case WM_LBUTTONDBLCLK:
56194595
RD
302 eventType = wxEVT_TASKBAR_LEFT_DCLICK;
303 break;
2bda0e17 304
c42404a5 305 case WM_RBUTTONDBLCLK:
56194595
RD
306 eventType = wxEVT_TASKBAR_RIGHT_DCLICK;
307 break;
2bda0e17 308
c42404a5 309 case WM_MOUSEMOVE:
56194595
RD
310 eventType = wxEVT_TASKBAR_MOVE;
311 break;
2bda0e17 312
c42404a5 313 default:
56194595 314 break;
4d0d77af 315 }
56194595 316
4d0d77af
VZ
317 if (eventType)
318 {
fa1c12bd 319 wxTaskBarIconEvent event(eventType, this);
56194595
RD
320
321 ProcessEvent(event);
322 }
4d0d77af 323
2bda0e17
KB
324 return 0;
325}