2 * Cursor and icon support
4 * Copyright 1995 Alexandre Julliard
5 * 1996 Martin Von Loewis
7 * 1998 Turchanov Sergey
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * http://www.microsoft.com/win32dev/ui/icons.htm
29 * Cursors and icons are stored in a global heap block, with the
32 * CURSORICONINFO info;
36 * The bits structures are in the format of a device-dependent bitmap.
38 * This layout is very sub-optimal, as the bitmap bits are stored in
39 * the X client instead of in the server like other bitmaps; however,
40 * some programs (notably Paint Brush) expect to be able to manipulate
41 * the bits directly :-(
43 * FIXME: what are we going to do with animation and color (bpp > 1) cursors ?!
52 #include "wine/winbase16.h"
53 #include "wine/winuser16.h"
54 #include "wine/exception.h"
56 #include "cursoricon.h"
58 #include "wine/debug.h"
64 #include "msvcrt/excpt.h"
66 WINE_DEFAULT_DEBUG_CHANNEL(cursor
);
67 WINE_DECLARE_DEBUG_CHANNEL(icon
);
68 WINE_DECLARE_DEBUG_CHANNEL(resource
);
71 static RECT CURSOR_ClipRect
; /* Cursor clipping rect */
75 static const WCHAR DISPLAYW
[] = {'D','I','S','P','L','A','Y',0};
77 /**********************************************************************
78 * ICONCACHE for cursors/icons loaded with LR_SHARED.
80 * FIXME: This should not be allocated on the system heap, but on a
81 * subsystem-global heap (i.e. one for all Win16 processes,
82 * and one for each Win32 process).
84 typedef struct tagICONCACHE
86 struct tagICONCACHE
*next
;
97 static ICONCACHE
*IconAnchor
= NULL
;
98 static CRITICAL_SECTION IconCrst
= CRITICAL_SECTION_INIT("IconCrst");
99 static WORD ICON_HOTSPOT
= 0x4242;
102 /***********************************************************************
105 * Helper function to map a file to memory:
107 * [RETURN] ptr - pointer to mapped file
109 static void *map_fileW( LPCWSTR name
)
111 HANDLE hFile
, hMapping
;
114 hFile
= CreateFileW( name
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
115 OPEN_EXISTING
, FILE_FLAG_RANDOM_ACCESS
, 0 );
116 if (hFile
!= INVALID_HANDLE_VALUE
)
118 hMapping
= CreateFileMappingA( hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
119 CloseHandle( hFile
);
122 ptr
= MapViewOfFile( hMapping
, FILE_MAP_READ
, 0, 0, 0 );
123 CloseHandle( hMapping
);
130 /***********************************************************************
131 * get_bitmap_width_bytes
133 * Return number of bytes taken by a scanline of 16-bit aligned Windows DDB
136 static int get_bitmap_width_bytes( int width
, int bpp
)
141 return 2 * ((width
+15) / 16);
143 return 2 * ((width
+3) / 4);
148 return width
+ (width
& 1);
155 WARN("Unknown depth %d, please report.\n", bpp
);
161 /**********************************************************************
162 * CURSORICON_FindSharedIcon
164 static HICON
CURSORICON_FindSharedIcon( HMODULE hModule
, HRSRC hRsrc
)
169 EnterCriticalSection( &IconCrst
);
171 for ( ptr
= IconAnchor
; ptr
; ptr
= ptr
->next
)
172 if ( ptr
->hModule
== hModule
&& ptr
->hRsrc
== hRsrc
)
179 LeaveCriticalSection( &IconCrst
);
184 /*************************************************************************
185 * CURSORICON_FindCache
187 * Given a handle, find the corresponding cache element
190 * Handle [I] handle to an Image
193 * Success: The cache entry
197 static ICONCACHE
* CURSORICON_FindCache(HICON hIcon
)
200 ICONCACHE
*pRet
=NULL
;
201 BOOL IsFound
= FALSE
;
204 EnterCriticalSection( &IconCrst
);
206 for (count
= 0, ptr
= IconAnchor
; ptr
!= NULL
&& !IsFound
; ptr
= ptr
->next
, count
++ )
208 if ( hIcon
== ptr
->hIcon
)
215 LeaveCriticalSection( &IconCrst
);
220 /**********************************************************************
221 * CURSORICON_AddSharedIcon
223 static void CURSORICON_AddSharedIcon( HMODULE hModule
, HRSRC hRsrc
, HRSRC hGroupRsrc
, HICON hIcon
)
225 ICONCACHE
*ptr
= HeapAlloc( GetProcessHeap(), 0, sizeof(ICONCACHE
) );
228 ptr
->hModule
= hModule
;
231 ptr
->hGroupRsrc
= hGroupRsrc
;
234 EnterCriticalSection( &IconCrst
);
235 ptr
->next
= IconAnchor
;
237 LeaveCriticalSection( &IconCrst
);
240 /**********************************************************************
241 * CURSORICON_DelSharedIcon
243 static INT
CURSORICON_DelSharedIcon( HICON hIcon
)
248 EnterCriticalSection( &IconCrst
);
250 for ( ptr
= IconAnchor
; ptr
; ptr
= ptr
->next
)
251 if ( ptr
->hIcon
== hIcon
)
253 if ( ptr
->count
> 0 ) ptr
->count
--;
258 LeaveCriticalSection( &IconCrst
);
263 /**********************************************************************
264 * CURSORICON_FreeModuleIcons
266 void CURSORICON_FreeModuleIcons( HMODULE hModule
)
268 ICONCACHE
**ptr
= &IconAnchor
;
270 if ( HIWORD( hModule
) )
271 hModule
= MapHModuleLS( hModule
);
273 hModule
= GetExePtr( hModule
);
275 EnterCriticalSection( &IconCrst
);
279 if ( (*ptr
)->hModule
== hModule
)
281 ICONCACHE
*freePtr
= *ptr
;
282 *ptr
= freePtr
->next
;
284 GlobalFree16(HICON_16(freePtr
->hIcon
));
285 HeapFree( GetProcessHeap(), 0, freePtr
);
291 LeaveCriticalSection( &IconCrst
);
294 /**********************************************************************
295 * CURSORICON_FindBestIcon
297 * Find the icon closest to the requested size and number of colors.
299 static CURSORICONDIRENTRY
*CURSORICON_FindBestIcon( CURSORICONDIR
*dir
, int width
,
300 int height
, int colors
)
303 CURSORICONDIRENTRY
*entry
, *bestEntry
= NULL
;
304 UINT iTotalDiff
, iXDiff
=0, iYDiff
=0, iColorDiff
;
305 UINT iTempXDiff
, iTempYDiff
, iTempColorDiff
;
307 if (dir
->idCount
< 1)
309 WARN_(icon
)("Empty directory!\n" );
312 if (dir
->idCount
== 1) return &dir
->idEntries
[0]; /* No choice... */
315 iTotalDiff
= 0xFFFFFFFF;
316 iColorDiff
= 0xFFFFFFFF;
317 for (i
= 0, entry
= &dir
->idEntries
[0]; i
< dir
->idCount
; i
++,entry
++)
319 iTempXDiff
= abs(width
- entry
->ResInfo
.icon
.bWidth
);
320 iTempYDiff
= abs(height
- entry
->ResInfo
.icon
.bHeight
);
322 if(iTotalDiff
> (iTempXDiff
+ iTempYDiff
))
326 iTotalDiff
= iXDiff
+ iYDiff
;
330 /* Find Best Colors for Best Fit */
331 for (i
= 0, entry
= &dir
->idEntries
[0]; i
< dir
->idCount
; i
++,entry
++)
333 if(abs(width
- entry
->ResInfo
.icon
.bWidth
) == iXDiff
&&
334 abs(height
- entry
->ResInfo
.icon
.bHeight
) == iYDiff
)
336 iTempColorDiff
= abs(colors
- entry
->ResInfo
.icon
.bColorCount
);
337 if(iColorDiff
> iTempColorDiff
)
340 iColorDiff
= iTempColorDiff
;
349 /**********************************************************************
350 * CURSORICON_FindBestCursor
352 * Find the cursor closest to the requested size.
353 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
356 static CURSORICONDIRENTRY
*CURSORICON_FindBestCursor( CURSORICONDIR
*dir
,
357 int width
, int height
, int color
)
359 int i
, maxwidth
, maxheight
;
360 CURSORICONDIRENTRY
*entry
, *bestEntry
= NULL
;
362 if (dir
->idCount
< 1)
364 WARN_(cursor
)("Empty directory!\n" );
367 if (dir
->idCount
== 1) return &dir
->idEntries
[0]; /* No choice... */
369 /* Double height to account for AND and XOR masks */
373 /* First find the largest one smaller than or equal to the requested size*/
375 maxwidth
= maxheight
= 0;
376 for(i
= 0,entry
= &dir
->idEntries
[0]; i
< dir
->idCount
; i
++,entry
++)
377 if ((entry
->ResInfo
.cursor
.wWidth
<= width
) && (entry
->ResInfo
.cursor
.wHeight
<= height
) &&
378 (entry
->ResInfo
.cursor
.wWidth
> maxwidth
) && (entry
->ResInfo
.cursor
.wHeight
> maxheight
) &&
379 (entry
->wBitCount
== 1))
382 maxwidth
= entry
->ResInfo
.cursor
.wWidth
;
383 maxheight
= entry
->ResInfo
.cursor
.wHeight
;
385 if (bestEntry
) return bestEntry
;
387 /* Now find the smallest one larger than the requested size */
389 maxwidth
= maxheight
= 255;
390 for(i
= 0,entry
= &dir
->idEntries
[0]; i
< dir
->idCount
; i
++,entry
++)
391 if ((entry
->ResInfo
.cursor
.wWidth
< maxwidth
) && (entry
->ResInfo
.cursor
.wHeight
< maxheight
) &&
392 (entry
->wBitCount
== 1))
395 maxwidth
= entry
->ResInfo
.cursor
.wWidth
;
396 maxheight
= entry
->ResInfo
.cursor
.wHeight
;
402 /*********************************************************************
403 * The main purpose of this function is to create fake resource directory
404 * and fake resource entries. There are several reasons for this:
405 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
407 * There are some "bad" cursor files which do not have
408 * bColorCount initialized but instead one must read this info
409 * directly from corresponding DIB sections
410 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
412 static BOOL
CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename
, BOOL fCursor
,
413 CURSORICONDIR
**res
, LPBYTE
**ptr
)
416 CURSORICONFILEDIR
*bits
;
417 int entries
, size
, i
;
421 if (!(bits
= map_fileW( filename
))) return FALSE
;
423 /* FIXME: test for inimated icons
424 * hack to load the first icon from the *.ani file
426 if ( *(LPDWORD
)bits
==0x46464952 ) /* "RIFF" */
427 { LPBYTE pos
= (LPBYTE
) bits
;
428 FIXME_(cursor
)("Animated icons not correctly implemented! %p \n", bits
);
431 { if (*(LPDWORD
)pos
==0x6e6f6369) /* "icon" */
432 { FIXME_(cursor
)("icon entry found! %p\n", bits
);
434 if ( !*(LPWORD
) pos
==0x2fe) /* iconsize */
437 bits
=(CURSORICONFILEDIR
*)(pos
+4);
438 FIXME_(cursor
)("icon size ok. offset=%p \n", bits
);
442 if (pos
>=(LPBYTE
)bits
+766) goto fail
;
445 if (!(entries
= bits
->idCount
)) goto fail
;
446 size
= sizeof(CURSORICONDIR
) + sizeof(CURSORICONDIRENTRY
) * (entries
- 1);
447 _free
= (LPBYTE
) size
;
449 for (i
=0; i
< entries
; i
++)
450 size
+= bits
->idEntries
[i
].dwDIBSize
+ (fCursor
? sizeof(POINT16
): 0);
452 if (!(*ptr
= HeapAlloc( GetProcessHeap(), 0,
453 entries
* sizeof (CURSORICONDIRENTRY
*)))) goto fail
;
454 if (!(*res
= HeapAlloc( GetProcessHeap(), 0, size
))) goto fail
;
456 _free
= (LPBYTE
)(*res
) + (int)_free
;
457 memcpy((*res
), bits
, 6);
458 for (i
=0; i
<entries
; i
++)
460 ((LPBYTE
*)(*ptr
))[i
] = _free
;
462 (*res
)->idEntries
[i
].ResInfo
.cursor
.wWidth
=bits
->idEntries
[i
].bWidth
;
463 (*res
)->idEntries
[i
].ResInfo
.cursor
.wHeight
=bits
->idEntries
[i
].bHeight
;
464 ((LPPOINT16
)_free
)->x
=bits
->idEntries
[i
].xHotspot
;
465 ((LPPOINT16
)_free
)->y
=bits
->idEntries
[i
].yHotspot
;
466 _free
+=sizeof(POINT16
);
468 (*res
)->idEntries
[i
].ResInfo
.icon
.bWidth
=bits
->idEntries
[i
].bWidth
;
469 (*res
)->idEntries
[i
].ResInfo
.icon
.bHeight
=bits
->idEntries
[i
].bHeight
;
470 (*res
)->idEntries
[i
].ResInfo
.icon
.bColorCount
= bits
->idEntries
[i
].bColorCount
;
472 (*res
)->idEntries
[i
].wPlanes
=1;
473 (*res
)->idEntries
[i
].wBitCount
= ((LPBITMAPINFOHEADER
)((LPBYTE
)bits
+
474 bits
->idEntries
[i
].dwDIBOffset
))->biBitCount
;
475 (*res
)->idEntries
[i
].dwBytesInRes
= bits
->idEntries
[i
].dwDIBSize
;
476 (*res
)->idEntries
[i
].wResId
=i
+1;
478 memcpy(_free
,(LPBYTE
)bits
+bits
->idEntries
[i
].dwDIBOffset
,
479 (*res
)->idEntries
[i
].dwBytesInRes
);
480 _free
+= (*res
)->idEntries
[i
].dwBytesInRes
;
482 UnmapViewOfFile( bits
);
485 if (*res
) HeapFree( GetProcessHeap(), 0, *res
);
486 if (*ptr
) HeapFree( GetProcessHeap(), 0, *ptr
);
487 UnmapViewOfFile( bits
);
492 /**********************************************************************
493 * CURSORICON_CreateFromResource
495 * Create a cursor or icon from in-memory resource template.
497 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
498 * with cbSize parameter as well.
500 static HICON
CURSORICON_CreateFromResource( HMODULE16 hModule
, HGLOBAL16 hObj
, LPBYTE bits
,
501 UINT cbSize
, BOOL bIcon
, DWORD dwVersion
,
502 INT width
, INT height
, UINT loadflags
)
505 int sizeAnd
, sizeXor
;
506 HBITMAP hAndBits
= 0, hXorBits
= 0; /* error condition for later */
507 BITMAP bmpXor
, bmpAnd
;
513 hotspot
.x
= ICON_HOTSPOT
;
514 hotspot
.y
= ICON_HOTSPOT
;
516 TRACE_(cursor
)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
517 (unsigned)bits
, cbSize
, (unsigned)dwVersion
, width
, height
,
518 bIcon
? "icon" : "cursor", (loadflags
& LR_MONOCHROME
) ? "mono" : "" );
519 if (dwVersion
== 0x00020000)
521 FIXME_(cursor
)("\t2.xx resources are not supported\n");
526 bmi
= (BITMAPINFO
*)bits
;
527 else /* get the hotspot */
529 POINT16
*pt
= (POINT16
*)bits
;
531 bmi
= (BITMAPINFO
*)(pt
+ 1);
533 size
= DIB_BitmapInfoSize( bmi
, DIB_RGB_COLORS
);
535 if (!width
) width
= bmi
->bmiHeader
.biWidth
;
536 if (!height
) height
= bmi
->bmiHeader
.biHeight
/2;
537 DoStretch
= (bmi
->bmiHeader
.biHeight
/2 != height
) ||
538 (bmi
->bmiHeader
.biWidth
!= width
);
540 /* Check bitmap header */
542 if ( (bmi
->bmiHeader
.biSize
!= sizeof(BITMAPCOREHEADER
)) &&
543 (bmi
->bmiHeader
.biSize
!= sizeof(BITMAPINFOHEADER
) ||
544 bmi
->bmiHeader
.biCompression
!= BI_RGB
) )
546 WARN_(cursor
)("\tinvalid resource bitmap header.\n");
550 if (!screen_dc
) screen_dc
= CreateDCA( "DISPLAY", NULL
, NULL
, NULL
);
555 /* Make sure we have room for the monochrome bitmap later on.
556 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
557 * up to and including the biBitCount. In-memory icon resource
558 * format is as follows:
560 * BITMAPINFOHEADER icHeader // DIB header
561 * RGBQUAD icColors[] // Color table
562 * BYTE icXOR[] // DIB bits for XOR mask
563 * BYTE icAND[] // DIB bits for AND mask
566 if ((pInfo
= (BITMAPINFO
*)HeapAlloc( GetProcessHeap(), 0,
567 max(size
, sizeof(BITMAPINFOHEADER
) + 2*sizeof(RGBQUAD
)))))
569 memcpy( pInfo
, bmi
, size
);
570 pInfo
->bmiHeader
.biHeight
/= 2;
572 /* Create the XOR bitmap */
577 hXorBits
= CreateCompatibleBitmap(screen_dc
, width
, height
);
581 hXorBits
= CreateBitmap(width
, height
, 1, 1, NULL
);
588 if (!hdcMem
) hdcMem
= CreateCompatibleDC(screen_dc
);
590 hOld
= SelectObject(hdcMem
, hXorBits
);
591 res
= StretchDIBits(hdcMem
, 0, 0, width
, height
, 0, 0,
592 bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
/2,
593 (char*)bmi
+ size
, pInfo
, DIB_RGB_COLORS
, SRCCOPY
);
594 SelectObject(hdcMem
, hOld
);
596 if (!res
) { DeleteObject(hXorBits
); hXorBits
= 0; }
598 } else hXorBits
= CreateDIBitmap( screen_dc
, &pInfo
->bmiHeader
,
599 CBM_INIT
, (char*)bmi
+ size
, pInfo
, DIB_RGB_COLORS
);
602 char* xbits
= (char *)bmi
+ size
+
603 DIB_GetDIBImageBytes(bmi
->bmiHeader
.biWidth
,
604 bmi
->bmiHeader
.biHeight
,
605 bmi
->bmiHeader
.biBitCount
) / 2;
607 pInfo
->bmiHeader
.biBitCount
= 1;
608 if (pInfo
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
))
610 RGBQUAD
*rgb
= pInfo
->bmiColors
;
612 pInfo
->bmiHeader
.biClrUsed
= pInfo
->bmiHeader
.biClrImportant
= 2;
613 rgb
[0].rgbBlue
= rgb
[0].rgbGreen
= rgb
[0].rgbRed
= 0x00;
614 rgb
[1].rgbBlue
= rgb
[1].rgbGreen
= rgb
[1].rgbRed
= 0xff;
615 rgb
[0].rgbReserved
= rgb
[1].rgbReserved
= 0;
619 RGBTRIPLE
*rgb
= (RGBTRIPLE
*)(((BITMAPCOREHEADER
*)pInfo
) + 1);
621 rgb
[0].rgbtBlue
= rgb
[0].rgbtGreen
= rgb
[0].rgbtRed
= 0x00;
622 rgb
[1].rgbtBlue
= rgb
[1].rgbtGreen
= rgb
[1].rgbtRed
= 0xff;
625 /* Create the AND bitmap */
628 if ((hAndBits
= CreateBitmap(width
, height
, 1, 1, NULL
))) {
632 if (!hdcMem
) hdcMem
= CreateCompatibleDC(screen_dc
);
634 hOld
= SelectObject(hdcMem
, hAndBits
);
635 res
= StretchDIBits(hdcMem
, 0, 0, width
, height
, 0, 0,
636 pInfo
->bmiHeader
.biWidth
, pInfo
->bmiHeader
.biHeight
,
637 xbits
, pInfo
, DIB_RGB_COLORS
, SRCCOPY
);
638 SelectObject(hdcMem
, hOld
);
640 if (!res
) { DeleteObject(hAndBits
); hAndBits
= 0; }
642 } else hAndBits
= CreateDIBitmap( screen_dc
, &pInfo
->bmiHeader
,
643 CBM_INIT
, xbits
, pInfo
, DIB_RGB_COLORS
);
645 if( !hAndBits
) DeleteObject( hXorBits
);
647 HeapFree( GetProcessHeap(), 0, pInfo
);
651 if( !hXorBits
|| !hAndBits
)
653 WARN_(cursor
)("\tunable to create an icon bitmap.\n");
657 /* Now create the CURSORICONINFO structure */
658 GetObjectA( hXorBits
, sizeof(bmpXor
), &bmpXor
);
659 GetObjectA( hAndBits
, sizeof(bmpAnd
), &bmpAnd
);
660 sizeXor
= bmpXor
.bmHeight
* bmpXor
.bmWidthBytes
;
661 sizeAnd
= bmpAnd
.bmHeight
* bmpAnd
.bmWidthBytes
;
663 if (hObj
) hObj
= GlobalReAlloc16( hObj
,
664 sizeof(CURSORICONINFO
) + sizeXor
+ sizeAnd
, GMEM_MOVEABLE
);
665 if (!hObj
) hObj
= GlobalAlloc16( GMEM_MOVEABLE
,
666 sizeof(CURSORICONINFO
) + sizeXor
+ sizeAnd
);
669 CURSORICONINFO
*info
;
671 /* Make it owned by the module */
672 if (hModule
) hModule
= GetExePtr(hModule
);
673 FarSetOwner16( hObj
, hModule
);
675 info
= (CURSORICONINFO
*)GlobalLock16( hObj
);
676 info
->ptHotSpot
.x
= hotspot
.x
;
677 info
->ptHotSpot
.y
= hotspot
.y
;
678 info
->nWidth
= bmpXor
.bmWidth
;
679 info
->nHeight
= bmpXor
.bmHeight
;
680 info
->nWidthBytes
= bmpXor
.bmWidthBytes
;
681 info
->bPlanes
= bmpXor
.bmPlanes
;
682 info
->bBitsPerPixel
= bmpXor
.bmBitsPixel
;
684 /* Transfer the bitmap bits to the CURSORICONINFO structure */
686 GetBitmapBits( hAndBits
, sizeAnd
, (char *)(info
+ 1) );
687 GetBitmapBits( hXorBits
, sizeXor
, (char *)(info
+ 1) + sizeAnd
);
688 GlobalUnlock16( hObj
);
691 DeleteObject( hAndBits
);
692 DeleteObject( hXorBits
);
693 return HICON_32((HICON16
)hObj
);
697 /**********************************************************************
698 * CreateIconFromResource (USER32.@)
700 HICON WINAPI
CreateIconFromResource( LPBYTE bits
, UINT cbSize
,
701 BOOL bIcon
, DWORD dwVersion
)
703 return CreateIconFromResourceEx( bits
, cbSize
, bIcon
, dwVersion
, 0,0,0);
707 /**********************************************************************
708 * CreateIconFromResourceEx (USER32.@)
710 HICON WINAPI
CreateIconFromResourceEx( LPBYTE bits
, UINT cbSize
,
711 BOOL bIcon
, DWORD dwVersion
,
712 INT width
, INT height
,
715 return CURSORICON_CreateFromResource( 0, 0, bits
, cbSize
, bIcon
, dwVersion
,
716 width
, height
, cFlag
);
719 /**********************************************************************
722 * Load a cursor or icon from resource or file.
724 static HICON
CURSORICON_Load(HINSTANCE hInstance
, LPCWSTR name
,
725 INT width
, INT height
, INT colors
,
726 BOOL fCursor
, UINT loadflags
)
732 CURSORICONDIRENTRY
*dirEntry
;
735 if ( loadflags
& LR_LOADFROMFILE
) /* Load from file */
738 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR
)name
, fCursor
, &dir
, &ptr
))
741 dirEntry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestCursor(dir
, width
, height
, 1);
743 dirEntry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestIcon(dir
, width
, height
, colors
);
744 bits
= ptr
[dirEntry
->wResId
-1];
745 hIcon
= CURSORICON_CreateFromResource( 0, 0, bits
, dirEntry
->dwBytesInRes
,
746 !fCursor
, 0x00030000, width
, height
, loadflags
);
747 HeapFree( GetProcessHeap(), 0, dir
);
748 HeapFree( GetProcessHeap(), 0, ptr
);
750 else /* Load from resource */
756 if (!hInstance
) /* Load OEM cursor/icon */
758 if (!(hInstance
= GetModuleHandleA( "user32.dll" ))) return 0;
761 /* Normalize hInstance (must be uniquely represented for icon cache) */
763 if ( HIWORD( hInstance
) )
764 hInstance
= MapHModuleLS( hInstance
);
766 hInstance
= GetExePtr( hInstance
);
768 /* Get directory resource ID */
770 if (!(hRsrc
= FindResourceW( hInstance
, name
,
771 fCursor
? RT_GROUP_CURSORW
: RT_GROUP_ICONW
)))
775 /* Find the best entry in the directory */
777 if (!(handle
= LoadResource( hInstance
, hRsrc
))) return 0;
778 if (!(dir
= (CURSORICONDIR
*)LockResource( handle
))) return 0;
780 dirEntry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestCursor( dir
,
783 dirEntry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestIcon( dir
,
784 width
, height
, colors
);
785 if (!dirEntry
) return 0;
786 wResId
= dirEntry
->wResId
;
787 dwBytesInRes
= dirEntry
->dwBytesInRes
;
788 FreeResource( handle
);
790 /* Load the resource */
792 if (!(hRsrc
= FindResourceW(hInstance
,MAKEINTRESOURCEW(wResId
),
793 fCursor
? RT_CURSORW
: RT_ICONW
))) return 0;
795 /* If shared icon, check whether it was already loaded */
796 if ( (loadflags
& LR_SHARED
)
797 && (hIcon
= CURSORICON_FindSharedIcon( hInstance
, hRsrc
) ) != 0 )
800 if (!(handle
= LoadResource( hInstance
, hRsrc
))) return 0;
801 bits
= (LPBYTE
)LockResource( handle
);
802 hIcon
= CURSORICON_CreateFromResource( 0, 0, bits
, dwBytesInRes
,
803 !fCursor
, 0x00030000, width
, height
, loadflags
);
804 FreeResource( handle
);
806 /* If shared icon, add to icon cache */
808 if ( hIcon
&& (loadflags
& LR_SHARED
) )
809 CURSORICON_AddSharedIcon( hInstance
, hRsrc
, hGroupRsrc
, hIcon
);
815 /***********************************************************************
818 * Make a copy of a cursor or icon.
820 static HICON
CURSORICON_Copy( HINSTANCE16 hInst16
, HICON hIcon
)
822 char *ptrOld
, *ptrNew
;
824 HICON16 hOld
= HICON_16(hIcon
);
827 if (!(ptrOld
= (char *)GlobalLock16( hOld
))) return 0;
828 if (hInst16
&& !(hInst16
= GetExePtr( hInst16
))) return 0;
829 size
= GlobalSize16( hOld
);
830 hNew
= GlobalAlloc16( GMEM_MOVEABLE
, size
);
831 FarSetOwner16( hNew
, hInst16
);
832 ptrNew
= (char *)GlobalLock16( hNew
);
833 memcpy( ptrNew
, ptrOld
, size
);
834 GlobalUnlock16( hOld
);
835 GlobalUnlock16( hNew
);
836 return HICON_32(hNew
);
839 /*************************************************************************
842 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
845 * Handle [I] handle to an Image
846 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
847 * iDesiredCX [I] The Desired width of the Image
848 * iDesiredCY [I] The desired height of the Image
849 * nFlags [I] The flags from CopyImage
852 * Success: The new handle of the Image
855 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
856 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
857 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
862 static HICON
CURSORICON_ExtCopy(HICON hIcon
, UINT nType
,
863 INT iDesiredCX
, INT iDesiredCY
,
868 TRACE_(icon
)("hIcon %u, nType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
869 hIcon
, nType
, iDesiredCX
, iDesiredCY
, nFlags
);
876 /* Best Fit or Monochrome */
877 if( (nFlags
& LR_COPYFROMRESOURCE
878 && (iDesiredCX
> 0 || iDesiredCY
> 0))
879 || nFlags
& LR_MONOCHROME
)
881 ICONCACHE
* pIconCache
= CURSORICON_FindCache(hIcon
);
883 /* Not Found in Cache, then do a straight copy
885 if(pIconCache
== NULL
)
887 hNew
= CURSORICON_Copy(0, hIcon
);
888 if(nFlags
& LR_COPYFROMRESOURCE
)
890 TRACE_(icon
)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
895 int iTargetCY
= iDesiredCY
, iTargetCX
= iDesiredCX
;
902 CURSORICONDIRENTRY
*pDirEntry
;
903 BOOL bIsIcon
= (nType
== IMAGE_ICON
);
905 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
907 if(((nFlags
& LR_MONOCHROME
) && !(nFlags
& LR_COPYFROMRESOURCE
))
908 || (iDesiredCX
== 0 && iDesiredCY
== 0))
910 iDesiredCY
= GetSystemMetrics(bIsIcon
?
911 SM_CYICON
: SM_CYCURSOR
);
912 iDesiredCX
= GetSystemMetrics(bIsIcon
?
913 SM_CXICON
: SM_CXCURSOR
);
916 /* Retrieve the CURSORICONDIRENTRY
918 if (!(hMem
= LoadResource( pIconCache
->hModule
,
919 pIconCache
->hGroupRsrc
)))
923 if (!(pDir
= (CURSORICONDIR
*)LockResource( hMem
)))
932 pDirEntry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestIcon(
933 pDir
, iDesiredCX
, iDesiredCY
, 256);
937 pDirEntry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestCursor(
938 pDir
, iDesiredCX
, iDesiredCY
, 1);
941 wResId
= pDirEntry
->wResId
;
942 dwBytesInRes
= pDirEntry
->dwBytesInRes
;
945 TRACE_(icon
)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
946 wResId
, dwBytesInRes
, pDirEntry
->ResInfo
.icon
.bWidth
,
947 pDirEntry
->ResInfo
.icon
.bHeight
, iDesiredCX
, iDesiredCY
);
951 if (!(hRsrc
= FindResourceW(pIconCache
->hModule
,
952 MAKEINTRESOURCEW(wResId
), bIsIcon
? RT_ICONW
: RT_CURSORW
)))
956 if (!(hMem
= LoadResource( pIconCache
->hModule
, hRsrc
)))
961 pBits
= (LPBYTE
)LockResource( hMem
);
963 if(nFlags
& LR_DEFAULTSIZE
)
965 iTargetCY
= GetSystemMetrics(SM_CYICON
);
966 iTargetCX
= GetSystemMetrics(SM_CXICON
);
969 /* Create a New Icon with the proper dimension
971 hNew
= CURSORICON_CreateFromResource( 0, 0, pBits
, dwBytesInRes
,
972 bIsIcon
, 0x00030000, iTargetCX
, iTargetCY
, nFlags
);
976 else hNew
= CURSORICON_Copy(0, hIcon
);
981 /***********************************************************************
982 * CreateCursor (USER32.@)
984 HCURSOR WINAPI
CreateCursor( HINSTANCE hInstance
,
985 INT xHotSpot
, INT yHotSpot
,
986 INT nWidth
, INT nHeight
,
987 LPCVOID lpANDbits
, LPCVOID lpXORbits
)
991 TRACE_(cursor
)("%dx%d spot=%d,%d xor=%p and=%p\n",
992 nWidth
, nHeight
, xHotSpot
, yHotSpot
, lpXORbits
, lpANDbits
);
994 info
.ptHotSpot
.x
= xHotSpot
;
995 info
.ptHotSpot
.y
= yHotSpot
;
996 info
.nWidth
= nWidth
;
997 info
.nHeight
= nHeight
;
998 info
.nWidthBytes
= 0;
1000 info
.bBitsPerPixel
= 1;
1002 return HICON_32(CreateCursorIconIndirect16(MapHModuleLS(hInstance
), &info
,
1003 lpANDbits
, lpXORbits
));
1007 /***********************************************************************
1008 * CreateIcon (USER.407)
1010 HICON16 WINAPI
CreateIcon16( HINSTANCE16 hInstance
, INT16 nWidth
,
1011 INT16 nHeight
, BYTE bPlanes
, BYTE bBitsPixel
,
1012 LPCVOID lpANDbits
, LPCVOID lpXORbits
)
1014 CURSORICONINFO info
;
1016 TRACE_(icon
)("%dx%dx%d, xor=%p, and=%p\n",
1017 nWidth
, nHeight
, bPlanes
* bBitsPixel
, lpXORbits
, lpANDbits
);
1019 info
.ptHotSpot
.x
= ICON_HOTSPOT
;
1020 info
.ptHotSpot
.y
= ICON_HOTSPOT
;
1021 info
.nWidth
= nWidth
;
1022 info
.nHeight
= nHeight
;
1023 info
.nWidthBytes
= 0;
1024 info
.bPlanes
= bPlanes
;
1025 info
.bBitsPerPixel
= bBitsPixel
;
1027 return CreateCursorIconIndirect16( hInstance
, &info
, lpANDbits
, lpXORbits
);
1031 /***********************************************************************
1032 * CreateIcon (USER32.@)
1034 * Creates an icon based on the specified bitmaps. The bitmaps must be
1035 * provided in a device dependent format and will be resized to
1036 * (SM_CXICON,SM_CYICON) and depth converted to match the screen's color
1037 * depth. The provided bitmaps must be top-down bitmaps.
1038 * Although Windows does not support 15bpp(*) this API must support it
1039 * for Winelib applications.
1041 * (*) Windows does not support 15bpp but it supports the 555 RGB 16bpp
1046 * - The provided bitmaps are not resized!
1047 * - The documentation says the lpXORbits bitmap must be in a device
1048 * dependent format. But we must still resize it and perform depth
1049 * conversions if necessary.
1050 * - I'm a bit unsure about the how the 'device dependent format' thing works.
1051 * I did some tests on windows and found that if you provide a 16bpp bitmap
1052 * in lpXORbits, then its format but be 565 RGB if the screen's bit depth
1053 * is 16bpp but it must be 555 RGB if the screen's bit depth is anything
1054 * else. I don't know if this is part of the GDI specs or if this is a
1055 * quirk of the graphics card driver.
1056 * - You may think that we check whether the bit depths match or not
1057 * as an optimization. But the truth is that the conversion using
1058 * CreateDIBitmap does not work for some bit depth (e.g. 8bpp) and I have
1060 * - I'm pretty sure that all the things we do in CreateIcon should
1061 * also be done in CreateIconIndirect...
1063 HICON WINAPI
CreateIcon(
1064 HINSTANCE hInstance
, /* [in] the application's hInstance */
1065 INT nWidth
, /* [in] the width of the provided bitmaps */
1066 INT nHeight
, /* [in] the height of the provided bitmaps */
1067 BYTE bPlanes
, /* [in] the number of planes in the provided bitmaps */
1068 BYTE bBitsPixel
, /* [in] the number of bits per pixel of the lpXORbits bitmap */
1069 LPCVOID lpANDbits
, /* [in] a monochrome bitmap representing the icon's mask */
1070 LPCVOID lpXORbits
) /* [in] the icon's 'color' bitmap */
1075 TRACE_(icon
)("%dx%dx%d, xor=%p, and=%p\n",
1076 nWidth
, nHeight
, bPlanes
* bBitsPixel
, lpXORbits
, lpANDbits
);
1082 if (GetDeviceCaps(hdc
,BITSPIXEL
)==bBitsPixel
) {
1083 CURSORICONINFO info
;
1085 info
.ptHotSpot
.x
= ICON_HOTSPOT
;
1086 info
.ptHotSpot
.y
= ICON_HOTSPOT
;
1087 info
.nWidth
= nWidth
;
1088 info
.nHeight
= nHeight
;
1089 info
.nWidthBytes
= 0;
1090 info
.bPlanes
= bPlanes
;
1091 info
.bBitsPerPixel
= bBitsPixel
;
1093 hIcon
=HICON_32(CreateCursorIconIndirect16(MapHModuleLS(hInstance
), &info
,
1094 lpANDbits
, lpXORbits
));
1100 iinfo
.xHotspot
=ICON_HOTSPOT
;
1101 iinfo
.yHotspot
=ICON_HOTSPOT
;
1102 iinfo
.hbmMask
=CreateBitmap(nWidth
,nHeight
,1,1,lpANDbits
);
1104 bmi
.bmiHeader
.biSize
=sizeof(bmi
.bmiHeader
);
1105 bmi
.bmiHeader
.biWidth
=nWidth
;
1106 bmi
.bmiHeader
.biHeight
=-nHeight
;
1107 bmi
.bmiHeader
.biPlanes
=bPlanes
;
1108 bmi
.bmiHeader
.biBitCount
=bBitsPixel
;
1109 bmi
.bmiHeader
.biCompression
=BI_RGB
;
1110 bmi
.bmiHeader
.biSizeImage
=0;
1111 bmi
.bmiHeader
.biXPelsPerMeter
=0;
1112 bmi
.bmiHeader
.biYPelsPerMeter
=0;
1113 bmi
.bmiHeader
.biClrUsed
=0;
1114 bmi
.bmiHeader
.biClrImportant
=0;
1116 iinfo
.hbmColor
= CreateDIBitmap( hdc
, &bmi
.bmiHeader
,
1117 CBM_INIT
, lpXORbits
,
1118 &bmi
, DIB_RGB_COLORS
);
1120 hIcon
=CreateIconIndirect(&iinfo
);
1121 DeleteObject(iinfo
.hbmMask
);
1122 DeleteObject(iinfo
.hbmColor
);
1129 /***********************************************************************
1130 * CreateCursorIconIndirect (USER.408)
1132 HGLOBAL16 WINAPI
CreateCursorIconIndirect16( HINSTANCE16 hInstance
,
1133 CURSORICONINFO
*info
,
1139 int sizeAnd
, sizeXor
;
1141 hInstance
= GetExePtr( hInstance
); /* Make it a module handle */
1142 if (!lpXORbits
|| !lpANDbits
|| info
->bPlanes
!= 1) return 0;
1143 info
->nWidthBytes
= get_bitmap_width_bytes(info
->nWidth
,info
->bBitsPerPixel
);
1144 sizeXor
= info
->nHeight
* info
->nWidthBytes
;
1145 sizeAnd
= info
->nHeight
* get_bitmap_width_bytes( info
->nWidth
, 1 );
1146 if (!(handle
= GlobalAlloc16( GMEM_MOVEABLE
,
1147 sizeof(CURSORICONINFO
) + sizeXor
+ sizeAnd
)))
1149 FarSetOwner16( handle
, hInstance
);
1150 ptr
= (char *)GlobalLock16( handle
);
1151 memcpy( ptr
, info
, sizeof(*info
) );
1152 memcpy( ptr
+ sizeof(CURSORICONINFO
), lpANDbits
, sizeAnd
);
1153 memcpy( ptr
+ sizeof(CURSORICONINFO
) + sizeAnd
, lpXORbits
, sizeXor
);
1154 GlobalUnlock16( handle
);
1159 /***********************************************************************
1160 * CopyIcon (USER.368)
1162 HICON16 WINAPI
CopyIcon16( HINSTANCE16 hInstance
, HICON16 hIcon
)
1164 TRACE_(icon
)("%04x %04x\n", hInstance
, hIcon
);
1165 return HICON_16(CURSORICON_Copy(hInstance
, HICON_32(hIcon
)));
1169 /***********************************************************************
1170 * CopyIcon (USER32.@)
1172 HICON WINAPI
CopyIcon( HICON hIcon
)
1174 TRACE_(icon
)("%04x\n", hIcon
);
1175 return CURSORICON_Copy( 0, hIcon
);
1179 /***********************************************************************
1180 * CopyCursor (USER.369)
1182 HCURSOR16 WINAPI
CopyCursor16( HINSTANCE16 hInstance
, HCURSOR16 hCursor
)
1184 TRACE_(cursor
)("%04x %04x\n", hInstance
, hCursor
);
1185 return HICON_16(CURSORICON_Copy(hInstance
, HCURSOR_32(hCursor
)));
1188 /**********************************************************************
1189 * DestroyIcon32 (USER.610)
1191 * This routine is actually exported from Win95 USER under the name
1192 * DestroyIcon32 ... The behaviour implemented here should mimic
1193 * the Win95 one exactly, especially the return values, which
1194 * depend on the setting of various flags.
1196 WORD WINAPI
DestroyIcon32( HGLOBAL16 handle
, UINT16 flags
)
1200 TRACE_(icon
)("(%04x, %04x)\n", handle
, flags
);
1202 /* Check whether destroying active cursor */
1204 if ( QUEUE_Current()->cursor
== HICON_32(handle
) )
1206 WARN_(cursor
)("Destroying active cursor!\n" );
1210 /* Try shared cursor/icon first */
1212 if ( !(flags
& CID_NONSHARED
) )
1214 INT count
= CURSORICON_DelSharedIcon(HICON_32(handle
));
1217 return (flags
& CID_WIN32
)? TRUE
: (count
== 0);
1219 /* FIXME: OEM cursors/icons should be recognized */
1222 /* Now assume non-shared cursor/icon */
1224 retv
= GlobalFree16( handle
);
1225 return (flags
& CID_RESOURCE
)? retv
: TRUE
;
1228 /***********************************************************************
1229 * DestroyIcon (USER32.@)
1231 BOOL WINAPI
DestroyIcon( HICON hIcon
)
1233 return DestroyIcon32(HICON_16(hIcon
), CID_WIN32
);
1237 /***********************************************************************
1238 * DestroyCursor (USER32.@)
1240 BOOL WINAPI
DestroyCursor( HCURSOR hCursor
)
1242 return DestroyIcon32(HCURSOR_16(hCursor
), CID_WIN32
);
1246 /***********************************************************************
1247 * DrawIcon (USER32.@)
1249 BOOL WINAPI
DrawIcon( HDC hdc
, INT x
, INT y
, HICON hIcon
)
1251 CURSORICONINFO
*ptr
;
1253 HBITMAP hXorBits
, hAndBits
;
1254 COLORREF oldFg
, oldBg
;
1256 if (!(ptr
= (CURSORICONINFO
*)GlobalLock16(HICON_16(hIcon
)))) return FALSE
;
1257 if (!(hMemDC
= CreateCompatibleDC( hdc
))) return FALSE
;
1258 hAndBits
= CreateBitmap( ptr
->nWidth
, ptr
->nHeight
, 1, 1,
1260 hXorBits
= CreateBitmap( ptr
->nWidth
, ptr
->nHeight
, ptr
->bPlanes
,
1261 ptr
->bBitsPerPixel
, (char *)(ptr
+ 1)
1262 + ptr
->nHeight
* get_bitmap_width_bytes(ptr
->nWidth
,1) );
1263 oldFg
= SetTextColor( hdc
, RGB(0,0,0) );
1264 oldBg
= SetBkColor( hdc
, RGB(255,255,255) );
1266 if (hXorBits
&& hAndBits
)
1268 HBITMAP hBitTemp
= SelectObject( hMemDC
, hAndBits
);
1269 BitBlt( hdc
, x
, y
, ptr
->nWidth
, ptr
->nHeight
, hMemDC
, 0, 0, SRCAND
);
1270 SelectObject( hMemDC
, hXorBits
);
1271 BitBlt(hdc
, x
, y
, ptr
->nWidth
, ptr
->nHeight
, hMemDC
, 0, 0,SRCINVERT
);
1272 SelectObject( hMemDC
, hBitTemp
);
1275 if (hXorBits
) DeleteObject( hXorBits
);
1276 if (hAndBits
) DeleteObject( hAndBits
);
1277 GlobalUnlock16(HICON_16(hIcon
));
1278 SetTextColor( hdc
, oldFg
);
1279 SetBkColor( hdc
, oldBg
);
1283 /***********************************************************************
1284 * DumpIcon (USER.459)
1286 DWORD WINAPI
DumpIcon16( SEGPTR pInfo
, WORD
*lpLen
,
1287 SEGPTR
*lpXorBits
, SEGPTR
*lpAndBits
)
1289 CURSORICONINFO
*info
= MapSL( pInfo
);
1290 int sizeAnd
, sizeXor
;
1292 if (!info
) return 0;
1293 sizeXor
= info
->nHeight
* info
->nWidthBytes
;
1294 sizeAnd
= info
->nHeight
* get_bitmap_width_bytes( info
->nWidth
, 1 );
1295 if (lpAndBits
) *lpAndBits
= pInfo
+ sizeof(CURSORICONINFO
);
1296 if (lpXorBits
) *lpXorBits
= pInfo
+ sizeof(CURSORICONINFO
) + sizeAnd
;
1297 if (lpLen
) *lpLen
= sizeof(CURSORICONINFO
) + sizeAnd
+ sizeXor
;
1298 return MAKELONG( sizeXor
, sizeXor
);
1302 /***********************************************************************
1303 * SetCursor (USER32.@)
1305 * A handle to the previous cursor shape.
1307 HCURSOR WINAPI
SetCursor( HCURSOR hCursor
/* [in] Handle of cursor to show */ )
1309 MESSAGEQUEUE
*queue
= QUEUE_Current();
1312 if (hCursor
== queue
->cursor
) return hCursor
; /* No change */
1313 TRACE_(cursor
)("%04x\n", hCursor
);
1314 hOldCursor
= queue
->cursor
;
1315 queue
->cursor
= hCursor
;
1316 /* Change the cursor shape only if it is visible */
1317 if (queue
->cursor_count
>= 0)
1319 USER_Driver
.pSetCursor( (CURSORICONINFO
*)GlobalLock16(HCURSOR_16(hCursor
)) );
1320 GlobalUnlock16(HCURSOR_16(hCursor
));
1325 /***********************************************************************
1326 * ShowCursor (USER32.@)
1328 INT WINAPI
ShowCursor( BOOL bShow
)
1330 MESSAGEQUEUE
*queue
= QUEUE_Current();
1332 TRACE_(cursor
)("%d, count=%d\n", bShow
, queue
->cursor_count
);
1336 if (++queue
->cursor_count
== 0) /* Show it */
1338 USER_Driver
.pSetCursor((CURSORICONINFO
*)GlobalLock16(HCURSOR_16(queue
->cursor
)));
1339 GlobalUnlock16(HCURSOR_16(queue
->cursor
));
1344 if (--queue
->cursor_count
== -1) /* Hide it */
1345 USER_Driver
.pSetCursor( NULL
);
1347 return queue
->cursor_count
;
1350 /***********************************************************************
1351 * GetCursor (USER32.@)
1353 HCURSOR WINAPI
GetCursor(void)
1355 return QUEUE_Current()->cursor
;
1359 /***********************************************************************
1360 * ClipCursor (USER.16)
1362 BOOL16 WINAPI
ClipCursor16( const RECT16
*rect
)
1364 if (!rect
) SetRectEmpty( &CURSOR_ClipRect
);
1365 else CONV_RECT16TO32( rect
, &CURSOR_ClipRect
);
1370 /***********************************************************************
1371 * ClipCursor (USER32.@)
1373 BOOL WINAPI
ClipCursor( const RECT
*rect
)
1375 if (!rect
) SetRectEmpty( &CURSOR_ClipRect
);
1376 else CopyRect( &CURSOR_ClipRect
, rect
);
1381 /***********************************************************************
1382 * GetClipCursor (USER.309)
1384 void WINAPI
GetClipCursor16( RECT16
*rect
)
1386 if (rect
) CONV_RECT32TO16( &CURSOR_ClipRect
, rect
);
1390 /***********************************************************************
1391 * GetClipCursor (USER32.@)
1393 BOOL WINAPI
GetClipCursor( RECT
*rect
)
1397 CopyRect( rect
, &CURSOR_ClipRect
);
1403 /**********************************************************************
1404 * LookupIconIdFromDirectoryEx (USER.364)
1406 * FIXME: exact parameter sizes
1408 INT16 WINAPI
LookupIconIdFromDirectoryEx16( LPBYTE dir
, BOOL16 bIcon
,
1409 INT16 width
, INT16 height
, UINT16 cFlag
)
1411 return LookupIconIdFromDirectoryEx( dir
, bIcon
, width
, height
, cFlag
);
1414 /**********************************************************************
1415 * LookupIconIdFromDirectoryEx (USER32.@)
1417 INT WINAPI
LookupIconIdFromDirectoryEx( LPBYTE xdir
, BOOL bIcon
,
1418 INT width
, INT height
, UINT cFlag
)
1420 CURSORICONDIR
*dir
= (CURSORICONDIR
*)xdir
;
1422 if( dir
&& !dir
->idReserved
&& (dir
->idType
& 3) )
1424 CURSORICONDIRENTRY
* entry
;
1429 palEnts
= GetSystemPaletteEntries(hdc
, 0, 0, NULL
);
1432 colors
= (cFlag
& LR_MONOCHROME
) ? 2 : palEnts
;
1437 entry
= CURSORICON_FindBestIcon( dir
, width
, height
, colors
);
1439 entry
= CURSORICON_FindBestCursor( dir
, width
, height
, 1);
1441 if( entry
) retVal
= entry
->wResId
;
1443 else WARN_(cursor
)("invalid resource directory\n");
1447 /**********************************************************************
1448 * LookupIconIdFromDirectory (USER.?)
1450 INT16 WINAPI
LookupIconIdFromDirectory16( LPBYTE dir
, BOOL16 bIcon
)
1452 return LookupIconIdFromDirectoryEx16( dir
, bIcon
,
1453 bIcon
? GetSystemMetrics(SM_CXICON
) : GetSystemMetrics(SM_CXCURSOR
),
1454 bIcon
? GetSystemMetrics(SM_CYICON
) : GetSystemMetrics(SM_CYCURSOR
), bIcon
? 0 : LR_MONOCHROME
);
1457 /**********************************************************************
1458 * LookupIconIdFromDirectory (USER32.@)
1460 INT WINAPI
LookupIconIdFromDirectory( LPBYTE dir
, BOOL bIcon
)
1462 return LookupIconIdFromDirectoryEx( dir
, bIcon
,
1463 bIcon
? GetSystemMetrics(SM_CXICON
) : GetSystemMetrics(SM_CXCURSOR
),
1464 bIcon
? GetSystemMetrics(SM_CYICON
) : GetSystemMetrics(SM_CYCURSOR
), bIcon
? 0 : LR_MONOCHROME
);
1467 /**********************************************************************
1468 * GetIconID (USER.455)
1470 WORD WINAPI
GetIconID16( HGLOBAL16 hResource
, DWORD resType
)
1472 LPBYTE lpDir
= (LPBYTE
)GlobalLock16(hResource
);
1474 TRACE_(cursor
)("hRes=%04x, entries=%i\n",
1475 hResource
, lpDir
? ((CURSORICONDIR
*)lpDir
)->idCount
: 0);
1480 return (WORD
)LookupIconIdFromDirectoryEx16( lpDir
, FALSE
,
1481 GetSystemMetrics(SM_CXCURSOR
), GetSystemMetrics(SM_CYCURSOR
), LR_MONOCHROME
);
1483 return (WORD
)LookupIconIdFromDirectoryEx16( lpDir
, TRUE
,
1484 GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
), 0 );
1486 WARN_(cursor
)("invalid res type %ld\n", resType
);
1491 /**********************************************************************
1492 * LoadCursorIconHandler (USER.336)
1494 * Supposed to load resources of Windows 2.x applications.
1496 HGLOBAL16 WINAPI
LoadCursorIconHandler16( HGLOBAL16 hResource
, HMODULE16 hModule
, HRSRC16 hRsrc
)
1498 FIXME_(cursor
)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1499 hResource
, hModule
, hRsrc
);
1500 return (HGLOBAL16
)0;
1503 /**********************************************************************
1504 * LoadDIBIconHandler (USER.357)
1506 * RT_ICON resource loader, installed by USER_SignalProc when module
1509 HGLOBAL16 WINAPI
LoadDIBIconHandler16( HGLOBAL16 hMemObj
, HMODULE16 hModule
, HRSRC16 hRsrc
)
1511 /* If hResource is zero we must allocate a new memory block, if it's
1512 * non-zero but GlobalLock() returns NULL then it was discarded and
1513 * we have to recommit some memory, otherwise we just need to check
1514 * the block size. See LoadProc() in 16-bit SDK for more.
1517 hMemObj
= NE_DefResourceHandler( hMemObj
, hModule
, hRsrc
);
1520 LPBYTE bits
= (LPBYTE
)GlobalLock16( hMemObj
);
1521 hMemObj
= HICON_16(CURSORICON_CreateFromResource(
1522 hModule
, hMemObj
, bits
,
1523 SizeofResource16(hModule
, hRsrc
), TRUE
, 0x00030000,
1524 GetSystemMetrics(SM_CXICON
),
1525 GetSystemMetrics(SM_CYICON
), LR_DEFAULTCOLOR
));
1530 /**********************************************************************
1531 * LoadDIBCursorHandler (USER.356)
1533 * RT_CURSOR resource loader. Same as above.
1535 HGLOBAL16 WINAPI
LoadDIBCursorHandler16( HGLOBAL16 hMemObj
, HMODULE16 hModule
, HRSRC16 hRsrc
)
1537 hMemObj
= NE_DefResourceHandler( hMemObj
, hModule
, hRsrc
);
1540 LPBYTE bits
= (LPBYTE
)GlobalLock16( hMemObj
);
1541 hMemObj
= HICON_16(CURSORICON_CreateFromResource(
1542 hModule
, hMemObj
, bits
,
1543 SizeofResource16(hModule
, hRsrc
), FALSE
, 0x00030000,
1544 GetSystemMetrics(SM_CXCURSOR
),
1545 GetSystemMetrics(SM_CYCURSOR
), LR_MONOCHROME
));
1550 /**********************************************************************
1551 * LoadIconHandler (USER.456)
1553 HICON16 WINAPI
LoadIconHandler16( HGLOBAL16 hResource
, BOOL16 bNew
)
1555 LPBYTE bits
= (LPBYTE
)LockResource16( hResource
);
1557 TRACE_(cursor
)("hRes=%04x\n",hResource
);
1559 return HICON_16(CURSORICON_CreateFromResource(0, 0, bits
, 0, TRUE
,
1560 bNew
? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR
));
1563 /***********************************************************************
1564 * LoadCursorW (USER32.@)
1566 HCURSOR WINAPI
LoadCursorW(HINSTANCE hInstance
, LPCWSTR name
)
1568 return LoadImageW( hInstance
, name
, IMAGE_CURSOR
, 0, 0,
1569 LR_SHARED
| LR_DEFAULTSIZE
);
1572 /***********************************************************************
1573 * LoadCursorA (USER32.@)
1575 HCURSOR WINAPI
LoadCursorA(HINSTANCE hInstance
, LPCSTR name
)
1577 return LoadImageA( hInstance
, name
, IMAGE_CURSOR
, 0, 0,
1578 LR_SHARED
| LR_DEFAULTSIZE
);
1581 /***********************************************************************
1582 * LoadCursorFromFileW (USER32.@)
1584 HCURSOR WINAPI
LoadCursorFromFileW (LPCWSTR name
)
1586 return LoadImageW( 0, name
, IMAGE_CURSOR
, 0, 0,
1587 LR_LOADFROMFILE
| LR_DEFAULTSIZE
);
1590 /***********************************************************************
1591 * LoadCursorFromFileA (USER32.@)
1593 HCURSOR WINAPI
LoadCursorFromFileA (LPCSTR name
)
1595 return LoadImageA( 0, name
, IMAGE_CURSOR
, 0, 0,
1596 LR_LOADFROMFILE
| LR_DEFAULTSIZE
);
1599 /***********************************************************************
1600 * LoadIconW (USER32.@)
1602 HICON WINAPI
LoadIconW(HINSTANCE hInstance
, LPCWSTR name
)
1604 return LoadImageW( hInstance
, name
, IMAGE_ICON
, 0, 0,
1605 LR_SHARED
| LR_DEFAULTSIZE
);
1608 /***********************************************************************
1609 * LoadIconA (USER32.@)
1611 HICON WINAPI
LoadIconA(HINSTANCE hInstance
, LPCSTR name
)
1613 return LoadImageA( hInstance
, name
, IMAGE_ICON
, 0, 0,
1614 LR_SHARED
| LR_DEFAULTSIZE
);
1617 /**********************************************************************
1618 * GetIconInfo (USER32.@)
1620 BOOL WINAPI
GetIconInfo(HICON hIcon
,PICONINFO iconinfo
) {
1621 CURSORICONINFO
*ciconinfo
;
1623 ciconinfo
= GlobalLock16(HICON_16(hIcon
));
1627 if ( (ciconinfo
->ptHotSpot
.x
== ICON_HOTSPOT
) &&
1628 (ciconinfo
->ptHotSpot
.y
== ICON_HOTSPOT
) )
1630 iconinfo
->fIcon
= TRUE
;
1631 iconinfo
->xHotspot
= ciconinfo
->nWidth
/ 2;
1632 iconinfo
->yHotspot
= ciconinfo
->nHeight
/ 2;
1636 iconinfo
->fIcon
= FALSE
;
1637 iconinfo
->xHotspot
= ciconinfo
->ptHotSpot
.x
;
1638 iconinfo
->yHotspot
= ciconinfo
->ptHotSpot
.y
;
1641 iconinfo
->hbmColor
= CreateBitmap ( ciconinfo
->nWidth
, ciconinfo
->nHeight
,
1642 ciconinfo
->bPlanes
, ciconinfo
->bBitsPerPixel
,
1643 (char *)(ciconinfo
+ 1)
1644 + ciconinfo
->nHeight
*
1645 get_bitmap_width_bytes (ciconinfo
->nWidth
,1) );
1646 iconinfo
->hbmMask
= CreateBitmap ( ciconinfo
->nWidth
, ciconinfo
->nHeight
,
1647 1, 1, (char *)(ciconinfo
+ 1));
1649 GlobalUnlock16(HICON_16(hIcon
));
1654 /**********************************************************************
1655 * CreateIconIndirect (USER32.@)
1657 HICON WINAPI
CreateIconIndirect(PICONINFO iconinfo
)
1659 BITMAP bmpXor
,bmpAnd
;
1661 int sizeXor
,sizeAnd
;
1663 GetObjectA( iconinfo
->hbmColor
, sizeof(bmpXor
), &bmpXor
);
1664 GetObjectA( iconinfo
->hbmMask
, sizeof(bmpAnd
), &bmpAnd
);
1666 sizeXor
= bmpXor
.bmHeight
* bmpXor
.bmWidthBytes
;
1667 sizeAnd
= bmpAnd
.bmHeight
* bmpAnd
.bmWidthBytes
;
1669 hObj
= GlobalAlloc16( GMEM_MOVEABLE
,
1670 sizeof(CURSORICONINFO
) + sizeXor
+ sizeAnd
);
1673 CURSORICONINFO
*info
;
1675 info
= (CURSORICONINFO
*)GlobalLock16( hObj
);
1677 /* If we are creating an icon, the hotspot is unused */
1678 if (iconinfo
->fIcon
)
1680 info
->ptHotSpot
.x
= ICON_HOTSPOT
;
1681 info
->ptHotSpot
.y
= ICON_HOTSPOT
;
1685 info
->ptHotSpot
.x
= iconinfo
->xHotspot
;
1686 info
->ptHotSpot
.y
= iconinfo
->yHotspot
;
1689 info
->nWidth
= bmpXor
.bmWidth
;
1690 info
->nHeight
= bmpXor
.bmHeight
;
1691 info
->nWidthBytes
= bmpXor
.bmWidthBytes
;
1692 info
->bPlanes
= bmpXor
.bmPlanes
;
1693 info
->bBitsPerPixel
= bmpXor
.bmBitsPixel
;
1695 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1697 GetBitmapBits( iconinfo
->hbmMask
,sizeAnd
,(char*)(info
+ 1) );
1698 GetBitmapBits( iconinfo
->hbmColor
,sizeXor
,(char*)(info
+ 1) +sizeAnd
);
1699 GlobalUnlock16( hObj
);
1701 return HICON_32(hObj
);
1704 /******************************************************************************
1705 * DrawIconEx (USER32.@) Draws an icon or cursor on device context
1708 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1711 * hdc [I] Handle to device context
1712 * x0 [I] X coordinate of upper left corner
1713 * y0 [I] Y coordinate of upper left corner
1714 * hIcon [I] Handle to icon to draw
1715 * cxWidth [I] Width of icon
1716 * cyWidth [I] Height of icon
1717 * istep [I] Index of frame in animated cursor
1718 * hbr [I] Handle to background brush
1719 * flags [I] Icon-drawing flags
1725 BOOL WINAPI
DrawIconEx( HDC hdc
, INT x0
, INT y0
, HICON hIcon
,
1726 INT cxWidth
, INT cyWidth
, UINT istep
,
1727 HBRUSH hbr
, UINT flags
)
1729 CURSORICONINFO
*ptr
= (CURSORICONINFO
*)GlobalLock16(HICON_16(hIcon
));
1730 HDC hDC_off
= 0, hMemDC
;
1731 BOOL result
= FALSE
, DoOffscreen
;
1732 HBITMAP hB_off
= 0, hOld
= 0;
1734 if (!ptr
) return FALSE
;
1735 TRACE_(icon
)("(hdc=%x,pos=%d.%d,hicon=%x,extend=%d.%d,istep=%d,br=%x,flags=0x%08x)\n",
1736 hdc
,x0
,y0
,hIcon
,cxWidth
,cyWidth
,istep
,hbr
,flags
1739 hMemDC
= CreateCompatibleDC (hdc
);
1741 FIXME_(icon
)("Ignoring istep=%d\n", istep
);
1742 if (flags
& DI_COMPAT
)
1743 FIXME_(icon
)("Ignoring flag DI_COMPAT\n");
1746 FIXME_(icon
)("no flags set? setting to DI_NORMAL\n");
1750 /* Calculate the size of the destination image. */
1753 if (flags
& DI_DEFAULTSIZE
)
1754 cxWidth
= GetSystemMetrics (SM_CXICON
);
1756 cxWidth
= ptr
->nWidth
;
1760 if (flags
& DI_DEFAULTSIZE
)
1761 cyWidth
= GetSystemMetrics (SM_CYICON
);
1763 cyWidth
= ptr
->nHeight
;
1766 DoOffscreen
= (GetObjectType( hbr
) == OBJ_BRUSH
);
1776 hDC_off
= CreateCompatibleDC(hdc
);
1777 hB_off
= CreateCompatibleBitmap(hdc
, cxWidth
, cyWidth
);
1778 if (hDC_off
&& hB_off
) {
1779 hOld
= SelectObject(hDC_off
, hB_off
);
1780 FillRect(hDC_off
, &r
, hbr
);
1784 if (hMemDC
&& (!DoOffscreen
|| (hDC_off
&& hB_off
)))
1786 HBITMAP hXorBits
, hAndBits
;
1787 COLORREF oldFg
, oldBg
;
1790 nStretchMode
= SetStretchBltMode (hdc
, STRETCH_DELETESCANS
);
1792 hXorBits
= CreateBitmap ( ptr
->nWidth
, ptr
->nHeight
,
1793 ptr
->bPlanes
, ptr
->bBitsPerPixel
,
1796 get_bitmap_width_bytes(ptr
->nWidth
,1) );
1797 hAndBits
= CreateBitmap ( ptr
->nWidth
, ptr
->nHeight
,
1798 1, 1, (char *)(ptr
+1) );
1799 oldFg
= SetTextColor( hdc
, RGB(0,0,0) );
1800 oldBg
= SetBkColor( hdc
, RGB(255,255,255) );
1802 if (hXorBits
&& hAndBits
)
1804 HBITMAP hBitTemp
= SelectObject( hMemDC
, hAndBits
);
1805 if (flags
& DI_MASK
)
1808 StretchBlt (hDC_off
, 0, 0, cxWidth
, cyWidth
,
1809 hMemDC
, 0, 0, ptr
->nWidth
, ptr
->nHeight
, SRCAND
);
1811 StretchBlt (hdc
, x0
, y0
, cxWidth
, cyWidth
,
1812 hMemDC
, 0, 0, ptr
->nWidth
, ptr
->nHeight
, SRCAND
);
1814 SelectObject( hMemDC
, hXorBits
);
1815 if (flags
& DI_IMAGE
)
1818 StretchBlt (hDC_off
, 0, 0, cxWidth
, cyWidth
,
1819 hMemDC
, 0, 0, ptr
->nWidth
, ptr
->nHeight
, SRCPAINT
);
1821 StretchBlt (hdc
, x0
, y0
, cxWidth
, cyWidth
,
1822 hMemDC
, 0, 0, ptr
->nWidth
, ptr
->nHeight
, SRCPAINT
);
1824 SelectObject( hMemDC
, hBitTemp
);
1828 SetTextColor( hdc
, oldFg
);
1829 SetBkColor( hdc
, oldBg
);
1830 if (hXorBits
) DeleteObject( hXorBits
);
1831 if (hAndBits
) DeleteObject( hAndBits
);
1832 SetStretchBltMode (hdc
, nStretchMode
);
1834 BitBlt(hdc
, x0
, y0
, cxWidth
, cyWidth
, hDC_off
, 0, 0, SRCCOPY
);
1835 SelectObject(hDC_off
, hOld
);
1838 if (hMemDC
) DeleteDC( hMemDC
);
1839 if (hDC_off
) DeleteDC(hDC_off
);
1840 if (hB_off
) DeleteObject(hB_off
);
1841 GlobalUnlock16(HICON_16(hIcon
));
1845 /***********************************************************************
1846 * DIB_FixColorsToLoadflags
1848 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
1851 static void DIB_FixColorsToLoadflags(BITMAPINFO
* bmi
, UINT loadflags
, BYTE pix
)
1854 COLORREF c_W
, c_S
, c_F
, c_L
, c_C
;
1858 if (bmi
->bmiHeader
.biBitCount
> 8) return;
1859 if (bmi
->bmiHeader
.biSize
== sizeof(BITMAPINFOHEADER
)) incr
= 4;
1860 else if (bmi
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
)) incr
= 3;
1862 WARN_(resource
)("Wrong bitmap header size!\n");
1865 colors
= bmi
->bmiHeader
.biClrUsed
;
1866 if (!colors
&& (bmi
->bmiHeader
.biBitCount
<= 8))
1867 colors
= 1 << bmi
->bmiHeader
.biBitCount
;
1868 c_W
= GetSysColor(COLOR_WINDOW
);
1869 c_S
= GetSysColor(COLOR_3DSHADOW
);
1870 c_F
= GetSysColor(COLOR_3DFACE
);
1871 c_L
= GetSysColor(COLOR_3DLIGHT
);
1872 if (loadflags
& LR_LOADTRANSPARENT
) {
1873 switch (bmi
->bmiHeader
.biBitCount
) {
1874 case 1: pix
= pix
>> 7; break;
1875 case 4: pix
= pix
>> 4; break;
1878 WARN_(resource
)("(%d): Unsupported depth\n", bmi
->bmiHeader
.biBitCount
);
1881 if (pix
>= colors
) {
1882 WARN_(resource
)("pixel has color index greater than biClrUsed!\n");
1885 if (loadflags
& LR_LOADMAP3DCOLORS
) c_W
= c_F
;
1886 ptr
= (RGBQUAD
*)((char*)bmi
->bmiColors
+pix
*incr
);
1887 ptr
->rgbBlue
= GetBValue(c_W
);
1888 ptr
->rgbGreen
= GetGValue(c_W
);
1889 ptr
->rgbRed
= GetRValue(c_W
);
1891 if (loadflags
& LR_LOADMAP3DCOLORS
)
1892 for (i
=0; i
<colors
; i
++) {
1893 ptr
= (RGBQUAD
*)((char*)bmi
->bmiColors
+i
*incr
);
1894 c_C
= RGB(ptr
->rgbRed
, ptr
->rgbGreen
, ptr
->rgbBlue
);
1895 if (c_C
== RGB(128, 128, 128)) {
1896 ptr
->rgbRed
= GetRValue(c_S
);
1897 ptr
->rgbGreen
= GetGValue(c_S
);
1898 ptr
->rgbBlue
= GetBValue(c_S
);
1899 } else if (c_C
== RGB(192, 192, 192)) {
1900 ptr
->rgbRed
= GetRValue(c_F
);
1901 ptr
->rgbGreen
= GetGValue(c_F
);
1902 ptr
->rgbBlue
= GetBValue(c_F
);
1903 } else if (c_C
== RGB(223, 223, 223)) {
1904 ptr
->rgbRed
= GetRValue(c_L
);
1905 ptr
->rgbGreen
= GetGValue(c_L
);
1906 ptr
->rgbBlue
= GetBValue(c_L
);
1912 /**********************************************************************
1915 static HBITMAP
BITMAP_Load( HINSTANCE instance
,LPCWSTR name
, UINT loadflags
)
1917 HBITMAP hbitmap
= 0;
1921 BITMAPINFO
*info
, *fix_info
=NULL
;
1925 if (!(loadflags
& LR_LOADFROMFILE
))
1929 /* OEM bitmap: try to load the resource from user32.dll */
1930 if (HIWORD(name
)) return 0;
1931 if (!(instance
= GetModuleHandleA("user32.dll"))) return 0;
1933 if (!(hRsrc
= FindResourceW( instance
, name
, RT_BITMAPW
))) return 0;
1934 if (!(handle
= LoadResource( instance
, hRsrc
))) return 0;
1936 if ((info
= (BITMAPINFO
*)LockResource( handle
)) == NULL
) return 0;
1940 if (!(ptr
= map_fileW( name
))) return 0;
1941 info
= (BITMAPINFO
*)(ptr
+ sizeof(BITMAPFILEHEADER
));
1943 size
= DIB_BitmapInfoSize(info
, DIB_RGB_COLORS
);
1944 if ((hFix
= GlobalAlloc(0, size
))) fix_info
=GlobalLock(hFix
);
1948 memcpy(fix_info
, info
, size
);
1949 pix
= *((LPBYTE
)info
+DIB_BitmapInfoSize(info
, DIB_RGB_COLORS
));
1950 DIB_FixColorsToLoadflags(fix_info
, loadflags
, pix
);
1951 if (!screen_dc
) screen_dc
= CreateDCA( "DISPLAY", NULL
, NULL
, NULL
);
1954 char *bits
= (char *)info
+ size
;
1955 if (loadflags
& LR_CREATEDIBSECTION
) {
1957 hbitmap
= CreateDIBSection(screen_dc
, fix_info
, DIB_RGB_COLORS
, NULL
, 0, 0);
1958 GetObjectA(hbitmap
, sizeof(DIBSECTION
), &dib
);
1959 SetDIBits(screen_dc
, hbitmap
, 0, dib
.dsBm
.bmHeight
, bits
, info
,
1963 hbitmap
= CreateDIBitmap( screen_dc
, &fix_info
->bmiHeader
, CBM_INIT
,
1964 bits
, fix_info
, DIB_RGB_COLORS
);
1970 if (loadflags
& LR_LOADFROMFILE
) UnmapViewOfFile( ptr
);
1974 /**********************************************************************
1975 * LoadImageA (USER32.@)
1977 * FIXME: implementation lacks some features, see LR_ defines in winuser.h
1980 /* filter for page-fault exceptions */
1981 static WINE_EXCEPTION_FILTER(page_fault
)
1983 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
)
1984 return EXCEPTION_EXECUTE_HANDLER
;
1985 return EXCEPTION_CONTINUE_SEARCH
;
1988 /*********************************************************************/
1990 HANDLE WINAPI
LoadImageA( HINSTANCE hinst
, LPCSTR name
, UINT type
,
1991 INT desiredx
, INT desiredy
, UINT loadflags
)
1997 return LoadImageW(hinst
, (LPWSTR
)name
, type
, desiredx
, desiredy
, loadflags
);
2000 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, name
, -1, NULL
, 0 );
2001 u_name
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
2002 MultiByteToWideChar( CP_ACP
, 0, name
, -1, u_name
, len
);
2004 __EXCEPT(page_fault
) {
2005 SetLastError( ERROR_INVALID_PARAMETER
);
2009 res
= LoadImageW(hinst
, u_name
, type
, desiredx
, desiredy
, loadflags
);
2010 HeapFree(GetProcessHeap(), 0, u_name
);
2015 /******************************************************************************
2016 * LoadImageW (USER32.@) Loads an icon, cursor, or bitmap
2019 * hinst [I] Handle of instance that contains image
2020 * name [I] Name of image
2021 * type [I] Type of image
2022 * desiredx [I] Desired width
2023 * desiredy [I] Desired height
2024 * loadflags [I] Load flags
2027 * Success: Handle to newly loaded image
2030 * FIXME: Implementation lacks some features, see LR_ defines in winuser.h
2032 HANDLE WINAPI
LoadImageW( HINSTANCE hinst
, LPCWSTR name
, UINT type
,
2033 INT desiredx
, INT desiredy
, UINT loadflags
)
2036 TRACE_(resource
)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2037 hinst
,name
,type
,desiredx
,desiredy
,loadflags
);
2039 TRACE_(resource
)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2040 hinst
,name
,type
,desiredx
,desiredy
,loadflags
);
2042 if (loadflags
& LR_DEFAULTSIZE
) {
2043 if (type
== IMAGE_ICON
) {
2044 if (!desiredx
) desiredx
= GetSystemMetrics(SM_CXICON
);
2045 if (!desiredy
) desiredy
= GetSystemMetrics(SM_CYICON
);
2046 } else if (type
== IMAGE_CURSOR
) {
2047 if (!desiredx
) desiredx
= GetSystemMetrics(SM_CXCURSOR
);
2048 if (!desiredy
) desiredy
= GetSystemMetrics(SM_CYCURSOR
);
2051 if (loadflags
& LR_LOADFROMFILE
) loadflags
&= ~LR_SHARED
;
2054 return BITMAP_Load( hinst
, name
, loadflags
);
2057 if (!screen_dc
) screen_dc
= CreateDCW( DISPLAYW
, NULL
, NULL
, NULL
);
2060 UINT palEnts
= GetSystemPaletteEntries(screen_dc
, 0, 0, NULL
);
2061 if (palEnts
== 0) palEnts
= 256;
2062 return CURSORICON_Load(hinst
, name
, desiredx
, desiredy
,
2063 palEnts
, FALSE
, loadflags
);
2068 return CURSORICON_Load(hinst
, name
, desiredx
, desiredy
,
2069 1, TRUE
, loadflags
);
2074 /******************************************************************************
2075 * CopyImage (USER32.@) Creates new image and copies attributes to it
2078 * hnd [I] Handle to image to copy
2079 * type [I] Type of image to copy
2080 * desiredx [I] Desired width of new image
2081 * desiredy [I] Desired height of new image
2082 * flags [I] Copy flags
2085 * Success: Handle to newly created image
2088 * FIXME: implementation still lacks nearly all features, see LR_*
2089 * defines in winuser.h
2091 HICON WINAPI
CopyImage( HANDLE hnd
, UINT type
, INT desiredx
,
2092 INT desiredy
, UINT flags
)
2101 if (!GetObjectW( hnd
, sizeof(bm
), &bm
)) return 0;
2103 if ((res
= CreateBitmapIndirect(&bm
)))
2105 char *buf
= HeapAlloc( GetProcessHeap(), 0, bm
.bmWidthBytes
* bm
.bmHeight
);
2106 GetBitmapBits( hnd
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
2107 SetBitmapBits( res
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
2108 HeapFree( GetProcessHeap(), 0, buf
);
2113 return CURSORICON_ExtCopy(hnd
,type
, desiredx
, desiredy
, flags
);
2115 /* Should call CURSORICON_ExtCopy but more testing
2116 * needs to be done before we change this
2118 return CopyCursor(hnd
);
2124 /******************************************************************************
2125 * LoadBitmapW (USER32.@) Loads bitmap from the executable file
2128 * Success: Handle to specified bitmap
2131 HBITMAP WINAPI
LoadBitmapW(
2132 HINSTANCE instance
, /* [in] Handle to application instance */
2133 LPCWSTR name
) /* [in] Address of bitmap resource name */
2135 return LoadImageW( instance
, name
, IMAGE_BITMAP
, 0, 0, 0 );
2138 /**********************************************************************
2139 * LoadBitmapA (USER32.@)
2141 HBITMAP WINAPI
LoadBitmapA( HINSTANCE instance
, LPCSTR name
)
2143 return LoadImageA( instance
, name
, IMAGE_BITMAP
, 0, 0, 0 );