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