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