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