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