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