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