]> git.saurik.com Git - wxWidgets.git/blame - src/msw/cursor.cpp
(hopefully) workaround for a carbon bug not always setting the modifiers event record...
[wxWidgets.git] / src / msw / cursor.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: cursor.cpp
3// Purpose: wxCursor class
4// Author: Julian Smart
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
6bf57206 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
0d0512bd
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
0d0512bd 21 #pragma implementation "cursor.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
0d0512bd 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
31#ifndef WX_PRECOMP
0d0512bd
VZ
32 #include "wx/list.h"
33 #include "wx/utils.h"
34 #include "wx/app.h"
fef15b42 35 #include "wx/bitmap.h"
0d0512bd 36 #include "wx/icon.h"
fef15b42 37 #include "wx/cursor.h"
2bda0e17
KB
38#endif
39
2b0b4c55 40#include "wx/module.h"
6cab7411 41#include "wx/image.h"
2bda0e17 42#include "wx/msw/private.h"
04ef50df 43#ifndef __WXMICROWIN__
2bda0e17 44#include "wx/msw/dib.h"
04ef50df 45#endif
2bda0e17 46
47d67540 47#if wxUSE_RESOURCE_LOADING_IN_MSW
0d0512bd
VZ
48 #include "wx/msw/curico.h"
49 #include "wx/msw/curicop.h"
2bda0e17
KB
50#endif
51
0d0512bd
VZ
52// ----------------------------------------------------------------------------
53// wxWin macros
54// ----------------------------------------------------------------------------
55
621b3e21 56IMPLEMENT_DYNAMIC_CLASS(wxCursor, wxGDIObject)
bfbd6dc1
VZ
57
58// ----------------------------------------------------------------------------
59// globals
60// ----------------------------------------------------------------------------
61
62// Current cursor, in order to hang on to cursor handle when setting the cursor
63// globally
64static wxCursor *gs_globalCursor = NULL;
65
66// ----------------------------------------------------------------------------
67// private classes
68// ----------------------------------------------------------------------------
69
70class wxCursorModule : public wxModule
71{
72public:
73 virtual bool OnInit()
74 {
75 gs_globalCursor = new wxCursor;
76
77 return TRUE;
78 }
79
80 virtual void OnExit()
81 {
82 delete gs_globalCursor;
83 gs_globalCursor = (wxCursor *)NULL;
84 }
85};
86
87// ============================================================================
88// implementation
89// ============================================================================
2bda0e17 90
0d0512bd
VZ
91// ----------------------------------------------------------------------------
92// wxCursorRefData
93// ----------------------------------------------------------------------------
94
95wxCursorRefData::wxCursorRefData()
2bda0e17 96{
0d0512bd
VZ
97 m_width = 32;
98 m_height = 32;
99
f20ad12c 100 m_destroyCursor = TRUE;
2bda0e17
KB
101}
102
0d0512bd 103void wxCursorRefData::Free()
2bda0e17 104{
032af30f
VZ
105 if ( m_hCursor )
106 {
04ef50df 107#ifndef __WXMICROWIN__
032af30f
VZ
108 if ( m_destroyCursor )
109 ::DestroyCursor((HCURSOR)m_hCursor);
04ef50df 110#endif
032af30f
VZ
111
112 m_hCursor = 0;
113 }
2bda0e17
KB
114}
115
0d0512bd 116// ----------------------------------------------------------------------------
2bda0e17 117// Cursors
0d0512bd
VZ
118// ----------------------------------------------------------------------------
119
120wxCursor::wxCursor()
2bda0e17
KB
121{
122}
123
bff4ec63
VZ
124wxCursor::wxCursor( const wxImage & image )
125{
126 //image has to be 32x32
127 wxImage image32 = image.Scale(32,32);
128 unsigned char * rgbBits = image32.GetData();
129 int w = image32.GetWidth() ;
130 int h = image32.GetHeight() ;
131 bool bHasMask = image32.HasMask() ;
132 int imagebitcount = (w*h)/8;
133
134 unsigned char r, g, b ;
135 unsigned char * bits = new unsigned char [imagebitcount];
136 unsigned char * maskBits = new unsigned char [imagebitcount];
137
138 int i,j, i8; unsigned char c, cMask;
139 for (i=0; i<imagebitcount; i++)
140 {
141 bits[i] = 0;
142 i8 = i * 8;
143//unlike gtk, the pixels go in the opposite order in the bytes
144 cMask = 128;
145 for (j=0; j<8; j++)
146 {
147 // possible overflow if we do the summation first ?
148 c = rgbBits[(i8+j)*3]/3 + rgbBits[(i8+j)*3+1]/3 + rgbBits[(i8+j)*3+2]/3 ;
149 //if average value is > mid grey
150 if (c>127)
151 bits[i] = bits[i] | cMask ;
152 cMask = cMask / 2 ;
153 }
154 }
155 if (bHasMask)
156 {
157 r = image32.GetMaskRed() ;
158 g = image32.GetMaskGreen() ;
159 b = image32.GetMaskBlue() ;
160
161 for (i=0; i<imagebitcount; i++)
162 {
163 maskBits[i] = 0x0;
164 i8 = i * 8;
165
166 cMask = 128;
167 for (j=0; j<8; j++)
168 {
169 if (rgbBits[(i8+j)*3] == r && rgbBits[(i8+j)*3+1] == g && rgbBits[(i8+j)*3+2] == b)
170 maskBits[i] = maskBits[i] | cMask ;
171 cMask = cMask / 2 ;
172 }
173 }
174 }
175 else
176 {
177 for (i=0; i<imagebitcount; i++)
178 maskBits[i]= 0x0 ;
179 }
180
181 int hotSpotX = image32.GetOptionInt(wxCUR_HOTSPOT_X);
182 int hotSpotY = image32.GetOptionInt(wxCUR_HOTSPOT_Y);
183 if (hotSpotX < 0 || hotSpotX >= w)
184 hotSpotX = 0;
185 if (hotSpotY < 0 || hotSpotY >= h)
186 hotSpotY = 0;
187
188 wxCursorRefData *refData = new wxCursorRefData;
189 m_refData = refData;
190 refData->m_hCursor = (WXHCURSOR) CreateCursor ( wxGetInstance(), hotSpotX, hotSpotY, w, h, /*AND*/ maskBits, /*XOR*/ bits );
15dadf31 191
bff4ec63
VZ
192 delete [] bits ;
193 delete [] maskBits;
194
195}
196
0d0512bd
VZ
197wxCursor::wxCursor(const char WXUNUSED(bits)[],
198 int WXUNUSED(width),
199 int WXUNUSED(height),
200 int WXUNUSED(hotSpotX), int WXUNUSED(hotSpotY),
201 const char WXUNUSED(maskBits)[])
2bda0e17
KB
202{
203}
204
0d0512bd
VZ
205wxCursor::wxCursor(const wxString& cursor_file,
206 long flags,
207 int hotSpotX, int hotSpotY)
2bda0e17 208{
04ef50df
JS
209#ifdef __WXMICROWIN__
210 m_refData = NULL;
211#else
0d0512bd
VZ
212 wxCursorRefData *refData = new wxCursorRefData;
213 m_refData = refData;
2bda0e17 214
0d0512bd
VZ
215 if (flags == wxBITMAP_TYPE_CUR_RESOURCE)
216 {
2f851133 217#ifdef __WIN95__
0d0512bd 218 refData->m_hCursor = (WXHCURSOR) LoadImage(wxGetInstance(), cursor_file, IMAGE_CURSOR, 0, 0, 0);
2f851133 219#else
0d0512bd 220 refData->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), cursor_file);
2f851133 221#endif
0d0512bd
VZ
222 }
223 else if (flags == wxBITMAP_TYPE_CUR)
224 {
2f851133 225#ifdef __WIN95__
0d0512bd 226 refData->m_hCursor = (WXHCURSOR) LoadImage(wxGetInstance(), cursor_file, IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
2f851133 227#else
47d67540 228#if wxUSE_RESOURCE_LOADING_IN_MSW
0d0512bd 229 refData->m_hCursor = (WXHCURSOR) ReadCursorFile(WXSTRINGCAST cursor_file, wxGetInstance(), &refData->m_width, &refData->m_height);
2f851133 230#endif
2bda0e17 231#endif
0d0512bd
VZ
232 }
233 else if (flags == wxBITMAP_TYPE_ICO)
234 {
47d67540 235#if wxUSE_RESOURCE_LOADING_IN_MSW
0d0512bd 236 refData->m_hCursor = (WXHCURSOR) IconToCursor(WXSTRINGCAST cursor_file, wxGetInstance(), hotSpotX, hotSpotY, &refData->m_width, &refData->m_height);
2bda0e17 237#endif
0d0512bd
VZ
238 }
239 else if (flags == wxBITMAP_TYPE_BMP)
240 {
47d67540 241#if wxUSE_RESOURCE_LOADING_IN_MSW
0d0512bd
VZ
242 HBITMAP hBitmap = 0;
243 HPALETTE hPalette = 0;
244 bool success = wxReadDIB(WXSTRINGCAST cursor_file, &hBitmap, &hPalette) != 0;
245 if (!success)
246 return;
247 if (hPalette)
248 DeleteObject(hPalette);
249 POINT pnt;
250 pnt.x = hotSpotX;
251 pnt.y = hotSpotY;
252 refData->m_hCursor = (WXHCURSOR) MakeCursorFromBitmap(wxGetInstance(), hBitmap, &pnt);
0d0512bd 253 DeleteObject(hBitmap);
2bda0e17 254#endif
0d0512bd
VZ
255 }
256
257#if WXWIN_COMPATIBILITY_2
258 refData->SetOk();
259#endif // WXWIN_COMPATIBILITY_2
04ef50df
JS
260
261#endif
2bda0e17
KB
262}
263
264// Cursors by stock number
debe6624 265wxCursor::wxCursor(int cursor_type)
2bda0e17 266{
04ef50df
JS
267#ifdef __WXMICROWIN__
268 m_refData = NULL;
269#else
0d0512bd
VZ
270 wxCursorRefData *refData = new wxCursorRefData;
271 m_refData = refData;
2bda0e17
KB
272
273 switch (cursor_type)
274 {
83f96286 275 case wxCURSOR_ARROWWAIT:
788722ac 276#ifndef __WIN16__
83f96286
RD
277 refData->m_hCursor = (WXHCURSOR) LoadCursor((HINSTANCE) NULL, IDC_APPSTARTING);
278 break;
788722ac 279#endif
2bda0e17 280 case wxCURSOR_WAIT:
0d0512bd 281 refData->m_hCursor = (WXHCURSOR) LoadCursor((HINSTANCE) NULL, IDC_WAIT);
2bda0e17
KB
282 break;
283 case wxCURSOR_IBEAM:
0d0512bd 284 refData->m_hCursor = (WXHCURSOR) LoadCursor((HINSTANCE) NULL, IDC_IBEAM);
2bda0e17
KB
285 break;
286 case wxCURSOR_CROSS:
0d0512bd 287 refData->m_hCursor = (WXHCURSOR) LoadCursor((HINSTANCE) NULL, IDC_CROSS);
2bda0e17
KB
288 break;
289 case wxCURSOR_SIZENWSE:
0d0512bd 290 refData->m_hCursor = (WXHCURSOR) LoadCursor((HINSTANCE) NULL, IDC_SIZENWSE);
2bda0e17
KB
291 break;
292 case wxCURSOR_SIZENESW:
0d0512bd 293 refData->m_hCursor = (WXHCURSOR) LoadCursor((HINSTANCE) NULL, IDC_SIZENESW);
2bda0e17
KB
294 break;
295 case wxCURSOR_SIZEWE:
0d0512bd 296 refData->m_hCursor = (WXHCURSOR) LoadCursor((HINSTANCE) NULL, IDC_SIZEWE);
2bda0e17
KB
297 break;
298 case wxCURSOR_SIZENS:
0d0512bd 299 refData->m_hCursor = (WXHCURSOR) LoadCursor((HINSTANCE) NULL, IDC_SIZENS);
2bda0e17
KB
300 break;
301 case wxCURSOR_CHAR:
302 {
0d0512bd 303 refData->m_hCursor = (WXHCURSOR) LoadCursor((HINSTANCE) NULL, IDC_ARROW);
2bda0e17
KB
304 break;
305 }
306 case wxCURSOR_HAND:
307 {
0d0512bd 308 refData->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), wxT("wxCURSOR_HAND"));
2bda0e17
KB
309 break;
310 }
311 case wxCURSOR_BULLSEYE:
312 {
0d0512bd 313 refData->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), wxT("wxCURSOR_BULLSEYE"));
2bda0e17
KB
314 break;
315 }
316 case wxCURSOR_PENCIL:
317 {
0d0512bd 318 refData->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), wxT("wxCURSOR_PENCIL"));
2bda0e17
KB
319 break;
320 }
321 case wxCURSOR_MAGNIFIER:
322 {
0d0512bd 323 refData->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), wxT("wxCURSOR_MAGNIFIER"));
2bda0e17
KB
324 break;
325 }
326 case wxCURSOR_NO_ENTRY:
327 {
0d0512bd 328 refData->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), wxT("wxCURSOR_NO_ENTRY"));
2bda0e17
KB
329 break;
330 }
331 case wxCURSOR_LEFT_BUTTON:
332 {
0d0512bd 333 refData->m_hCursor = (WXHCURSOR) LoadCursor((HINSTANCE) NULL, IDC_ARROW);
2bda0e17
KB
334 break;
335 }
336 case wxCURSOR_RIGHT_BUTTON:
337 {
0d0512bd 338 refData->m_hCursor = (WXHCURSOR) LoadCursor((HINSTANCE) NULL, IDC_ARROW);
2bda0e17
KB
339 break;
340 }
341 case wxCURSOR_MIDDLE_BUTTON:
342 {
0d0512bd 343 refData->m_hCursor = (WXHCURSOR) LoadCursor((HINSTANCE) NULL, IDC_ARROW);
2bda0e17
KB
344 break;
345 }
346 case wxCURSOR_SIZING:
347 {
0d0512bd 348 refData->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), wxT("wxCURSOR_SIZING"));
2bda0e17
KB
349 break;
350 }
351 case wxCURSOR_WATCH:
352 {
0d0512bd 353 refData->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), wxT("wxCURSOR_WATCH"));
2bda0e17
KB
354 break;
355 }
356 case wxCURSOR_SPRAYCAN:
357 {
0d0512bd 358 refData->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), wxT("wxCURSOR_ROLLER"));
2bda0e17
KB
359 break;
360 }
361 case wxCURSOR_PAINT_BRUSH:
362 {
0d0512bd 363 refData->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), wxT("wxCURSOR_PBRUSH"));
2bda0e17
KB
364 break;
365 }
366 case wxCURSOR_POINT_LEFT:
367 {
0d0512bd 368 refData->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), wxT("wxCURSOR_PLEFT"));
2bda0e17
KB
369 break;
370 }
371 case wxCURSOR_POINT_RIGHT:
372 {
0d0512bd 373 refData->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), wxT("wxCURSOR_PRIGHT"));
2bda0e17
KB
374 break;
375 }
376 case wxCURSOR_QUESTION_ARROW:
377 {
b96340e6 378// refData->m_hCursor = (WXHCURSOR) LoadImage(wxGetInstance(), wxT("wxCURSOR_QARROW"), IMAGE_CURSOR, 16, 16, LR_MONOCHROME);
285edb24
JS
379// refData->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), wxT("wxCURSOR_QARROW"));
380 refData->m_hCursor = (WXHCURSOR) LoadCursor((HINSTANCE) NULL, IDC_HELP);
2bda0e17
KB
381 break;
382 }
383 case wxCURSOR_BLANK:
384 {
0d0512bd 385 refData->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), wxT("wxCURSOR_BLANK"));
2bda0e17
KB
386 break;
387 }
15dadf31
RD
388 case wxCURSOR_RIGHT_ARROW:
389 {
390 refData->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), wxT("wxCURSOR_RIGHT_ARROW"));
391 break;
392 }
2bda0e17
KB
393 default:
394 case wxCURSOR_ARROW:
0d0512bd 395 refData->m_hCursor = (WXHCURSOR) LoadCursor((HINSTANCE) NULL, IDC_ARROW);
2bda0e17
KB
396 break;
397 }
771a855f
VZ
398
399 // no need to destroy the stock cursors
d2913c40
JS
400 // TODO: check this
401 //m_refData->m_destroyCursor = FALSE;
402#endif
2bda0e17
KB
403}
404
0d0512bd 405wxCursor::~wxCursor()
2bda0e17 406{
2bda0e17
KB
407}
408
0d0512bd 409// ----------------------------------------------------------------------------
2bda0e17 410// Global cursor setting
0d0512bd
VZ
411// ----------------------------------------------------------------------------
412
bfbd6dc1 413const wxCursor *wxGetGlobalCursor()
2bda0e17 414{
bfbd6dc1
VZ
415 return gs_globalCursor;
416}
2bda0e17 417
bfbd6dc1
VZ
418void wxSetCursor(const wxCursor& cursor)
419{
420 if ( cursor.Ok() )
6bf57206 421 {
04ef50df 422#ifndef __WXMICROWIN__
bfbd6dc1 423 ::SetCursor(GetHcursorOf(cursor));
04ef50df 424#endif
6bf57206 425
bfbd6dc1
VZ
426 if ( gs_globalCursor )
427 *gs_globalCursor = cursor;
6bf57206 428 }
2bda0e17
KB
429}
430
431