]> git.saurik.com Git - wxWidgets.git/blob - src/msw/taskbar.cpp
39344c02a0ec86319c6f005ae7bfbb0d21e6c3e3
[wxWidgets.git] / src / msw / taskbar.cpp
1 /////////////////////////////////////////////////////////////////////////
2 // File: taskbar.cpp
3 // Purpose: Implements wxTaskBarIcon class for manipulating icons on
4 // the Windows task bar.
5 // Author: Julian Smart
6 // Modified by:
7 // Created: 24/3/98
8 // RCS-ID: $Id$
9 // Copyright: (c)
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////
12
13 #ifdef __GNUG__
14 #pragma implementation "taskbar.h"
15 #endif
16
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 #ifndef WX_PRECOMP
25 #include "wx/defs.h"
26 #include "wx/window.h"
27 #include "wx/frame.h"
28 #include "wx/utils.h"
29 #include "wx/menu.h"
30 #endif
31
32 #if defined(__WIN95__) && !defined(__TWIN32__)
33
34 #include <windows.h>
35
36 #include "wx/msw/winundef.h"
37
38 #include <string.h>
39 #include "wx/taskbar.h"
40 #include "wx/msw/private.h"
41
42 #ifndef __TWIN32__
43 #ifdef __GNUWIN32_OLD__
44 #include "wx/msw/gnuwin32/extra.h"
45 #endif
46 #endif
47
48 #ifdef __SALFORDC__
49 #include <shellapi.h>
50 #endif
51
52 #include "wx/listimpl.cpp"
53 WX_DEFINE_LIST(wxTaskBarIconList);
54
55 LRESULT APIENTRY _EXPORT wxTaskBarIconWindowProc( HWND hWnd, unsigned msg,
56 UINT wParam, LONG lParam );
57
58 wxChar *wxTaskBarWindowClass = (wxChar*) wxT("wxTaskBarWindowClass");
59
60 wxTaskBarIconList wxTaskBarIcon::sm_taskBarIcons;
61 bool wxTaskBarIcon::sm_registeredClass = FALSE;
62 UINT wxTaskBarIcon::sm_taskbarMsg = 0;
63
64 DEFINE_EVENT_TYPE( wxEVT_TASKBAR_MOVE )
65 DEFINE_EVENT_TYPE( wxEVT_TASKBAR_LEFT_DOWN )
66 DEFINE_EVENT_TYPE( wxEVT_TASKBAR_LEFT_UP )
67 DEFINE_EVENT_TYPE( wxEVT_TASKBAR_RIGHT_DOWN )
68 DEFINE_EVENT_TYPE( wxEVT_TASKBAR_RIGHT_UP )
69 DEFINE_EVENT_TYPE( wxEVT_TASKBAR_LEFT_DCLICK )
70 DEFINE_EVENT_TYPE( wxEVT_TASKBAR_RIGHT_DCLICK )
71
72 #if WXWIN_COMPATIBILITY_2_4
73 BEGIN_EVENT_TABLE(wxTaskBarIcon, wxEvtHandler)
74 EVT_TASKBAR_MOVE (wxTaskBarIcon::_OnMouseMove)
75 EVT_TASKBAR_LEFT_DOWN (wxTaskBarIcon::_OnLButtonDown)
76 EVT_TASKBAR_LEFT_UP (wxTaskBarIcon::_OnLButtonUp)
77 EVT_TASKBAR_RIGHT_DOWN (wxTaskBarIcon::_OnRButtonDown)
78 EVT_TASKBAR_RIGHT_UP (wxTaskBarIcon::_OnRButtonUp)
79 EVT_TASKBAR_LEFT_DCLICK (wxTaskBarIcon::_OnLButtonDClick)
80 EVT_TASKBAR_RIGHT_DCLICK (wxTaskBarIcon::_OnRButtonDClick)
81 END_EVENT_TABLE()
82 #endif
83
84
85 IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
86
87
88 wxTaskBarIcon::wxTaskBarIcon(void)
89 {
90 m_hWnd = 0;
91 m_iconAdded = false;
92
93 AddObject(this);
94
95 if (RegisterWindowClass())
96 m_hWnd = CreateTaskBarWindow();
97 }
98
99 wxTaskBarIcon::~wxTaskBarIcon(void)
100 {
101 RemoveObject(this);
102
103 if (m_iconAdded)
104 {
105 RemoveIcon();
106 }
107
108 if (m_hWnd)
109 {
110 ::DestroyWindow((HWND) m_hWnd);
111 m_hWnd = 0;
112 }
113 }
114
115 // Operations
116 bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
117 {
118 if (!IsOk())
119 return false;
120
121 NOTIFYICONDATA notifyData;
122
123 memset(&notifyData, 0, sizeof(notifyData));
124 notifyData.cbSize = sizeof(notifyData);
125 notifyData.hWnd = (HWND) m_hWnd;
126 notifyData.uCallbackMessage = sm_taskbarMsg;
127 notifyData.uFlags = NIF_MESSAGE ;
128 if (icon.Ok())
129 {
130 notifyData.uFlags |= NIF_ICON;
131 notifyData.hIcon = (HICON) icon.GetHICON();
132 }
133
134 if (((const wxChar*) tooltip != NULL) && (tooltip != wxT("")))
135 {
136 notifyData.uFlags |= NIF_TIP ;
137 lstrcpyn(notifyData.szTip, WXSTRINGCAST tooltip, sizeof(notifyData.szTip));
138 }
139
140 notifyData.uID = 99;
141
142 if (m_iconAdded)
143 return (Shell_NotifyIcon(NIM_MODIFY, & notifyData) != 0);
144 else
145 {
146 m_iconAdded = (Shell_NotifyIcon(NIM_ADD, & notifyData) != 0);
147 return m_iconAdded;
148 }
149 }
150
151 bool wxTaskBarIcon::RemoveIcon(void)
152 {
153 if (!m_iconAdded)
154 return false;
155
156 NOTIFYICONDATA notifyData;
157
158 memset(&notifyData, 0, sizeof(notifyData));
159 notifyData.cbSize = sizeof(notifyData);
160 notifyData.hWnd = (HWND) m_hWnd;
161 notifyData.uCallbackMessage = sm_taskbarMsg;
162 notifyData.uFlags = NIF_MESSAGE;
163 notifyData.hIcon = 0 ; // hIcon;
164 notifyData.uID = 99;
165 m_iconAdded = false;
166
167 return (Shell_NotifyIcon(NIM_DELETE, & notifyData) != 0);
168 }
169
170 bool wxTaskBarIcon::PopupMenu(wxMenu *menu) //, int x, int y);
171 {
172 // OK, so I know this isn't thread-friendly, but
173 // what to do? We need this check.
174
175 static bool s_inPopup = false;
176
177 if (s_inPopup)
178 return false;
179
180 s_inPopup = true;
181
182 bool rval = false;
183 wxWindow* win;
184 int x, y;
185 wxGetMousePosition(&x, &y);
186
187 // is wxFrame the best window type to use???
188 win = new wxFrame(NULL, -1, wxEmptyString, wxPoint(x,y), wxSize(-1,-1), 0);
189 win->PushEventHandler(this);
190
191 // Remove from record of top-level windows, or will confuse wxWindows
192 // if we try to exit right now.
193 wxTopLevelWindows.DeleteObject(win);
194
195 menu->UpdateUI();
196
197 // Work around a WIN32 bug
198 ::SetForegroundWindow ((HWND) win->GetHWND ());
199
200 rval = win->PopupMenu(menu, 0, 0);
201
202 // Work around a WIN32 bug
203 ::PostMessage ((HWND) win->GetHWND(),WM_NULL,0,0L);
204
205 win->PopEventHandler(false);
206 win->Destroy();
207 delete win;
208
209 s_inPopup = false;
210
211 return rval;
212 }
213
214 #if WXWIN_COMPATIBILITY_2_4
215 // Overridables
216 void wxTaskBarIcon::OnMouseMove(wxEvent&) {}
217 void wxTaskBarIcon::OnLButtonDown(wxEvent&) {}
218 void wxTaskBarIcon::OnLButtonUp(wxEvent&) {}
219 void wxTaskBarIcon::OnRButtonDown(wxEvent&) {}
220 void wxTaskBarIcon::OnRButtonUp(wxEvent&) {}
221 void wxTaskBarIcon::OnLButtonDClick(wxEvent&) {}
222 void wxTaskBarIcon::OnRButtonDClick(wxEvent&) {}
223
224 void wxTaskBarIcon::_OnMouseMove(wxEvent& e) { OnMouseMove(e); }
225 void wxTaskBarIcon::_OnLButtonDown(wxEvent& e) { OnLButtonDown(e); }
226 void wxTaskBarIcon::_OnLButtonUp(wxEvent& e) { OnLButtonUp(e); }
227 void wxTaskBarIcon::_OnRButtonDown(wxEvent& e) { OnRButtonDown(e); }
228 void wxTaskBarIcon::_OnRButtonUp(wxEvent& e) { OnRButtonUp(e); }
229 void wxTaskBarIcon::_OnLButtonDClick(wxEvent& e) { OnLButtonDClick(e); }
230 void wxTaskBarIcon::_OnRButtonDClick(wxEvent& e) { OnRButtonDClick(e); }
231 #endif
232
233 wxTaskBarIcon* wxTaskBarIcon::FindObjectForHWND(WXHWND hWnd)
234 {
235 wxTaskBarIconList::Node *node = sm_taskBarIcons.GetFirst();
236 while (node)
237 {
238 wxTaskBarIcon *obj = node->GetData();
239 if (obj->GetHWND() == hWnd)
240 return obj;
241 node = node->GetNext();
242 }
243 return NULL;
244 }
245
246 void wxTaskBarIcon::AddObject(wxTaskBarIcon* obj)
247 {
248 sm_taskBarIcons.Append(obj);
249 }
250
251 void wxTaskBarIcon::RemoveObject(wxTaskBarIcon* obj)
252 {
253 sm_taskBarIcons.DeleteObject(obj);
254 }
255
256 bool wxTaskBarIcon::RegisterWindowClass()
257 {
258 if (sm_registeredClass)
259 return true;
260
261 // Also register the taskbar message here
262 sm_taskbarMsg = ::RegisterWindowMessage(wxT("wxTaskBarIconMessage"));
263
264 WNDCLASS wc;
265 bool rc;
266
267 HINSTANCE hInstance = GetModuleHandle(NULL);
268
269 /*
270 * set up and register window class
271 */
272 wc.style = CS_HREDRAW | CS_VREDRAW;
273 wc.lpfnWndProc = (WNDPROC) wxTaskBarIconWindowProc;
274 wc.cbClsExtra = 0;
275 wc.cbWndExtra = 0;
276 wc.hInstance = hInstance;
277 wc.hIcon = 0;
278 wc.hCursor = 0;
279 wc.hbrBackground = 0;
280 wc.lpszMenuName = NULL;
281 wc.lpszClassName = wxTaskBarWindowClass ;
282 rc = (::RegisterClass( &wc ) != 0);
283
284 sm_registeredClass = (rc != 0);
285
286 return( (rc != 0) );
287 }
288
289 WXHWND wxTaskBarIcon::CreateTaskBarWindow()
290 {
291 HINSTANCE hInstance = GetModuleHandle(NULL);
292
293 HWND hWnd = CreateWindowEx (0, wxTaskBarWindowClass,
294 wxT("wxTaskBarWindow"),
295 WS_OVERLAPPED,
296 0,
297 0,
298 10,
299 10,
300 NULL,
301 (HMENU) 0,
302 hInstance,
303 NULL);
304
305 return (WXHWND) hWnd;
306 }
307
308 long wxTaskBarIcon::WindowProc( WXHWND hWnd, unsigned int msg, unsigned int wParam, long lParam )
309 {
310 wxEventType eventType = 0;
311
312 if (msg != sm_taskbarMsg)
313 return DefWindowProc((HWND) hWnd, msg, wParam, lParam);
314
315 switch (lParam)
316 {
317 case WM_LBUTTONDOWN:
318 eventType = wxEVT_TASKBAR_LEFT_DOWN;
319 break;
320
321 case WM_LBUTTONUP:
322 eventType = wxEVT_TASKBAR_LEFT_UP;
323 break;
324
325 case WM_RBUTTONDOWN:
326 eventType = wxEVT_TASKBAR_RIGHT_DOWN;
327 break;
328
329 case WM_RBUTTONUP:
330 eventType = wxEVT_TASKBAR_RIGHT_UP;
331 break;
332
333 case WM_LBUTTONDBLCLK:
334 eventType = wxEVT_TASKBAR_LEFT_DCLICK;
335 break;
336
337 case WM_RBUTTONDBLCLK:
338 eventType = wxEVT_TASKBAR_RIGHT_DCLICK;
339 break;
340
341 case WM_MOUSEMOVE:
342 eventType = wxEVT_TASKBAR_MOVE;
343 break;
344
345 default:
346 break;
347 }
348
349 if (eventType) {
350 wxTaskBarIconEvent event(eventType, this);
351
352 ProcessEvent(event);
353 }
354 return 0;
355 }
356
357 LRESULT APIENTRY _EXPORT wxTaskBarIconWindowProc( HWND hWnd, unsigned msg,
358 UINT wParam, LONG lParam )
359 {
360 wxTaskBarIcon *obj = wxTaskBarIcon::FindObjectForHWND((WXHWND) hWnd);
361 if (obj)
362 return obj->WindowProc((WXHWND) hWnd, msg, wParam, lParam);
363 else
364 return DefWindowProc(hWnd, msg, wParam, lParam);
365 }
366
367 #endif
368 // __WIN95__