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