]> git.saurik.com Git - wxWidgets.git/blob - src/msw/curico.cpp
workarounded false memory leak report
[wxWidgets.git] / src / msw / curico.cpp
1 //* Written by Microsoft Product Support Services, Windows Developer Support. *
2 //*****************************************************************************
3 // (C) Copyright Microsoft Corp. 1993. All rights reserved.
4 // You have a royalty-free right to use, modify, reproduce and
5 // distribute the Sample Files (and/or any modified version) in
6 // any way you find useful, provided that you agree that
7 // Microsoft has no warranty obligations or liability for any
8 // Sample Application Files which are modified.
9
10 // Modified by Petr Smilauer, March 1994 for wxWin library purposes!
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #include <io.h>
20 #include <windows.h>
21
22 #if defined(__MWERKS__)
23 #include <wingdi.h>
24 #include <winuser.h>
25 #endif
26
27 #ifdef __GNUWIN32_OLD__
28 #include "wx/msw/gnuwin32/extra.h"
29 #endif
30
31 #include "wx/wxchar.h"
32 #include "wx/msw/curicop.h"
33 #include "wx/msw/curico.h"
34 #include "wx/string.h"
35
36 //*****************************************************************************
37 //* Function : ReadIconFile() *
38 //* Purpose : Reads an icon resource file and creates an icon based on that *
39 //* information. *
40 //* Parameters : char *szFileName - The icon resource file. *
41 //* Returns : A handle to an icon. The handle will be NULL if an icon cannot *
42 //* be created for any reason. *
43 //*****************************************************************************
44
45 HICON ReadIconFile( wxChar *szFileName, HINSTANCE hInst, int *W, int *H)
46 { HICON hIcon;
47 HANDLE hDIB;
48
49 if( (hDIB = ReadIcon(szFileName, W, H)) == (HANDLE) NULL)
50 // read the icon DIB from file
51 return (HICON) NULL;
52 hIcon = MakeIcon( hDIB, hInst); // create an icon from DIB
53 GlobalFree( hDIB);
54 return hIcon;
55 }
56
57 //*****************************************************************************
58 //* Function : CursorToIcon() *
59 //* Purpose : Reads a cursor resource file and creates an icon based on that *
60 //* information. *
61 //* Parameters : char *szFileName - The cursor resource file. *
62 //* Returns : A handle to an icon. The handle will be NULL if an icon cannot *
63 //* be created for any reason. *
64 //* Comments : A cursor is monochrome. So, the resulting icon will also be *
65 //* monochrome. *
66 //*****************************************************************************
67
68 HICON CursorToIcon( wxChar *szFileName, HINSTANCE hInst, int *W, int *H)
69 { HANDLE hDIB; // Handle to DIB memory
70 HICON hIcon; // Handle to Icon
71
72 if( (hDIB = ReadCur( szFileName, NULL, W, H)) == (HANDLE) NULL)
73 // Read cursor DIB
74 return (HICON) NULL;
75 hIcon = MakeIcon( hDIB, hInst); // make icon from cursor DIB
76 GlobalFree( hDIB);
77 return hIcon;
78 }
79
80 //*****************************************************************************
81 //* Function : ReadIcon() *
82 //* Purpose : Reads an icon resource file and extracts the DIB information. *
83 //* Parameters : char *szFileName - The icon resource file. *
84 //* Returns : A handle to a DIB. The handle will be NULL if the resource file*
85 //* is corrupt or if memory cannot be allocated for the DIB info. *
86 //*****************************************************************************
87
88 HANDLE ReadIcon( wxChar *szFileName, int *W, int *H)
89 { ICONFILEHEADER iconFileHead; // ICON file header structure
90 ICONFILERES iconFileRes; // ICON file resource
91 WORD cbHead,
92 cbRes,
93 cbBits; // Used for reading in file
94 int hFile; // File handle
95 LPBITMAPINFO lpDIB; // Pointer to DIB memory
96 HANDLE hDIB;
97 int nWidth = GetSystemMetrics( SM_CXICON),
98 nHeight = GetSystemMetrics( SM_CYICON),
99 nDirEntries = 0;
100
101 // Open and read the .ICO file header and the first ICONFILERES
102 hFile = _lopen( wxConvertWX2MB(szFileName), OF_READ);
103 cbHead = _lread( hFile, (LPSTR)&iconFileHead, sizeof(ICONFILEHEADER));
104 cbRes = _lread( hFile, (LPSTR)&iconFileRes, sizeof(ICONFILERES));
105 ++nDirEntries;
106
107 if((cbHead != sizeof( ICONFILEHEADER)) || (cbRes != sizeof( ICONFILERES)))
108 return (HANDLE) NULL;
109 // Verify that it's an .ICON file
110 if( iconFileHead.wResourceType != 1)
111 return (HANDLE) NULL;
112
113 // inserted by P.S.
114 while( ((unsigned)nDirEntries < iconFileHead.wResourceCount) &&
115 ((iconFileRes.bWidth != nWidth) || (iconFileRes.bHeight != nHeight)))
116 {
117 cbRes = _lread( hFile, (LPSTR )&iconFileRes, sizeof( ICONFILERES));
118 if(cbRes != sizeof( ICONFILERES))
119 return (HANDLE) NULL;
120 else
121 ++nDirEntries;
122 }
123
124 if(W != 0)
125 *W = iconFileRes.bWidth;
126 if(H != 0)
127 *H = iconFileRes.bHeight;
128
129 // Allocate and lock memory to read in the DIB
130 hDIB = GlobalAlloc(GHND, iconFileRes.dwDIBSize);
131 if(hDIB == (HANDLE) NULL)
132 return (HANDLE) NULL;
133
134 #ifdef __WINDOWS_386__
135 lpDIB = (LPBITMAPINFO)MK_FP32(GlobalLock(hDIB));
136 #else
137 lpDIB = (LPBITMAPINFO)GlobalLock(hDIB);
138 #endif
139
140 // Now read the DIB portion of the file, which follows the
141 // end of icon resource table
142 _llseek( hFile, iconFileRes.dwDIBOffset, 0);
143 cbBits = _lread( hFile, (LPSTR )lpDIB, (WORD )iconFileRes.dwDIBSize);
144
145 // Done reading file
146 _lclose(hFile);
147
148 GlobalUnlock( hDIB);
149
150 if( (DWORD )cbBits != iconFileRes.dwDIBSize)
151 {
152 GlobalFree( hDIB);
153 return (HANDLE) NULL;
154 }
155 return hDIB;
156 }
157
158 //*****************************************************************************
159 //* Function : MakeIcon() *
160 //* Purpose : Creates an icon based on the DIB info. returned by ReadIcon. *
161 //* Parameters : HANDLE hDIB - A handle to the icon's DIB information. *
162 //* Returns : A handle to an Icon. NULL is returned if an icon cannot be *
163 //* successfully created. *
164 //* Comments : The steps involved in making an icon from a DIB are very *
165 //* similar to those involved in making a cursor from a DIB. *
166 //* Steps : 1) Obtain a pointer to the Icon's DIB bits. *
167 //* 2) Divide the DIB'd height with 2 to account for the fact that the*
168 //* DIB stores both the XOR and the AND masks, one after the other.*
169 //* 3) Determine the offset to the XOR bits. *
170 //* 4) Determine the offset to the AND bits. *
171 //* 5) Create a device dependent bitmap with the XOR bits. *
172 //* 6) Obtain the device dependent XOR bitmask and save in memory. *
173 //* The AND bitmask is monochrome. Monochrome bits are identical *
174 //* in both the device dependent bitmaps and device independent *
175 //* bitmaps. So, no need to convert the AND bitmask. *
176 //* 7) Since a DIB is stored upside down, flip the monochrome AND bits*
177 //* by scanlines. *
178 //* 8) Use the XOR and AND bits and create an icon with CreateIcon. *
179 //*****************************************************************************
180
181 HICON MakeIcon( HANDLE hDIB, HINSTANCE hInst)
182 { LPSTR lpXORbits,
183 lpANDbits; // Pointer to XOR and AND bits
184 HBITMAP hbmXor; // handle to XOR bitmap
185 BITMAP bmpXor; // Used to manipulate XOR bitmap
186 DWORD dwBmpSize; // Size of XOR bitmap
187 HANDLE hXorDDB;
188 LPSTR lpXorDDB;
189 LONG szFlip[32];
190 int j,
191 k;
192 HDC hDC;
193 HICON hIcon;
194 LPBITMAPINFO lpDIB;
195
196 // 1) Obtain a pointer to the Icon's DIB bits.
197 #ifdef __WINDOWS_386__
198 lpDIB = (LPBITMAPINFO )MK_FP32(GlobalLock( hDIB));
199 #else
200 lpDIB = (LPBITMAPINFO )GlobalLock( hDIB);
201 #endif
202
203 // 2) Divide the DIB'd height with 2 to account for the fact that the
204 // DIB stores both the XOR and the AND masks, one after the other.
205 lpDIB->bmiHeader.biHeight /= 2;
206
207 // 3) Determine the offset to the XOR bits.
208 // To obtain this value, we have to skip the header, and color table
209 lpXORbits = (LPSTR )lpDIB + (int )lpDIB->bmiHeader.biSize +
210 (DIBNumColors( (LPSTR )lpDIB) * sizeof( RGBQUAD));
211
212 // 4) Determine the offset to the AND bits.
213 // To obtain this value, skip the XOR bits
214 lpANDbits = lpXORbits + (int )(lpDIB->bmiHeader.biHeight *
215 (WIDTHBYTES ( lpDIB->bmiHeader.biWidth *
216 lpDIB->bmiHeader.biBitCount)));
217
218 // Get a hDC so we can create a bitmap compatible with it
219 hDC = CreateDC( wxT("DISPLAY"), NULL, NULL, NULL);
220
221 // 5) Create a device dependent bitmap with the XOR bits.
222 hbmXor = CreateDIBitmap( hDC, (LPBITMAPINFOHEADER)&(lpDIB->bmiHeader),
223 CBM_INIT, lpXORbits, lpDIB, DIB_RGB_COLORS);
224
225 GetObject( hbmXor, sizeof(BITMAP), (LPSTR)&bmpXor);
226
227 dwBmpSize = (DWORD )(bmpXor.bmWidthBytes * bmpXor.bmHeight * bmpXor.bmPlanes);
228 hXorDDB = GlobalAlloc( GHND, dwBmpSize);
229 if(hXorDDB == (HANDLE) NULL)
230 {
231 // clean up before quitting
232 DeleteObject( hbmXor);
233 DeleteDC( hDC);
234 GlobalUnlock( hDIB);
235 return (HICON) NULL;
236 }
237
238 #ifdef __WINDOWS_386__
239 lpXorDDB = (LPSTR)MK_FP32(GlobalLock( hXorDDB));
240 #else
241 lpXorDDB = (LPSTR)GlobalLock( hXorDDB);
242 #endif
243
244 // 6) Obtain the device dependent XOR bitmask and save in memory.
245 // The AND bitmask is monochrome. Monochrome bits are identical
246 // in both the device dependent bitmaps and device independent
247 // bitmaps. So, no need to convert the AND bitmask.
248 GetBitmapBits( hbmXor, dwBmpSize, lpXorDDB);
249
250 // 7) Since a DIB is stored upside down, flip the monochrome AND bits by scanlines.
251 k = (int )lpDIB->bmiHeader.biHeight;
252 for( j = 0 ; j < k ; j++, lpANDbits += sizeof(DWORD))
253 szFlip[(k - 1) - j] = *(DWORD FAR *)lpANDbits;
254
255 // 8) Use the XOR and AND bits and create an icon with CreateIcon.
256 hIcon = CreateIcon( hInst, bmpXor.bmWidth, bmpXor.bmHeight, bmpXor.bmPlanes,
257 bmpXor.bmBitsPixel, (const BYTE *)szFlip, (const BYTE *)lpXorDDB);
258
259 // Clean up before exiting.
260 DeleteObject( hbmXor);
261 GlobalUnlock( hXorDDB);
262 GlobalFree( hXorDDB);
263 DeleteDC( hDC);
264 GlobalUnlock( hDIB);
265
266 return hIcon;
267 }
268
269 // **************************************************************************
270
271 //*****************************************************************************
272 //* Function : ReadCursorFile() *
273 //* Purpose : Reads a cursor resource file and creates a cursor based on that*
274 //* information. *
275 //* Parameters : char *szFileName - The cursor resource file. *
276 //* Returns : A handle to a cursor. The handle will be NULL if a cursor can't*
277 //* be created for any reason. *
278 //*****************************************************************************
279
280 HCURSOR ReadCursorFile( wxChar *szFileName, HINSTANCE hInst, int *W, int *H,
281 int *XHot, int *YHot)
282 { HANDLE hDIB; // Handle to DIB memory
283 HCURSOR hCursor;
284 POINT ptHotSpot;
285
286 // read cur DIB from file
287 if( (hDIB = ReadCur( szFileName, (LPPOINT )&ptHotSpot, W, H)) == (HANDLE) NULL)
288 return (HCURSOR) NULL;
289 hCursor = MakeCursor( hDIB, (LPPOINT )&ptHotSpot, hInst);//create cur from DIB
290 if(XHot != 0)
291 *XHot = ptHotSpot.x;
292 if(YHot != 0)
293 *YHot = ptHotSpot.y;
294 GlobalFree( hDIB);
295 return ( hCursor);
296 }
297
298 //*****************************************************************************
299 //* Function : IconToCursor() *
300 //* Purpose : Reads an icon resource file and creates a cursor based on that *
301 //* information. *
302 //* Parameters : char *szFileName - The icon resource file. *
303 //* Returns : A handle to a cursor. The handle will be NULL if a cursor can't*
304 //* be created for any reason. *
305 //* Comments : An icon may be in color. So, the DIB has to be forced to be *
306 //* monochrome. *
307 //*****************************************************************************
308
309 HCURSOR IconToCursor( wxChar *szFileName, HINSTANCE hInst, int XHot, int YHot,
310 int *W, int *H)
311 { HCURSOR hCursor;
312 HANDLE hDIB;
313 POINT ptHotSpot;
314
315 if( (hDIB = ReadIcon( szFileName, W, H)) == (HANDLE) NULL)
316 //read icon file to get icon DIB
317 return (HCURSOR) NULL;
318 // Set the hot spot of the cursor
319 ptHotSpot.x = XHot;
320 ptHotSpot.y = YHot;
321 hCursor = MakeCursor( hDIB, (LPPOINT )&ptHotSpot, hInst);
322 //create cursor from DIB
323 GlobalFree( hDIB);
324 return hCursor;
325 }
326
327 //*****************************************************************************
328 //* Function : ReadCur() *
329 //* Purpose : Reads a cursor resource file and extracts the DIB information. *
330 //* Parameters : LPSTR szFileName - The cursor resource file. *
331 //* Returns : A handle to a DIB. The handle will be NULL if the resource file*
332 //* is corrupt or if memory cannot be allocated for the DIB info. *
333 //*****************************************************************************
334
335 HANDLE ReadCur( wxChar *szFileName, LPPOINT lpptHotSpot, int *W, int *H)
336 { CURFILEHEADER curFileHead; // CURSOR file header structure
337 CURFILERES curFileRes; // CURSOR file resource
338 WORD cbHead,
339 cbRes,
340 cbBits; // Used for reading in file
341 LPBITMAPINFO lpDIB; // Pointer to DIB memory
342 int hFile; // Handle to File
343 HANDLE hDIB;
344 int nWidth = GetSystemMetrics( SM_CXCURSOR),
345 nHeight = GetSystemMetrics( SM_CYCURSOR),
346 nDirEntries = 0;
347
348 // Open and read the .ICO file header and the first ICONFILERES
349 hFile = _lopen( wxConvertWX2MB(szFileName), OF_READ);
350 cbHead = _lread( hFile, (LPSTR )&curFileHead, sizeof( CURFILEHEADER));
351 cbRes = _lread( hFile, (LPSTR )&curFileRes, sizeof( CURFILERES));
352 ++nDirEntries;
353
354 if((cbHead != sizeof( CURFILEHEADER)) || (cbRes != sizeof( CURFILERES)))
355 return (HANDLE) NULL;
356
357 // Verify that it's an .CUR file
358 if ((curFileRes.bReserved1 != 0) || (curFileHead.wResourceType != 2))
359 return (HANDLE) NULL;
360
361 // following added by P.S.
362 while( ((unsigned)nDirEntries < curFileHead.wResourceCount) &&
363 ((curFileRes.bWidth != nWidth) || (curFileRes.bHeight != nHeight)))
364 {
365 cbRes = _lread( hFile, (LPSTR )&curFileRes, sizeof( CURFILERES));
366 if(cbRes != sizeof( CURFILERES))
367 return (HANDLE) NULL;
368 else
369 ++nDirEntries;
370 }
371 if(W != 0)
372 *W = curFileRes.bWidth;
373 if(H != 0)
374 *H = curFileRes.bHeight;
375
376
377 // Allocate & lock memory to read in the DIB
378 hDIB = GlobalAlloc(GHND, curFileRes.dwDIBSize);
379 if(hDIB == (HANDLE) NULL)
380 return (HANDLE) NULL;
381
382 #ifdef __WINDOWS_386__
383 lpDIB = (LPBITMAPINFO )MK_FP32(GlobalLock(hDIB));
384 #else
385 lpDIB = (LPBITMAPINFO )GlobalLock(hDIB);
386 #endif
387
388 // Now read the DIB portion of the file, which follows the
389 // end of icon resource table
390 _llseek( hFile, curFileRes.dwDIBOffset, 0);
391 cbBits = _lread( hFile, (LPSTR )lpDIB, (WORD )curFileRes.dwDIBSize);
392
393 // Done reading file
394 _lclose(hFile);
395
396 if((DWORD)cbBits != curFileRes.dwDIBSize)
397 {
398 GlobalUnlock( hDIB);
399 GlobalFree( hDIB);
400 return (HANDLE) NULL;
401 }
402 if(lpptHotSpot != (LPPOINT) NULL) // If it is necessary to know the hot spot
403 {
404 lpptHotSpot->x = (int )curFileRes.wXHotspot;
405 lpptHotSpot->y = (int )curFileRes.wYHotspot;
406 }
407 GlobalUnlock( hDIB);
408 return( hDIB);
409 }
410
411 //*****************************************************************************
412 //* Function : ColorDDBToMonoDDB() *
413 //* Purpose : Converts a color bitmap to a monochrome bitmap. *
414 //* Parameters : HBITMAP hbm - The color bitmap. *
415 //* Returns : A handle to a monochrome bitmap. *
416 //*****************************************************************************
417 HBITMAP ColorDDBToMonoDDB ( HBITMAP hbm)
418 { BITMAP bm;
419 BITMAPINFOHEADER bi;
420 LPBITMAPINFOHEADER lpbi;
421 DWORD dwLen;
422 HANDLE hdib;
423 HANDLE h;
424 HDC hdc;
425 HBITMAP hbmMono;
426
427 GetObject( hbm, sizeof( bm), (LPSTR )&bm);
428
429 bi.biSize = sizeof( BITMAPINFOHEADER); // size of this structure
430 bi.biWidth = bm.bmWidth; // bitmap width in pixels
431 bi.biHeight = bm.bmHeight; // bitmap height in pixels
432 bi.biPlanes = 1; // # of planes always 1 for DIBs
433 bi.biBitCount = bm.bmPlanes * bm.bmBitsPixel; // color bits per pixel
434 bi.biCompression = BI_RGB; // no compression
435 bi.biSizeImage = 0; // 0 means default size
436 bi.biXPelsPerMeter = 0; // not used
437 bi.biYPelsPerMeter = 0; // not used
438 bi.biClrUsed = 0; // 0 means default colors
439 bi.biClrImportant = 0; // 0 means defaults
440
441 dwLen = bi.biSize + PaletteSize((LPSTR)&bi);
442
443 hdc = GetDC( (HWND) NULL);
444
445 hdib = GlobalAlloc( GHND, dwLen);
446 if (hdib == (HANDLE) NULL)
447 {
448 ReleaseDC( (HWND) NULL, hdc);
449 return (HBITMAP) NULL;
450 }
451
452 #ifdef __WINDOWS_386__
453 lpbi = (LPBITMAPINFOHEADER )MK_FP32(GlobalLock( hdib));
454 #else
455 lpbi = (LPBITMAPINFOHEADER )GlobalLock( hdib);
456 #endif
457
458 *lpbi = bi;
459
460 // Call GetDIBits with a NULL lpBits parameter; it will calculate
461 // the biSizeImage field.
462 GetDIBits( hdc, hbm, 0, (WORD)bi.biHeight,
463 NULL, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
464
465 bi = *lpbi;
466 GlobalUnlock( hdib);
467
468 // If the driver did not fill in the biSizeImage field, make one up.
469 if(bi.biSizeImage == 0)
470 bi.biSizeImage = WIDTHBYTES( (DWORD )bm.bmWidth * bi.biBitCount) * bm.bmHeight;
471
472 // Reallocate the buffer big enough to hold all the bits.
473 dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + bi.biSizeImage;
474 if( (h = GlobalReAlloc( hdib, dwLen, 0)) != 0)
475 hdib = h;
476 else
477 {
478 GlobalFree( hdib);
479 ReleaseDC( (HWND) NULL, hdc);
480 return (HBITMAP) NULL;
481 }
482
483 // Call GetDIBits with a NON-NULL lpBits parameter, to actually
484 // get the bits this time.
485
486 #ifdef __WINDOWS_386__
487 lpbi = (LPBITMAPINFOHEADER )MK_FP32(GlobalLock( hdib));
488 #else
489 lpbi = (LPBITMAPINFOHEADER )GlobalLock( hdib);
490 #endif
491
492 if( GetDIBits( hdc, hbm, 0, (WORD)bi.biHeight,
493 (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi),
494 (LPBITMAPINFO)lpbi, DIB_RGB_COLORS) == 0)
495 {
496 GlobalUnlock( hdib);
497 hdib = (HANDLE) NULL;
498 ReleaseDC( (HWND) NULL, hdc);
499 return (HBITMAP) NULL;
500 }
501
502 // Finally, create a monochrome DDB, and put the DIB into
503 // it. SetDIBits does smart color conversion.
504 hbmMono = CreateBitmap((WORD)lpbi->biWidth, (WORD)lpbi->biHeight, 1, 1, NULL);
505 SetDIBits( hdc, hbmMono, (WORD)0, (WORD)lpbi->biHeight,
506 (LPSTR)lpbi + (int )lpbi->biSize + PaletteSize((LPSTR)lpbi),
507 (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
508
509 bi = *lpbi;
510 GlobalUnlock( hdib);
511 GlobalFree( hdib);
512
513 ReleaseDC((HWND) NULL, hdc);
514 return hbmMono;
515 }
516
517 //*****************************************************************************
518 //* Function : MakeCursor() *
519 //* Purpose : Creates a cursor based on the DIB info. returned by ReadCursor.*
520 //* Parameters : HANDLE hDIB - A handle to the cursor's DIB information. *
521 //* LPPOINT lppt - A pointer to a point struct. indicating the *
522 //* location of the Cursor's hot spot. *
523 //* Returns : A handle to a cursor. NULL is returned if a cursor cannot be *
524 //* successfully created. *
525 //* Comments : The steps involved in making a cursor from a DIB are very *
526 //* similar to those involved in making an icon from a DIB. *
527 //* Steps : 1) Obtain a pointer to the Cursor's DIB bits. *
528 //* 2) Divide the DIB's height with 2 to account for the fact that the*
529 //* DIB stores both the XOR and the AND masks, one after the other.*
530 //* 3) Determine the offset to the XOR bits. *
531 //* 4) Determine the offset to the AND bits. *
532 //* 5) Create a device dependent bitmap with the XOR bits. *
533 //* 6) Obtain the device dependent XOR bitmask and save in memory. *
534 //* The AND bitmask is monochrome. Monochrome bits are identical *
535 //* in both the device dependent bitmaps and device independent *
536 //* bitmaps. So, no need to convert the AND bitmask. *
537 //* 7) Since a DIB is stored upside down, flip the monochrome AND bits*
538 //* by scanlines. *
539 //* 8) Use the XOR and AND bits and create a cursor with CreateCursor.*
540 //*****************************************************************************
541
542 HCURSOR MakeCursor( HANDLE hDIB, LPPOINT lpptHotSpot, HINSTANCE hInst)
543 { LPSTR lpXORbits,
544 lpANDbits; // Pointer to XOR and AND bits
545 HBITMAP hbmXor; // handle to XOR bitmap
546 BITMAP bmpXor; // Used to manipulate XOR bitmap
547 DWORD dwBmpSize; // Size of XOR bitmap
548 HCURSOR hCursor;
549 HANDLE hXorDDB;
550 LPSTR lpXorDDB;
551 LONG szFlip[32];
552 int j,
553 k;
554 HDC hDC;
555 LPBITMAPINFO lpDIB;
556
557 // 1) Obtain a pointer to the Cursor's DIB bits.
558 #ifdef __WINDOWS_386__
559 lpDIB = (LPBITMAPINFO )MK_FP32(GlobalLock( hDIB));
560 #else
561 lpDIB = (LPBITMAPINFO )GlobalLock( hDIB);
562 #endif
563
564 // 2) Divide the DIB's height with 2 to account for the fact that the
565 // DIB stores both the XOR and the AND masks, one after the other.
566 lpDIB->bmiHeader.biHeight /= 2;
567
568 // 3) Determine the offset to the XOR bits.
569 // To obtain this value, we have to skip the header, and color table
570 lpXORbits = (LPSTR )lpDIB + (int )lpDIB->bmiHeader.biSize +
571 (DIBNumColors((LPSTR)lpDIB) * sizeof(RGBQUAD));
572
573 // 4) Determine the offset to the AND bits
574 // To obtain this value, skip the XOR bits
575 lpANDbits = lpXORbits + (int )( lpDIB->bmiHeader.biHeight *
576 (WIDTHBYTES( lpDIB->bmiHeader.biWidth *
577 lpDIB->bmiHeader.biBitCount)));
578
579 // Get a hDC so we can create a bitmap compatible with it
580 hDC = CreateDC( wxT("DISPLAY"), NULL, NULL, NULL);
581
582 // 5) Create a device dependent bitmap with the XOR bits.
583 hbmXor = CreateBitmap( (int )lpDIB->bmiHeader.biWidth,
584 (int )lpDIB->bmiHeader.biHeight, 1, 1, NULL);
585 SetDIBits( hDC, hbmXor, 0, (WORD)lpDIB->bmiHeader.biHeight, lpXORbits,
586 lpDIB, DIB_RGB_COLORS);
587 GetObject( hbmXor, sizeof( BITMAP), (LPSTR )&bmpXor);
588
589 dwBmpSize = (DWORD )(bmpXor.bmWidthBytes * bmpXor.bmHeight * bmpXor.bmPlanes);
590 hXorDDB = GlobalAlloc( GHND, dwBmpSize);
591 if(hXorDDB == (HANDLE) NULL)
592 { // clean up before quitting
593 DeleteObject( hbmXor);
594 DeleteDC( hDC);
595 GlobalUnlock( hDIB);
596 return (HCURSOR) NULL;
597 }
598 #ifdef __WINDOWS_386__
599 lpXorDDB = (LPSTR)MK_FP32(GlobalLock( hXorDDB));
600 #else
601 lpXorDDB = (LPSTR)GlobalLock( hXorDDB);
602 #endif
603
604 // 6) Obtain the device dependent XOR bitmask and save in memory.
605 // The AND bitmask is monochrome. Monochrome bits are identical
606 // in both the device dependent bitmaps and device independent
607 // bitmaps. So, no need to convert the AND bitmask.
608 GetBitmapBits( hbmXor, dwBmpSize, lpXorDDB);
609
610 // 7) Since a DIB is stored upside down, flip the monochrome AND bits by scanlines.
611 k = (int)lpDIB->bmiHeader.biHeight;
612 for( j = 0 ; j < k; j++, lpANDbits += sizeof( DWORD))
613 szFlip[(k - 1) - j] = *(DWORD FAR *)lpANDbits;
614
615 // 8) Use the XOR and AND bits and create a cursor with CreateCursor.
616 hCursor = CreateCursor( hInst, lpptHotSpot->x, lpptHotSpot->y,
617 bmpXor.bmWidth, bmpXor.bmHeight, (LPSTR)szFlip, lpXorDDB);
618
619 // Clean up before exiting.
620 DeleteObject( hbmXor);
621 GlobalUnlock( hXorDDB);
622 GlobalFree( hXorDDB);
623 DeleteDC( hDC);
624 GlobalUnlock( hDIB);
625
626 return hCursor;
627 }
628
629 //*****************************************************************************
630 //* Function : PaletteSize() *
631 //* Purpose : Calculates the palette size in bytes. If the info. block is of *
632 //* the BITMAPCOREHEADER type, the number of colors is multiplied *
633 //* by sizeof(RGBTRIPLE) to give the palette size, otherwise the *
634 //* number of colors is multiplied by sizeof(RGBQUAD). *
635 //* Parameters : LPSTR pv - pointer to the BITMAPINFOHEADER *
636 //* Returns : The size of the palette. *
637 //*****************************************************************************
638
639 WORD PaletteSize( LPSTR pv)
640 { LPBITMAPINFOHEADER lpbi;
641 WORD NumColors;
642
643 lpbi = (LPBITMAPINFOHEADER )pv;
644 NumColors = DIBNumColors((LPSTR )lpbi);
645
646 if(lpbi->biSize == sizeof( BITMAPCOREHEADER)) // OS/2 style DIBs
647 return NumColors * sizeof( RGBTRIPLE);
648 else
649 return NumColors * sizeof( RGBQUAD);
650 }
651
652 //*****************************************************************************
653 //* Function : DIBNumColors() *
654 //* Purpose : This function calculates the number of colors in the DIB's *
655 //* color table by finding the bits per pixel for the DIB (whether *
656 //* Win3.0 or OS/2-style DIB). If bits per pixel is 1: colors=2, *
657 //* if 4: colors=16, if 8: colors=256, if 24, no colors in color *
658 //* table. *
659 //* Parameters : LPSTR lpbi - pointer to packed-DIB memory block. *
660 //* Returns : The number of colors in the color table. *
661 //*****************************************************************************
662
663 WORD DIBNumColors ( LPSTR pv)
664 { int bits;
665 BITMAPINFOHEADER *lpbi;
666 BITMAPCOREHEADER *lpbc;
667
668 lpbi = ((BITMAPINFOHEADER* )pv); // assume win 3.0 style DIBs
669 lpbc = ((BITMAPCOREHEADER* )pv); // assume OS/2 style DIBs
670
671 // With the BITMAPINFO format headers, the size of the palette
672 // is in biClrUsed, whereas in the BITMAPCORE - style headers, it
673 // is dependent on the bits per pixel ( = 2 raised to the power of
674 // bits/pixel).
675
676 if(lpbi->biSize != sizeof( BITMAPCOREHEADER))
677 {
678 if(lpbi->biClrUsed != 0)
679 return (WORD)lpbi->biClrUsed;
680 bits = lpbi->biBitCount;
681 }
682 else
683 bits = lpbc->bcBitCount;
684
685 switch( bits)
686 {
687 case 1:
688 return 2;
689 case 4:
690 return 16;
691 case 8:
692 return 256;
693 default:
694 // A 24 bitcount DIB has no color table
695 return 0;
696 }
697 }
698
699 #if 0
700 // ******************************************************************
701 BOOL fGetXPixmap( BOOL fIsIcon, wxChar *szFileName, HINSTANCE hInst,
702 char cData[], int &width, int &height)
703 { HDC hdc,
704 hdcMemory;
705 HBITMAP hbmp,
706 holdbmp;
707 int i,
708 j,
709 w,
710 h;
711 BYTE *s,
712 cByte,
713 cMask;
714 COLORREF rgb;
715 HCURSOR hIconOrCursor = fIsIcon ?
716 IconToCursor( szFileName, hInst, 0, 0, &w, &h)
717 : ReadCursorFile( szFileName, hInst, &w, &h, 0, 0);
718 int sum;
719
720 if(hIconOrCursor == 0)
721 return FALSE;
722
723 hdc = GetDC( GetDesktopWindow());
724 hdcMemory = CreateCompatibleDC( hdc);
725 hbmp = CreateCompatibleBitmap( hdc, w, h);
726 holdbmp = SelectObject( hdcMemory, hbmp);
727 PatBlt( hdcMemory, 0, 0, w, h, BLACKNESS); // or use WHITENESS??
728 DrawIcon( hdcMemory, 0, 0, hIconOrCursor); //using HCURSOR with DrawIcon is OK
729
730 // the data retrieval follows:
731 width = w;
732 height = h;
733 for( j = 0, s = (BYTE *)cData ; j < h ; ++j)
734 for( i = 0 ; i < w ; ++i, cMask >>= 1)
735 {
736 if( (i % 8) == 0)
737 {
738 cByte = 0;
739 cMask = 0x80;
740 }
741 rgb = GetPixel( hdcMemory, i, j);
742 sum = (int )(rgb & 0xFFL);
743 sum += (int )((rgb & 0xFF00L) >> 8);
744 sum += (int )((rgb & 0xFF0000L) >> 16);
745 if(sum > 381)
746 cByte = cByte | cMask;
747 if( (i % 8) == 7)
748 {
749 *s = cByte;
750 ++s;
751 }
752 }
753 SelectObject( hdcMemory, holdbmp);
754 DeleteDC( hdcMemory);
755 ReleaseDC( GetDesktopWindow(), hdc);
756 DestroyCursor( hIconOrCursor);
757 DeleteObject( hbmp);
758 return TRUE;
759 }
760 #endif
761
762 // Added from scavenged internet code, JACS 23/6/95
763 HCURSOR MakeCursorFromBitmap(HINSTANCE hInst, HBITMAP hBitmap, POINT *pPoint)
764 {
765 HDC hDCColor, hDCMono;
766 HDC hDC;
767 HBITMAP hBmpOld;
768 HBITMAP hAndBmp;
769 HBITMAP hXorBmp;
770 HCURSOR hNewCursor;
771 BITMAP bm;
772 DWORD dwBytes;
773 NPSTR andBits;
774 NPSTR xorBits;
775
776 hDC = GetDC((HWND) NULL);
777 hDCColor = CreateCompatibleDC(hDC);
778 hDCMono = CreateCompatibleDC(hDC);
779 hAndBmp = CreateCompatibleBitmap(hDCMono, 32, 32);
780 hXorBmp = CreateCompatibleBitmap(hDCMono, 32, 32);
781
782 hBmpOld = (HBITMAP) SelectObject(hDCColor, hBitmap);
783 SelectObject(hDCMono, hAndBmp);
784 SetBkColor(hDCColor, RGB(191, 191, 191));
785
786 BitBlt(hDCMono, 0, 0, 32, 32, hDCColor, 0, 0, SRCCOPY);
787
788 // Now we have the AND Mask
789
790 GetObject(hAndBmp, sizeof(BITMAP), (LPSTR) &bm);
791 dwBytes = (bm.bmWidthBytes * bm.bmHeight);
792 andBits = (NPSTR) LocalAlloc(LPTR, dwBytes);
793 GetBitmapBits(hAndBmp, dwBytes, andBits);
794
795 SelectObject(hDCMono, hXorBmp);
796 SetBkColor(hDCColor, RGB(0, 0, 0));
797
798 BitBlt(hDCMono, 0, 0, 32, 32, hDCColor, 0, 0, SRCCOPY);
799
800 // Now we have the XOR Mask
801
802 GetObject(hXorBmp, sizeof(BITMAP), (LPSTR) &bm);
803 dwBytes = (bm.bmWidthBytes * bm.bmHeight);
804 xorBits = (NPSTR) LocalAlloc(LPTR, dwBytes);
805 GetBitmapBits(hXorBmp, dwBytes, xorBits);
806
807 if (pPoint->x > 32)
808 pPoint->x = 32;
809 if (pPoint->y > 32)
810 pPoint->y = 32;
811
812 hNewCursor = CreateCursor(hInst,
813 pPoint->x, pPoint->y, 32, 32, andBits, xorBits);
814
815 SelectObject(hDCColor, hBmpOld);
816 SelectObject(hDCMono, hBmpOld);
817 DeleteDC(hDCColor);
818 DeleteDC(hDCMono);
819 DeleteObject(hAndBmp);
820 DeleteObject(hXorBmp);
821 ReleaseDC(NULL, hDC);
822 #ifndef __WIN32__
823 #ifdef STRICT
824 LocalUnlock(LocalHandle((void NEAR*) andBits));
825 LocalUnlock(LocalHandle((void NEAR*) xorBits));
826 LocalFree(LocalHandle((void NEAR*) andBits));
827 LocalFree(LocalHandle((void NEAR*) xorBits));
828 #else
829 LocalUnlock(LocalHandle((WORD) andBits));
830 LocalUnlock(LocalHandle((WORD) xorBits));
831 LocalFree(LocalHandle((WORD) andBits));
832 LocalFree(LocalHandle((WORD) xorBits));
833 #endif
834 #else
835 LocalUnlock(LocalHandle((LPCVOID) andBits));
836 LocalUnlock(LocalHandle((LPCVOID) xorBits));
837 LocalFree(LocalHandle((LPCVOID) andBits));
838 LocalFree(LocalHandle((LPCVOID) xorBits));
839 #endif
840 return hNewCursor;
841 }
842
843 /*
844 * This doesn't work: just gives us a grey square. Ideas, anyone?
845 */
846
847 HICON MakeIconFromBitmap(HINSTANCE hInst, HBITMAP hBitmap)
848 {
849 HDC hDCColor, hDCMono;
850 HDC hDC;
851 HBITMAP hBmpOld;
852 HBITMAP hAndBmp;
853 HBITMAP hXorBmp;
854 HICON hNewIcon;
855 BITMAP bm;
856 DWORD dwBytes;
857 NPSTR andBits;
858 NPSTR xorBits;
859
860 hDC = GetDC((HWND) NULL);
861 hDCColor = CreateCompatibleDC(hDC);
862 hDCMono = CreateCompatibleDC(hDC);
863 hAndBmp = CreateCompatibleBitmap(hDCMono, 32, 32);
864 hXorBmp = CreateCompatibleBitmap(hDCMono, 32, 32);
865
866 hBmpOld = (HBITMAP) SelectObject(hDCColor, hBitmap);
867 SelectObject(hDCMono, hAndBmp);
868 SetBkColor(hDCColor, RGB(191, 191, 191));
869
870 BitBlt(hDCMono, 0, 0, 32, 32, hDCColor, 0, 0, SRCCOPY);
871
872 // Now we have the AND Mask
873
874 GetObject(hAndBmp, sizeof(BITMAP), (LPSTR) &bm);
875 dwBytes = (bm.bmWidthBytes * bm.bmHeight);
876 andBits = (NPSTR) LocalAlloc(LPTR, dwBytes);
877 GetBitmapBits(hAndBmp, dwBytes, andBits);
878
879 SelectObject(hDCMono, hXorBmp);
880 SetBkColor(hDCColor, RGB(0, 0, 0));
881
882 BitBlt(hDCMono, 0, 0, 32, 32, hDCColor, 0, 0, SRCCOPY);
883
884 // Now we have the XOR Mask
885
886 GetObject(hXorBmp, sizeof(BITMAP), (LPSTR) &bm);
887 dwBytes = (bm.bmWidthBytes * bm.bmHeight);
888 xorBits = (NPSTR) LocalAlloc(LPTR, dwBytes);
889 GetBitmapBits(hXorBmp, dwBytes, xorBits);
890
891 hNewIcon = CreateIcon(hInst, 1, 4, 32, 32, (unsigned char *)andBits, (unsigned char *)xorBits);
892
893 SelectObject(hDCColor, hBmpOld);
894 SelectObject(hDCMono, hBmpOld);
895 DeleteDC(hDCColor);
896 DeleteDC(hDCMono);
897 DeleteObject(hAndBmp);
898 DeleteObject(hXorBmp);
899 ReleaseDC((HWND) NULL, hDC);
900 #ifndef __WIN32__
901 #ifdef STRICT
902 LocalUnlock(LocalHandle((void NEAR*) andBits));
903 LocalUnlock(LocalHandle((void NEAR*) xorBits));
904 LocalFree(LocalHandle((void NEAR*) andBits));
905 LocalFree(LocalHandle((void NEAR*) xorBits));
906 #else
907 LocalUnlock(LocalHandle((WORD) andBits));
908 LocalUnlock(LocalHandle((WORD) xorBits));
909 LocalFree(LocalHandle((WORD) andBits));
910 LocalFree(LocalHandle((WORD) xorBits));
911 #endif
912 #else
913 LocalUnlock(LocalHandle((LPCVOID) andBits));
914 LocalUnlock(LocalHandle((LPCVOID) xorBits));
915 LocalFree(LocalHandle((LPCVOID) andBits));
916 LocalFree(LocalHandle((LPCVOID) xorBits));
917 #endif
918 return hNewIcon;
919 }
920