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