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 ?!
51 #include "wine/winbase16.h"
52 #include "wine/winuser16.h"
53 #include "wine/exception.h"
56 #include "cursoricon.h"
58 #include "wine/debug.h"
63 #include "msvcrt/excpt.h"
65 WINE_DECLARE_DEBUG_CHANNEL(cursor);
66 WINE_DECLARE_DEBUG_CHANNEL(icon);
67 WINE_DECLARE_DEBUG_CHANNEL(resource);
69 static HCURSOR hActiveCursor = 0; /* Active cursor */
70 static INT CURSOR_ShowCount = 0; /* Cursor display count */
71 static RECT CURSOR_ClipRect; /* Cursor clipping rect */
75 /**********************************************************************
76 * ICONCACHE for cursors/icons loaded with LR_SHARED.
78 * FIXME: This should not be allocated on the system heap, but on a
79 * subsystem-global heap (i.e. one for all Win16 processes,
80 * and one for each Win32 process).
82 typedef struct tagICONCACHE
84 struct tagICONCACHE *next;
95 static ICONCACHE *IconAnchor = NULL;
96 static CRITICAL_SECTION IconCrst = CRITICAL_SECTION_INIT("IconCrst");
97 static WORD ICON_HOTSPOT = 0x4242;
100 /***********************************************************************
103 * Helper function to map a file to memory:
105 * [RETURN] ptr - pointer to mapped file
107 static void *map_fileW( LPCWSTR name )
109 HANDLE hFile, hMapping;
112 hFile = CreateFileW( name, GENERIC_READ, FILE_SHARE_READ, NULL,
113 OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0 );
114 if (hFile != INVALID_HANDLE_VALUE)
116 hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
117 CloseHandle( hFile );
120 ptr = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
121 CloseHandle( hMapping );
128 /**********************************************************************
129 * CURSORICON_FindSharedIcon
131 static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
136 EnterCriticalSection( &IconCrst );
138 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
139 if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
142 handle = ptr->handle;
146 LeaveCriticalSection( &IconCrst );
151 /*************************************************************************
152 * CURSORICON_FindCache
154 * Given a handle, find the corresponding cache element
157 * Handle [I] handle to an Image
160 * Success: The cache entry
164 static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
167 ICONCACHE *pRet=NULL;
168 BOOL IsFound = FALSE;
171 EnterCriticalSection( &IconCrst );
173 for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
175 if ( handle == ptr->handle )
182 LeaveCriticalSection( &IconCrst );
187 /**********************************************************************
188 * CURSORICON_AddSharedIcon
190 static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
192 ICONCACHE *ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(ICONCACHE) );
195 ptr->hModule = hModule;
197 ptr->handle = handle;
198 ptr->hGroupRsrc = hGroupRsrc;
201 EnterCriticalSection( &IconCrst );
202 ptr->next = IconAnchor;
204 LeaveCriticalSection( &IconCrst );
207 /**********************************************************************
208 * CURSORICON_DelSharedIcon
210 static INT CURSORICON_DelSharedIcon( HANDLE handle )
215 EnterCriticalSection( &IconCrst );
217 for ( ptr = IconAnchor; ptr; ptr = ptr->next )
218 if ( ptr->handle == handle )
220 if ( ptr->count > 0 ) ptr->count--;
225 LeaveCriticalSection( &IconCrst );
230 /**********************************************************************
231 * CURSORICON_FreeModuleIcons
233 void CURSORICON_FreeModuleIcons( HMODULE hModule )
235 ICONCACHE **ptr = &IconAnchor;
237 if ( HIWORD( hModule ) )
238 hModule = MapHModuleLS( hModule );
240 hModule = GetExePtr( hModule );
242 EnterCriticalSection( &IconCrst );
246 if ( (*ptr)->hModule == hModule )
248 ICONCACHE *freePtr = *ptr;
249 *ptr = freePtr->next;
251 GlobalFree16( freePtr->handle );
252 HeapFree( GetProcessHeap(), 0, freePtr );
258 LeaveCriticalSection( &IconCrst );
261 /**********************************************************************
262 * CURSORICON_FindBestIcon
264 * Find the icon closest to the requested size and number of colors.
266 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
267 int height, int colors )
270 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
271 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
272 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
274 if (dir->idCount < 1)
276 WARN_(icon)("Empty directory!\n" );
279 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
282 iTotalDiff = 0xFFFFFFFF;
283 iColorDiff = 0xFFFFFFFF;
284 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
286 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
287 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
289 if(iTotalDiff > (iTempXDiff + iTempYDiff))
293 iTotalDiff = iXDiff + iYDiff;
297 /* Find Best Colors for Best Fit */
298 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
300 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
301 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
303 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
304 if(iColorDiff > iTempColorDiff)
307 iColorDiff = iTempColorDiff;
316 /**********************************************************************
317 * CURSORICON_FindBestCursor
319 * Find the cursor closest to the requested size.
320 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
323 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
324 int width, int height, int color)
326 int i, maxwidth, maxheight;
327 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
329 if (dir->idCount < 1)
331 WARN_(cursor)("Empty directory!\n" );
334 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
336 /* Double height to account for AND and XOR masks */
340 /* First find the largest one smaller than or equal to the requested size*/
342 maxwidth = maxheight = 0;
343 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
344 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
345 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
346 (entry->wBitCount == 1))
349 maxwidth = entry->ResInfo.cursor.wWidth;
350 maxheight = entry->ResInfo.cursor.wHeight;
352 if (bestEntry) return bestEntry;
354 /* Now find the smallest one larger than the requested size */
356 maxwidth = maxheight = 255;
357 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
358 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
359 (entry->wBitCount == 1))
362 maxwidth = entry->ResInfo.cursor.wWidth;
363 maxheight = entry->ResInfo.cursor.wHeight;
369 /*********************************************************************
370 * The main purpose of this function is to create fake resource directory
371 * and fake resource entries. There are several reasons for this:
372 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
374 * There are some "bad" cursor files which do not have
375 * bColorCount initialized but instead one must read this info
376 * directly from corresponding DIB sections
377 * Note: wResId is index to array of pointer returned in ptrs (origin is 1)
379 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor,
380 CURSORICONDIR **res, LPBYTE **ptr)
383 CURSORICONFILEDIR *bits;
384 int entries, size, i;
388 if (!(bits = map_fileW( filename ))) return FALSE;
390 /* FIXME: test for inimated icons
391 * hack to load the first icon from the *.ani file
393 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */
394 { LPBYTE pos = (LPBYTE) bits;
395 FIXME_(cursor)("Animated icons not correctly implemented! %p \n", bits);
398 { if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */
399 { FIXME_(cursor)("icon entry found! %p\n", bits);
401 if ( !*(LPWORD) pos==0x2fe) /* iconsize */
404 bits=(CURSORICONFILEDIR*)(pos+4);
405 FIXME_(cursor)("icon size ok. offset=%p \n", bits);
409 if (pos>=(LPBYTE)bits+766) goto fail;
412 if (!(entries = bits->idCount)) goto fail;
413 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1);
414 _free = (LPBYTE) size;
416 for (i=0; i < entries; i++)
417 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
419 if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
420 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
421 if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
423 _free = (LPBYTE)(*res) + (int)_free;
424 memcpy((*res), bits, 6);
425 for (i=0; i<entries; i++)
427 ((LPBYTE*)(*ptr))[i] = _free;
429 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth;
430 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight;
431 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
432 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
433 _free+=sizeof(POINT16);
435 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth;
436 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight;
437 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount;
439 (*res)->idEntries[i].wPlanes=1;
440 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
441 bits->idEntries[i].dwDIBOffset))->biBitCount;
442 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize;
443 (*res)->idEntries[i].wResId=i+1;
445 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
446 (*res)->idEntries[i].dwBytesInRes);
447 _free += (*res)->idEntries[i].dwBytesInRes;
449 UnmapViewOfFile( bits );
452 if (*res) HeapFree( GetProcessHeap(), 0, *res );
453 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
454 UnmapViewOfFile( bits );
459 /**********************************************************************
460 * CURSORICON_CreateFromResource
462 * Create a cursor or icon from in-memory resource template.
464 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
465 * with cbSize parameter as well.
467 static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
468 UINT cbSize, BOOL bIcon, DWORD dwVersion,
469 INT width, INT height, UINT loadflags )
472 int sizeAnd, sizeXor;
473 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
474 BITMAP bmpXor, bmpAnd;
480 hotspot.x = ICON_HOTSPOT;
481 hotspot.y = ICON_HOTSPOT;
483 TRACE_(cursor)("%08x (%u bytes), ver %08x, %ix%i %s %s\n",
484 (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
485 bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
486 if (dwVersion == 0x00020000)
488 FIXME_(cursor)("\t2.xx resources are not supported\n");
493 bmi = (BITMAPINFO *)bits;
494 else /* get the hotspot */
496 POINT16 *pt = (POINT16 *)bits;
498 bmi = (BITMAPINFO *)(pt + 1);
500 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
502 if (!width) width = bmi->bmiHeader.biWidth;
503 if (!height) height = bmi->bmiHeader.biHeight/2;
504 DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
505 (bmi->bmiHeader.biWidth != width);
507 /* Check bitmap header */
509 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
510 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
511 bmi->bmiHeader.biCompression != BI_RGB) )
513 WARN_(cursor)("\tinvalid resource bitmap header.\n");
517 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
522 /* Make sure we have room for the monochrome bitmap later on.
523 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
524 * up to and including the biBitCount. In-memory icon resource
525 * format is as follows:
527 * BITMAPINFOHEADER icHeader // DIB header
528 * RGBQUAD icColors[] // Color table
529 * BYTE icXOR[] // DIB bits for XOR mask
530 * BYTE icAND[] // DIB bits for AND mask
533 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
534 max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
536 memcpy( pInfo, bmi, size );
537 pInfo->bmiHeader.biHeight /= 2;
539 /* Create the XOR bitmap */
544 hXorBits = CreateCompatibleBitmap(screen_dc, width, height);
548 hXorBits = CreateBitmap(width, height, 1, 1, NULL);
555 if (!hdcMem) hdcMem = CreateCompatibleDC(screen_dc);
557 hOld = SelectObject(hdcMem, hXorBits);
558 res = StretchDIBits(hdcMem, 0, 0, width, height, 0, 0,
559 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
560 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
561 SelectObject(hdcMem, hOld);
563 if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
565 } else hXorBits = CreateDIBitmap( screen_dc, &pInfo->bmiHeader,
566 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
569 char* xbits = (char *)bmi + size +
570 DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
571 bmi->bmiHeader.biHeight,
572 bmi->bmiHeader.biBitCount) / 2;
574 pInfo->bmiHeader.biBitCount = 1;
575 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
577 RGBQUAD *rgb = pInfo->bmiColors;
579 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2;
580 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
581 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
582 rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
586 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1);
588 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
589 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
592 /* Create the AND bitmap */
595 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) {
599 if (!hdcMem) hdcMem = CreateCompatibleDC(screen_dc);
601 hOld = SelectObject(hdcMem, hAndBits);
602 res = StretchDIBits(hdcMem, 0, 0, width, height, 0, 0,
603 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
604 xbits, pInfo, DIB_RGB_COLORS, SRCCOPY);
605 SelectObject(hdcMem, hOld);
607 if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
609 } else hAndBits = CreateDIBitmap( screen_dc, &pInfo->bmiHeader,
610 CBM_INIT, xbits, pInfo, DIB_RGB_COLORS );
612 if( !hAndBits ) DeleteObject( hXorBits );
614 HeapFree( GetProcessHeap(), 0, pInfo );
618 if( !hXorBits || !hAndBits )
620 WARN_(cursor)("\tunable to create an icon bitmap.\n");
624 /* Now create the CURSORICONINFO structure */
625 GetObjectA( hXorBits, sizeof(bmpXor), &bmpXor );
626 GetObjectA( hAndBits, sizeof(bmpAnd), &bmpAnd );
627 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
628 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
630 if (hObj) hObj = GlobalReAlloc16( hObj,
631 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE );
632 if (!hObj) hObj = GlobalAlloc16( GMEM_MOVEABLE,
633 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
636 CURSORICONINFO *info;
638 /* Make it owned by the module */
639 if (hInstance) hInstance = GetExePtr(hInstance);
640 FarSetOwner16( hObj, hInstance );
642 info = (CURSORICONINFO *)GlobalLock16( hObj );
643 info->ptHotSpot.x = hotspot.x;
644 info->ptHotSpot.y = hotspot.y;
645 info->nWidth = bmpXor.bmWidth;
646 info->nHeight = bmpXor.bmHeight;
647 info->nWidthBytes = bmpXor.bmWidthBytes;
648 info->bPlanes = bmpXor.bmPlanes;
649 info->bBitsPerPixel = bmpXor.bmBitsPixel;
651 /* Transfer the bitmap bits to the CURSORICONINFO structure */
653 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
654 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
655 GlobalUnlock16( hObj );
658 DeleteObject( hAndBits );
659 DeleteObject( hXorBits );
664 /**********************************************************************
665 * CreateIconFromResourceEx (USER.450)
667 * FIXME: not sure about exact parameter types
669 HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
670 DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
672 return CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
673 width, height, cFlag);
677 /**********************************************************************
678 * CreateIconFromResource (USER32.@)
680 HICON WINAPI CreateIconFromResource( LPBYTE bits, UINT cbSize,
681 BOOL bIcon, DWORD dwVersion)
683 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0);
687 /**********************************************************************
688 * CreateIconFromResourceEx (USER32.@)
690 HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
691 BOOL bIcon, DWORD dwVersion,
692 INT width, INT height,
695 return CURSORICON_CreateFromResource( 0, 0, bits, cbSize, bIcon, dwVersion,
696 width, height, cFlag );
699 /**********************************************************************
702 * Load a cursor or icon from resource or file.
704 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
705 INT width, INT height, INT colors,
706 BOOL fCursor, UINT loadflags )
708 HANDLE handle = 0, h = 0;
711 CURSORICONDIRENTRY *dirEntry;
714 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */
717 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
720 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
722 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
723 bits = ptr[dirEntry->wResId-1];
724 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes,
725 !fCursor, 0x00030000, width, height, loadflags);
726 HeapFree( GetProcessHeap(), 0, dir );
727 HeapFree( GetProcessHeap(), 0, ptr );
729 else /* Load from resource */
735 if (!hInstance) /* Load OEM cursor/icon */
737 if (!(hInstance = GetModuleHandleA( "user32.dll" ))) return 0;
740 /* Normalize hInstance (must be uniquely represented for icon cache) */
742 if ( HIWORD( hInstance ) )
743 hInstance = MapHModuleLS( hInstance );
745 hInstance = GetExePtr( hInstance );
747 /* Get directory resource ID */
749 if (!(hRsrc = FindResourceW( hInstance, name,
750 fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
754 /* Find the best entry in the directory */
756 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
757 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
759 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
762 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
763 width, height, colors );
764 if (!dirEntry) return 0;
765 wResId = dirEntry->wResId;
766 dwBytesInRes = dirEntry->dwBytesInRes;
767 FreeResource( handle );
769 /* Load the resource */
771 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId),
772 fCursor ? RT_CURSORW : RT_ICONW ))) return 0;
774 /* If shared icon, check whether it was already loaded */
775 if ( (loadflags & LR_SHARED)
776 && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
779 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
780 bits = (LPBYTE)LockResource( handle );
781 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes,
782 !fCursor, 0x00030000, width, height, loadflags);
783 FreeResource( handle );
785 /* If shared icon, add to icon cache */
787 if ( h && (loadflags & LR_SHARED) )
788 CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
794 /***********************************************************************
797 * Make a copy of a cursor or icon.
799 static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
801 char *ptrOld, *ptrNew;
805 if (!(ptrOld = (char *)GlobalLock16( handle ))) return 0;
806 if (hInstance && !(hInstance = GetExePtr( hInstance ))) return 0;
807 size = GlobalSize16( handle );
808 hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
809 FarSetOwner16( hNew, hInstance );
810 ptrNew = (char *)GlobalLock16( hNew );
811 memcpy( ptrNew, ptrOld, size );
812 GlobalUnlock16( handle );
813 GlobalUnlock16( hNew );
817 /*************************************************************************
820 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
823 * Handle [I] handle to an Image
824 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
825 * iDesiredCX [I] The Desired width of the Image
826 * iDesiredCY [I] The desired height of the Image
827 * nFlags [I] The flags from CopyImage
830 * Success: The new handle of the Image
833 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
834 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
835 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
840 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
841 INT iDesiredCX, INT iDesiredCY,
846 TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
847 Handle, nType, iDesiredCX, iDesiredCY, nFlags);
854 /* Best Fit or Monochrome */
855 if( (nFlags & LR_COPYFROMRESOURCE
856 && (iDesiredCX > 0 || iDesiredCY > 0))
857 || nFlags & LR_MONOCHROME)
859 ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
861 /* Not Found in Cache, then do a straight copy
863 if(pIconCache == NULL)
865 hNew = CURSORICON_Copy(0, Handle);
866 if(nFlags & LR_COPYFROMRESOURCE)
868 TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
873 int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
880 CURSORICONDIRENTRY *pDirEntry;
881 BOOL bIsIcon = (nType == IMAGE_ICON);
883 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
885 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
886 || (iDesiredCX == 0 && iDesiredCY == 0))
888 iDesiredCY = GetSystemMetrics(bIsIcon ?
889 SM_CYICON : SM_CYCURSOR);
890 iDesiredCX = GetSystemMetrics(bIsIcon ?
891 SM_CXICON : SM_CXCURSOR);
894 /* Retrieve the CURSORICONDIRENTRY
896 if (!(hMem = LoadResource( pIconCache->hModule ,
897 pIconCache->hGroupRsrc)))
901 if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
910 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
911 pDir, iDesiredCX, iDesiredCY, 256);
915 pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
916 pDir, iDesiredCX, iDesiredCY, 1);
919 wResId = pDirEntry->wResId;
920 dwBytesInRes = pDirEntry->dwBytesInRes;
923 TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
924 wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
925 pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
929 if (!(hRsrc = FindResourceW(pIconCache->hModule ,
930 MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
934 if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
939 pBits = (LPBYTE)LockResource( hMem );
941 if(nFlags & LR_DEFAULTSIZE)
943 iTargetCY = GetSystemMetrics(SM_CYICON);
944 iTargetCX = GetSystemMetrics(SM_CXICON);
947 /* Create a New Icon with the proper dimension
949 hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
950 bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
954 else hNew = CURSORICON_Copy(0, Handle);
958 /***********************************************************************
959 * CURSORICON_IconToCursor
961 * Converts bitmap to mono and truncates if icon is too large (should
962 * probably do StretchBlt() instead).
964 HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL bSemiTransparent)
967 CURSORICONINFO *pIcon = NULL;
970 if (!(pIcon = (CURSORICONINFO*)GlobalLock16( hIcon ))) return FALSE;
971 if (pIcon->bPlanes * pIcon->bBitsPerPixel == 1)
973 hRet = CURSORICON_Copy( 0, hIcon );
976 pIcon = GlobalLock16(hRet);
978 pIcon->ptHotSpot.x = pIcon->ptHotSpot.y = 15;
980 GlobalUnlock16(hRet);
986 int maxx, maxy, ix, iy, bpp = pIcon->bBitsPerPixel;
987 BYTE* psPtr, *pxbPtr = pXorBits;
988 unsigned xor_width, and_width, val_base = 0xffffffff >> (32 - bpp);
993 TRACE_(icon)("[%04x] %ix%i %ibpp (bogus %ibps)\n",
994 hIcon, pIcon->nWidth, pIcon->nHeight, pIcon->bBitsPerPixel, pIcon->nWidthBytes );
996 xor_width = BITMAP_GetWidthBytes( pIcon->nWidth, bpp );
997 and_width = BITMAP_GetWidthBytes( pIcon->nWidth, 1 );
998 psPtr = (BYTE *)(pIcon + 1) + pIcon->nHeight * and_width;
1000 memset(pXorBits, 0, 128);
1001 cI.bBitsPerPixel = 1; cI.bPlanes = 1;
1002 cI.ptHotSpot.x = cI.ptHotSpot.y = 15;
1003 cI.nWidth = 32; cI.nHeight = 32;
1004 cI.nWidthBytes = 4; /* 32x1bpp */
1006 maxx = (pIcon->nWidth > 32) ? 32 : pIcon->nWidth;
1007 maxy = (pIcon->nHeight > 32) ? 32 : pIcon->nHeight;
1009 for( iy = 0; iy < maxy; iy++ )
1011 unsigned shift = iy % 2;
1013 memcpy( pAndBits + iy * 4, (BYTE *)(pIcon + 1) + iy * and_width,
1014 (and_width > 4) ? 4 : and_width );
1015 for( ix = 0; ix < maxx; ix++ )
1017 if( bSemiTransparent && ((ix+shift)%2) )
1019 /* set AND bit, XOR bit stays 0 */
1021 pbc = pAndBits + iy * 4 + ix/8;
1022 *pbc |= 0x80 >> (ix%8);
1026 /* keep AND bit, set XOR bit */
1028 unsigned *psc = (unsigned*)(psPtr + (ix * bpp)/8);
1029 unsigned val = ((*psc) >> (ix * bpp)%8) & val_base;
1030 if(!PALETTE_Driver->pIsDark(val))
1032 pbc = pxbPtr + ix/8;
1033 *pbc |= 0x80 >> (ix%8);
1041 hRet = CreateCursorIconIndirect16( 0 , &cI, pAndBits, pXorBits);
1043 if( !hRet ) /* fall back on default drag cursor */
1044 hRet = CURSORICON_Copy( 0 ,
1045 CURSORICON_Load(0,MAKEINTRESOURCEW(OCR_DRAGOBJECT),
1046 GetSystemMetrics(SM_CXCURSOR),
1047 GetSystemMetrics(SM_CYCURSOR), 1, TRUE, 0) );
1054 /***********************************************************************
1055 * LoadCursor (USER.173)
1057 HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, LPCSTR name )
1059 return LoadCursorA( hInstance, name );
1063 /***********************************************************************
1064 * LoadIcon (USER.174)
1066 HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, LPCSTR name )
1068 return LoadIconA( hInstance, name );
1072 /***********************************************************************
1073 * CreateCursor (USER.406)
1075 HCURSOR16 WINAPI CreateCursor16( HINSTANCE16 hInstance,
1076 INT16 xHotSpot, INT16 yHotSpot,
1077 INT16 nWidth, INT16 nHeight,
1078 LPCVOID lpANDbits, LPCVOID lpXORbits )
1080 CURSORICONINFO info;
1082 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1083 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1085 info.ptHotSpot.x = xHotSpot;
1086 info.ptHotSpot.y = yHotSpot;
1087 info.nWidth = nWidth;
1088 info.nHeight = nHeight;
1089 info.nWidthBytes = 0;
1091 info.bBitsPerPixel = 1;
1093 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1097 /***********************************************************************
1098 * CreateCursor (USER32.@)
1100 HCURSOR WINAPI CreateCursor( HINSTANCE hInstance,
1101 INT xHotSpot, INT yHotSpot,
1102 INT nWidth, INT nHeight,
1103 LPCVOID lpANDbits, LPCVOID lpXORbits )
1105 CURSORICONINFO info;
1107 TRACE_(cursor)("%dx%d spot=%d,%d xor=%p and=%p\n",
1108 nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits);
1110 info.ptHotSpot.x = xHotSpot;
1111 info.ptHotSpot.y = yHotSpot;
1112 info.nWidth = nWidth;
1113 info.nHeight = nHeight;
1114 info.nWidthBytes = 0;
1116 info.bBitsPerPixel = 1;
1118 return CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1122 /***********************************************************************
1123 * CreateIcon (USER.407)
1125 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
1126 INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
1127 LPCVOID lpANDbits, LPCVOID lpXORbits )
1129 CURSORICONINFO info;
1131 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1132 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1134 info.ptHotSpot.x = ICON_HOTSPOT;
1135 info.ptHotSpot.y = ICON_HOTSPOT;
1136 info.nWidth = nWidth;
1137 info.nHeight = nHeight;
1138 info.nWidthBytes = 0;
1139 info.bPlanes = bPlanes;
1140 info.bBitsPerPixel = bBitsPixel;
1142 return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
1146 /***********************************************************************
1147 * CreateIcon (USER32.@)
1149 * Creates an icon based on the specified bitmaps. The bitmaps must be
1150 * provided in a device dependent format and will be resized to
1151 * (SM_CXICON,SM_CYICON) and depth converted to match the screen's color
1152 * depth. The provided bitmaps must be top-down bitmaps.
1153 * Although Windows does not support 15bpp(*) this API must support it
1154 * for Winelib applications.
1156 * (*) Windows does not support 15bpp but it supports the 555 RGB 16bpp
1161 * - The provided bitmaps are not resized!
1162 * - The documentation says the lpXORbits bitmap must be in a device
1163 * dependent format. But we must still resize it and perform depth
1164 * conversions if necessary.
1165 * - I'm a bit unsure about the how the 'device dependent format' thing works.
1166 * I did some tests on windows and found that if you provide a 16bpp bitmap
1167 * in lpXORbits, then its format but be 565 RGB if the screen's bit depth
1168 * is 16bpp but it must be 555 RGB if the screen's bit depth is anything
1169 * else. I don't know if this is part of the GDI specs or if this is a
1170 * quirk of the graphics card driver.
1171 * - You may think that we check whether the bit depths match or not
1172 * as an optimization. But the truth is that the conversion using
1173 * CreateDIBitmap does not work for some bit depth (e.g. 8bpp) and I have
1175 * - I'm pretty sure that all the things we do in CreateIcon should
1176 * also be done in CreateIconIndirect...
1178 HICON WINAPI CreateIcon(
1179 HINSTANCE hInstance, /* [in] the application's hInstance, currently unused */
1180 INT nWidth, /* [in] the width of the provided bitmaps */
1181 INT nHeight, /* [in] the height of the provided bitmaps */
1182 BYTE bPlanes, /* [in] the number of planes in the provided bitmaps */
1183 BYTE bBitsPixel, /* [in] the number of bits per pixel of the lpXORbits bitmap */
1184 LPCVOID lpANDbits, /* [in] a monochrome bitmap representing the icon's mask */
1185 LPCVOID lpXORbits) /* [in] the icon's 'color' bitmap */
1190 TRACE_(icon)("%dx%dx%d, xor=%p, and=%p\n",
1191 nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits);
1197 if (GetDeviceCaps(hdc,BITSPIXEL)==bBitsPixel) {
1198 CURSORICONINFO info;
1200 info.ptHotSpot.x = ICON_HOTSPOT;
1201 info.ptHotSpot.y = ICON_HOTSPOT;
1202 info.nWidth = nWidth;
1203 info.nHeight = nHeight;
1204 info.nWidthBytes = 0;
1205 info.bPlanes = bPlanes;
1206 info.bBitsPerPixel = bBitsPixel;
1208 hIcon=CreateCursorIconIndirect16( 0, &info, lpANDbits, lpXORbits );
1214 iinfo.xHotspot=ICON_HOTSPOT;
1215 iinfo.yHotspot=ICON_HOTSPOT;
1216 iinfo.hbmMask=CreateBitmap(nWidth,nHeight,1,1,lpANDbits);
1218 bmi.bmiHeader.biSize=sizeof(bmi.bmiHeader);
1219 bmi.bmiHeader.biWidth=nWidth;
1220 bmi.bmiHeader.biHeight=-nHeight;
1221 bmi.bmiHeader.biPlanes=bPlanes;
1222 bmi.bmiHeader.biBitCount=bBitsPixel;
1223 bmi.bmiHeader.biCompression=BI_RGB;
1224 bmi.bmiHeader.biSizeImage=0;
1225 bmi.bmiHeader.biXPelsPerMeter=0;
1226 bmi.bmiHeader.biYPelsPerMeter=0;
1227 bmi.bmiHeader.biClrUsed=0;
1228 bmi.bmiHeader.biClrImportant=0;
1230 iinfo.hbmColor = CreateDIBitmap( hdc, &bmi.bmiHeader,
1231 CBM_INIT, lpXORbits,
1232 &bmi, DIB_RGB_COLORS );
1234 hIcon=CreateIconIndirect(&iinfo);
1235 DeleteObject(iinfo.hbmMask);
1236 DeleteObject(iinfo.hbmColor);
1243 /***********************************************************************
1244 * CreateCursorIconIndirect (USER.408)
1246 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
1247 CURSORICONINFO *info,
1253 int sizeAnd, sizeXor;
1255 hInstance = GetExePtr( hInstance ); /* Make it a module handle */
1256 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
1257 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel);
1258 sizeXor = info->nHeight * info->nWidthBytes;
1259 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1260 if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
1261 sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
1263 FarSetOwner16( handle, hInstance );
1264 ptr = (char *)GlobalLock16( handle );
1265 memcpy( ptr, info, sizeof(*info) );
1266 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
1267 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
1268 GlobalUnlock16( handle );
1273 /***********************************************************************
1274 * CopyIcon (USER.368)
1276 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1278 TRACE_(icon)("%04x %04x\n", hInstance, hIcon );
1279 return CURSORICON_Copy( hInstance, hIcon );
1283 /***********************************************************************
1284 * CopyIcon (USER32.@)
1286 HICON WINAPI CopyIcon( HICON hIcon )
1288 TRACE_(icon)("%04x\n", hIcon );
1289 return CURSORICON_Copy( 0, hIcon );
1293 /***********************************************************************
1294 * CopyCursor (USER.369)
1296 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1298 TRACE_(cursor)("%04x %04x\n", hInstance, hCursor );
1299 return CURSORICON_Copy( hInstance, hCursor );
1302 /**********************************************************************
1303 * DestroyIcon32 (USER.610)
1304 * DestroyIcon32 (USER32.@)
1306 * This routine is actually exported from Win95 USER under the name
1307 * DestroyIcon32 ... The behaviour implemented here should mimic
1308 * the Win95 one exactly, especially the return values, which
1309 * depend on the setting of various flags.
1311 WORD WINAPI DestroyIcon32( HGLOBAL16 handle, UINT16 flags )
1315 TRACE_(icon)("(%04x, %04x)\n", handle, flags );
1317 /* Check whether destroying active cursor */
1319 if ( hActiveCursor == handle )
1321 WARN_(cursor)("Destroying active cursor!\n" );
1325 /* Try shared cursor/icon first */
1327 if ( !(flags & CID_NONSHARED) )
1329 INT count = CURSORICON_DelSharedIcon( handle );
1332 return (flags & CID_WIN32)? TRUE : (count == 0);
1334 /* FIXME: OEM cursors/icons should be recognized */
1337 /* Now assume non-shared cursor/icon */
1339 retv = GlobalFree16( handle );
1340 return (flags & CID_RESOURCE)? retv : TRUE;
1343 /***********************************************************************
1344 * DestroyIcon (USER.457)
1346 BOOL16 WINAPI DestroyIcon16( HICON16 hIcon )
1348 return DestroyIcon32( hIcon, 0 );
1351 /***********************************************************************
1352 * DestroyIcon (USER32.@)
1354 BOOL WINAPI DestroyIcon( HICON hIcon )
1356 return DestroyIcon32( hIcon, CID_WIN32 );
1359 /***********************************************************************
1360 * DestroyCursor (USER.458)
1362 BOOL16 WINAPI DestroyCursor16( HCURSOR16 hCursor )
1364 return DestroyIcon32( hCursor, 0 );
1367 /***********************************************************************
1368 * DestroyCursor (USER32.@)
1370 BOOL WINAPI DestroyCursor( HCURSOR hCursor )
1372 return DestroyIcon32( hCursor, CID_WIN32 );
1376 /***********************************************************************
1377 * DrawIcon (USER.84)
1379 BOOL16 WINAPI DrawIcon16( HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon )
1381 return DrawIcon( hdc, x, y, hIcon );
1385 /***********************************************************************
1386 * DrawIcon (USER32.@)
1388 BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
1390 CURSORICONINFO *ptr;
1392 HBITMAP hXorBits, hAndBits;
1393 COLORREF oldFg, oldBg;
1395 if (!(ptr = (CURSORICONINFO *)GlobalLock16( hIcon ))) return FALSE;
1396 if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
1397 hAndBits = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1,
1399 hXorBits = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes,
1400 ptr->bBitsPerPixel, (char *)(ptr + 1)
1401 + ptr->nHeight * BITMAP_GetWidthBytes(ptr->nWidth,1) );
1402 oldFg = SetTextColor( hdc, RGB(0,0,0) );
1403 oldBg = SetBkColor( hdc, RGB(255,255,255) );
1405 if (hXorBits && hAndBits)
1407 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
1408 BitBlt( hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0, SRCAND );
1409 SelectObject( hMemDC, hXorBits );
1410 BitBlt(hdc, x, y, ptr->nWidth, ptr->nHeight, hMemDC, 0, 0,SRCINVERT);
1411 SelectObject( hMemDC, hBitTemp );
1414 if (hXorBits) DeleteObject( hXorBits );
1415 if (hAndBits) DeleteObject( hAndBits );
1416 GlobalUnlock16( hIcon );
1417 SetTextColor( hdc, oldFg );
1418 SetBkColor( hdc, oldBg );
1423 /***********************************************************************
1424 * IconSize (USER.86)
1426 * See "Undocumented Windows". Used by W2.0 paint.exe.
1428 DWORD WINAPI IconSize16( void )
1430 return MAKELONG(GetSystemMetrics(SM_CYICON), GetSystemMetrics(SM_CXICON));
1434 /***********************************************************************
1435 * DumpIcon (USER.459)
1437 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
1438 SEGPTR *lpXorBits, SEGPTR *lpAndBits )
1440 CURSORICONINFO *info = MapSL( pInfo );
1441 int sizeAnd, sizeXor;
1443 if (!info) return 0;
1444 sizeXor = info->nHeight * info->nWidthBytes;
1445 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 );
1446 if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
1447 if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
1448 if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
1449 return MAKELONG( sizeXor, sizeXor );
1453 /***********************************************************************
1454 * SetCursor (USER.69)
1456 HCURSOR16 WINAPI SetCursor16( HCURSOR16 hCursor )
1458 return (HCURSOR16)SetCursor( hCursor );
1462 /***********************************************************************
1463 * SetCursor (USER32.@)
1465 * A handle to the previous cursor shape.
1467 HCURSOR WINAPI SetCursor(
1468 HCURSOR hCursor /* [in] Handle of cursor to show */
1472 if (hCursor == hActiveCursor) return hActiveCursor; /* No change */
1473 TRACE_(cursor)("%04x\n", hCursor );
1474 hOldCursor = hActiveCursor;
1475 hActiveCursor = hCursor;
1476 /* Change the cursor shape only if it is visible */
1477 if (CURSOR_ShowCount >= 0)
1479 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1480 GlobalUnlock16( hActiveCursor );
1486 /***********************************************************************
1487 * ShowCursor (USER.71)
1489 INT16 WINAPI ShowCursor16( BOOL16 bShow )
1491 return ShowCursor( bShow );
1495 /***********************************************************************
1496 * ShowCursor (USER32.@)
1498 INT WINAPI ShowCursor( BOOL bShow )
1500 TRACE_(cursor)("%d, count=%d\n",
1501 bShow, CURSOR_ShowCount );
1505 if (++CURSOR_ShowCount == 0) /* Show it */
1507 USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16( hActiveCursor ) );
1508 GlobalUnlock16( hActiveCursor );
1513 if (--CURSOR_ShowCount == -1) /* Hide it */
1514 USER_Driver.pSetCursor( NULL );
1516 return CURSOR_ShowCount;
1520 /***********************************************************************
1521 * GetCursor (USER.247)
1523 HCURSOR16 WINAPI GetCursor16(void)
1525 return hActiveCursor;
1529 /***********************************************************************
1530 * GetCursor (USER32.@)
1532 HCURSOR WINAPI GetCursor(void)
1534 return hActiveCursor;
1538 /***********************************************************************
1539 * ClipCursor (USER.16)
1541 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
1543 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1544 else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
1549 /***********************************************************************
1550 * ClipCursor (USER32.@)
1552 BOOL WINAPI ClipCursor( const RECT *rect )
1554 if (!rect) SetRectEmpty( &CURSOR_ClipRect );
1555 else CopyRect( &CURSOR_ClipRect, rect );
1560 /***********************************************************************
1561 * GetClipCursor (USER.309)
1563 void WINAPI GetClipCursor16( RECT16 *rect )
1565 if (rect) CONV_RECT32TO16( &CURSOR_ClipRect, rect );
1569 /***********************************************************************
1570 * GetClipCursor (USER32.@)
1572 BOOL WINAPI GetClipCursor( RECT *rect )
1576 CopyRect( rect, &CURSOR_ClipRect );
1582 /**********************************************************************
1583 * LookupIconIdFromDirectoryEx (USER.364)
1585 * FIXME: exact parameter sizes
1587 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
1588 INT16 width, INT16 height, UINT16 cFlag )
1590 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
1592 if( dir && !dir->idReserved && (dir->idType & 3) )
1594 CURSORICONDIRENTRY* entry;
1599 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
1602 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
1607 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
1609 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
1611 if( entry ) retVal = entry->wResId;
1613 else WARN_(cursor)("invalid resource directory\n");
1617 /**********************************************************************
1618 * LookupIconIdFromDirectoryEx (USER32.@)
1620 INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE dir, BOOL bIcon,
1621 INT width, INT height, UINT cFlag )
1623 return LookupIconIdFromDirectoryEx16( dir, bIcon, width, height, cFlag );
1626 /**********************************************************************
1627 * LookupIconIdFromDirectory (USER.?)
1629 INT16 WINAPI LookupIconIdFromDirectory16( LPBYTE dir, BOOL16 bIcon )
1631 return LookupIconIdFromDirectoryEx16( dir, bIcon,
1632 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1633 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1636 /**********************************************************************
1637 * LookupIconIdFromDirectory (USER32.@)
1639 INT WINAPI LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
1641 return LookupIconIdFromDirectoryEx( dir, bIcon,
1642 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
1643 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
1646 /**********************************************************************
1647 * GetIconID (USER.455)
1649 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
1651 LPBYTE lpDir = (LPBYTE)GlobalLock16(hResource);
1653 TRACE_(cursor)("hRes=%04x, entries=%i\n",
1654 hResource, lpDir ? ((CURSORICONDIR*)lpDir)->idCount : 0);
1659 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, FALSE,
1660 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1662 return (WORD)LookupIconIdFromDirectoryEx16( lpDir, TRUE,
1663 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 );
1665 WARN_(cursor)("invalid res type %ld\n", resType );
1670 /**********************************************************************
1671 * LoadCursorIconHandler (USER.336)
1673 * Supposed to load resources of Windows 2.x applications.
1675 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1677 FIXME_(cursor)("(%04x,%04x,%04x): old 2.x resources are not supported!\n",
1678 hResource, hModule, hRsrc);
1679 return (HGLOBAL16)0;
1682 /**********************************************************************
1683 * LoadDIBIconHandler (USER.357)
1685 * RT_ICON resource loader, installed by USER_SignalProc when module
1688 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1690 /* If hResource is zero we must allocate a new memory block, if it's
1691 * non-zero but GlobalLock() returns NULL then it was discarded and
1692 * we have to recommit some memory, otherwise we just need to check
1693 * the block size. See LoadProc() in 16-bit SDK for more.
1696 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1699 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1700 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1701 SizeofResource16(hModule, hRsrc), TRUE, 0x00030000,
1702 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR );
1707 /**********************************************************************
1708 * LoadDIBCursorHandler (USER.356)
1710 * RT_CURSOR resource loader. Same as above.
1712 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1714 hMemObj = NE_DefResourceHandler( hMemObj, hModule, hRsrc );
1717 LPBYTE bits = (LPBYTE)GlobalLock16( hMemObj );
1718 hMemObj = CURSORICON_CreateFromResource( hModule, hMemObj, bits,
1719 SizeofResource16(hModule, hRsrc), FALSE, 0x00030000,
1720 GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
1725 /**********************************************************************
1726 * LoadIconHandler (USER.456)
1728 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
1730 LPBYTE bits = (LPBYTE)LockResource16( hResource );
1732 TRACE_(cursor)("hRes=%04x\n",hResource);
1734 return CURSORICON_CreateFromResource( 0, 0, bits, 0, TRUE,
1735 bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
1738 /***********************************************************************
1739 * LoadCursorW (USER32.@)
1741 HCURSOR WINAPI LoadCursorW(HINSTANCE hInstance, LPCWSTR name)
1743 return LoadImageW( hInstance, name, IMAGE_CURSOR, 0, 0,
1744 LR_SHARED | LR_DEFAULTSIZE );
1747 /***********************************************************************
1748 * LoadCursorA (USER32.@)
1750 HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR name)
1752 return LoadImageA( hInstance, name, IMAGE_CURSOR, 0, 0,
1753 LR_SHARED | LR_DEFAULTSIZE );
1756 /***********************************************************************
1757 * LoadCursorFromFileW (USER32.@)
1759 HCURSOR WINAPI LoadCursorFromFileW (LPCWSTR name)
1761 return LoadImageW( 0, name, IMAGE_CURSOR, 0, 0,
1762 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1765 /***********************************************************************
1766 * LoadCursorFromFileA (USER32.@)
1768 HCURSOR WINAPI LoadCursorFromFileA (LPCSTR name)
1770 return LoadImageA( 0, name, IMAGE_CURSOR, 0, 0,
1771 LR_LOADFROMFILE | LR_DEFAULTSIZE );
1774 /***********************************************************************
1775 * LoadIconW (USER32.@)
1777 HICON WINAPI LoadIconW(HINSTANCE hInstance, LPCWSTR name)
1779 return LoadImageW( hInstance, name, IMAGE_ICON, 0, 0,
1780 LR_SHARED | LR_DEFAULTSIZE );
1783 /***********************************************************************
1784 * LoadIconA (USER32.@)
1786 HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name)
1788 return LoadImageA( hInstance, name, IMAGE_ICON, 0, 0,
1789 LR_SHARED | LR_DEFAULTSIZE );
1792 /**********************************************************************
1793 * GetIconInfo (USER.395)
1795 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon,LPICONINFO16 iconinfo)
1798 BOOL16 ret = GetIconInfo((HICON)hIcon, &ii32);
1800 iconinfo->fIcon = ii32.fIcon;
1801 iconinfo->xHotspot = ii32.xHotspot;
1802 iconinfo->yHotspot = ii32.yHotspot;
1803 iconinfo->hbmMask = ii32.hbmMask;
1804 iconinfo->hbmColor = ii32.hbmColor;
1808 /**********************************************************************
1809 * GetIconInfo (USER32.@)
1811 BOOL WINAPI GetIconInfo(HICON hIcon,PICONINFO iconinfo) {
1812 CURSORICONINFO *ciconinfo;
1814 ciconinfo = GlobalLock16(hIcon);
1818 if ( (ciconinfo->ptHotSpot.x == ICON_HOTSPOT) &&
1819 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT) )
1821 iconinfo->fIcon = TRUE;
1822 iconinfo->xHotspot = ciconinfo->nWidth / 2;
1823 iconinfo->yHotspot = ciconinfo->nHeight / 2;
1827 iconinfo->fIcon = FALSE;
1828 iconinfo->xHotspot = ciconinfo->ptHotSpot.x;
1829 iconinfo->yHotspot = ciconinfo->ptHotSpot.y;
1832 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1833 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel,
1834 (char *)(ciconinfo + 1)
1835 + ciconinfo->nHeight *
1836 BITMAP_GetWidthBytes (ciconinfo->nWidth,1) );
1837 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight,
1838 1, 1, (char *)(ciconinfo + 1));
1840 GlobalUnlock16(hIcon);
1845 /**********************************************************************
1846 * CreateIconIndirect (USER32.@)
1848 HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
1850 BITMAP bmpXor,bmpAnd;
1852 int sizeXor,sizeAnd;
1854 GetObjectA( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
1855 GetObjectA( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd );
1857 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
1858 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
1860 hObj = GlobalAlloc16( GMEM_MOVEABLE,
1861 sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
1864 CURSORICONINFO *info;
1866 info = (CURSORICONINFO *)GlobalLock16( hObj );
1868 /* If we are creating an icon, the hotspot is unused */
1869 if (iconinfo->fIcon)
1871 info->ptHotSpot.x = ICON_HOTSPOT;
1872 info->ptHotSpot.y = ICON_HOTSPOT;
1876 info->ptHotSpot.x = iconinfo->xHotspot;
1877 info->ptHotSpot.y = iconinfo->yHotspot;
1880 info->nWidth = bmpXor.bmWidth;
1881 info->nHeight = bmpXor.bmHeight;
1882 info->nWidthBytes = bmpXor.bmWidthBytes;
1883 info->bPlanes = bmpXor.bmPlanes;
1884 info->bBitsPerPixel = bmpXor.bmBitsPixel;
1886 /* Transfer the bitmap bits to the CURSORICONINFO structure */
1888 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
1889 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd);
1890 GlobalUnlock16( hObj );
1896 /**********************************************************************
1897 * DrawIconEx (USER.394)
1899 BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1900 INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1901 HBRUSH16 hbr, UINT16 flags)
1903 return DrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
1908 /******************************************************************************
1909 * DrawIconEx (USER32.@) Draws an icon or cursor on device context
1912 * Why is this using SM_CXICON instead of SM_CXCURSOR?
1915 * hdc [I] Handle to device context
1916 * x0 [I] X coordinate of upper left corner
1917 * y0 [I] Y coordinate of upper left corner
1918 * hIcon [I] Handle to icon to draw
1919 * cxWidth [I] Width of icon
1920 * cyWidth [I] Height of icon
1921 * istep [I] Index of frame in animated cursor
1922 * hbr [I] Handle to background brush
1923 * flags [I] Icon-drawing flags
1929 BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
1930 INT cxWidth, INT cyWidth, UINT istep,
1931 HBRUSH hbr, UINT flags )
1933 CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
1934 HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
1935 BOOL result = FALSE, DoOffscreen;
1936 HBITMAP hB_off = 0, hOld = 0;
1938 if (!ptr) return FALSE;
1939 TRACE_(icon)("(hdc=%x,pos=%d.%d,hicon=%x,extend=%d.%d,istep=%d,br=%x,flags=0x%08x)\n",
1940 hdc,x0,y0,hIcon,cxWidth,cyWidth,istep,hbr,flags
1944 FIXME_(icon)("Ignoring istep=%d\n", istep);
1945 if (flags & DI_COMPAT)
1946 FIXME_(icon)("Ignoring flag DI_COMPAT\n");
1949 FIXME_(icon)("no flags set? setting to DI_NORMAL\n");
1953 /* Calculate the size of the destination image. */
1956 if (flags & DI_DEFAULTSIZE)
1957 cxWidth = GetSystemMetrics (SM_CXICON);
1959 cxWidth = ptr->nWidth;
1963 if (flags & DI_DEFAULTSIZE)
1964 cyWidth = GetSystemMetrics (SM_CYICON);
1966 cyWidth = ptr->nHeight;
1969 DoOffscreen = (GetObjectType( hbr ) == OBJ_BRUSH);
1979 hDC_off = CreateCompatibleDC(hdc);
1980 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
1981 if (hDC_off && hB_off) {
1982 hOld = SelectObject(hDC_off, hB_off);
1983 FillRect(hDC_off, &r, hbr);
1987 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
1989 HBITMAP hXorBits, hAndBits;
1990 COLORREF oldFg, oldBg;
1993 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
1995 hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
1996 ptr->bPlanes, ptr->bBitsPerPixel,
1999 BITMAP_GetWidthBytes(ptr->nWidth,1) );
2000 hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
2001 1, 1, (char *)(ptr+1) );
2002 oldFg = SetTextColor( hdc, RGB(0,0,0) );
2003 oldBg = SetBkColor( hdc, RGB(255,255,255) );
2005 if (hXorBits && hAndBits)
2007 HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
2008 if (flags & DI_MASK)
2011 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
2012 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
2014 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
2015 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
2017 SelectObject( hMemDC, hXorBits );
2018 if (flags & DI_IMAGE)
2021 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
2022 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
2024 StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
2025 hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
2027 SelectObject( hMemDC, hBitTemp );
2031 SetTextColor( hdc, oldFg );
2032 SetBkColor( hdc, oldBg );
2033 if (hXorBits) DeleteObject( hXorBits );
2034 if (hAndBits) DeleteObject( hAndBits );
2035 SetStretchBltMode (hdc, nStretchMode);
2037 BitBlt(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
2038 SelectObject(hDC_off, hOld);
2041 if (hMemDC) DeleteDC( hMemDC );
2042 if (hDC_off) DeleteDC(hDC_off);
2043 if (hB_off) DeleteObject(hB_off);
2044 GlobalUnlock16( hIcon );
2048 /***********************************************************************
2049 * DIB_FixColorsToLoadflags
2051 * Change color table entries when LR_LOADTRANSPARENT or LR_LOADMAP3DCOLORS
2054 static void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix)
2057 COLORREF c_W, c_S, c_F, c_L, c_C;
2061 if (bmi->bmiHeader.biBitCount > 8) return;
2062 if (bmi->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) incr = 4;
2063 else if (bmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) incr = 3;
2065 WARN_(resource)("Wrong bitmap header size!\n");
2068 colors = bmi->bmiHeader.biClrUsed;
2069 if (!colors && (bmi->bmiHeader.biBitCount <= 8))
2070 colors = 1 << bmi->bmiHeader.biBitCount;
2071 c_W = GetSysColor(COLOR_WINDOW);
2072 c_S = GetSysColor(COLOR_3DSHADOW);
2073 c_F = GetSysColor(COLOR_3DFACE);
2074 c_L = GetSysColor(COLOR_3DLIGHT);
2075 if (loadflags & LR_LOADTRANSPARENT) {
2076 switch (bmi->bmiHeader.biBitCount) {
2077 case 1: pix = pix >> 7; break;
2078 case 4: pix = pix >> 4; break;
2081 WARN_(resource)("(%d): Unsupported depth\n", bmi->bmiHeader.biBitCount);
2084 if (pix >= colors) {
2085 WARN_(resource)("pixel has color index greater than biClrUsed!\n");
2088 if (loadflags & LR_LOADMAP3DCOLORS) c_W = c_F;
2089 ptr = (RGBQUAD*)((char*)bmi->bmiColors+pix*incr);
2090 ptr->rgbBlue = GetBValue(c_W);
2091 ptr->rgbGreen = GetGValue(c_W);
2092 ptr->rgbRed = GetRValue(c_W);
2094 if (loadflags & LR_LOADMAP3DCOLORS)
2095 for (i=0; i<colors; i++) {
2096 ptr = (RGBQUAD*)((char*)bmi->bmiColors+i*incr);
2097 c_C = RGB(ptr->rgbRed, ptr->rgbGreen, ptr->rgbBlue);
2098 if (c_C == RGB(128, 128, 128)) {
2099 ptr->rgbRed = GetRValue(c_S);
2100 ptr->rgbGreen = GetGValue(c_S);
2101 ptr->rgbBlue = GetBValue(c_S);
2102 } else if (c_C == RGB(192, 192, 192)) {
2103 ptr->rgbRed = GetRValue(c_F);
2104 ptr->rgbGreen = GetGValue(c_F);
2105 ptr->rgbBlue = GetBValue(c_F);
2106 } else if (c_C == RGB(223, 223, 223)) {
2107 ptr->rgbRed = GetRValue(c_L);
2108 ptr->rgbGreen = GetGValue(c_L);
2109 ptr->rgbBlue = GetBValue(c_L);
2115 /**********************************************************************
2118 static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
2120 HBITMAP hbitmap = 0;
2124 BITMAPINFO *info, *fix_info=NULL;
2128 if (!(loadflags & LR_LOADFROMFILE))
2132 /* OEM bitmap: try to load the resource from user32.dll */
2133 if (HIWORD(name)) return 0;
2134 if (!(instance = GetModuleHandleA("user32.dll"))) return 0;
2136 if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
2137 if (!(handle = LoadResource( instance, hRsrc ))) return 0;
2139 if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
2143 if (!(ptr = map_fileW( name ))) return 0;
2144 info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
2146 size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
2147 if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
2151 memcpy(fix_info, info, size);
2152 pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
2153 DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
2154 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
2157 char *bits = (char *)info + size;
2158 if (loadflags & LR_CREATEDIBSECTION) {
2160 hbitmap = CreateDIBSection(screen_dc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
2161 GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
2162 SetDIBits(screen_dc, hbitmap, 0, dib.dsBm.bmHeight, bits, info,
2166 hbitmap = CreateDIBitmap( screen_dc, &fix_info->bmiHeader, CBM_INIT,
2167 bits, fix_info, DIB_RGB_COLORS );
2173 if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
2178 /***********************************************************************
2179 * LoadImage (USER.389)
2182 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
2183 INT16 desiredx, INT16 desiredy, UINT16 loadflags)
2185 return LoadImageA( hinst, name, type, desiredx, desiredy, loadflags );
2188 /**********************************************************************
2189 * LoadImageA (USER32.@)
2191 * FIXME: implementation lacks some features, see LR_ defines in winuser.h
2194 /* filter for page-fault exceptions */
2195 static WINE_EXCEPTION_FILTER(page_fault)
2197 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
2198 return EXCEPTION_EXECUTE_HANDLER;
2199 return EXCEPTION_CONTINUE_SEARCH;
2202 /*********************************************************************/
2204 HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
2205 INT desiredx, INT desiredy, UINT loadflags)
2211 return LoadImageW(hinst, (LPWSTR)name, type, desiredx, desiredy, loadflags);
2214 DWORD len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
2215 u_name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
2216 MultiByteToWideChar( CP_ACP, 0, name, -1, u_name, len );
2218 __EXCEPT(page_fault) {
2219 SetLastError( ERROR_INVALID_PARAMETER );
2223 res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
2224 HeapFree(GetProcessHeap(), 0, u_name);
2229 /******************************************************************************
2230 * LoadImageW (USER32.@) Loads an icon, cursor, or bitmap
2233 * hinst [I] Handle of instance that contains image
2234 * name [I] Name of image
2235 * type [I] Type of image
2236 * desiredx [I] Desired width
2237 * desiredy [I] Desired height
2238 * loadflags [I] Load flags
2241 * Success: Handle to newly loaded image
2244 * FIXME: Implementation lacks some features, see LR_ defines in winuser.h
2246 HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
2247 INT desiredx, INT desiredy, UINT loadflags )
2250 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2251 hinst,name,type,desiredx,desiredy,loadflags);
2253 TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
2254 hinst,name,type,desiredx,desiredy,loadflags);
2256 if (loadflags & LR_DEFAULTSIZE) {
2257 if (type == IMAGE_ICON) {
2258 if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
2259 if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
2260 } else if (type == IMAGE_CURSOR) {
2261 if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
2262 if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
2265 if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
2268 return BITMAP_Load( hinst, name, loadflags );
2271 if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
2274 UINT palEnts = GetSystemPaletteEntries(screen_dc, 0, 0, NULL);
2275 if (palEnts == 0) palEnts = 256;
2276 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2277 palEnts, FALSE, loadflags);
2282 return CURSORICON_Load(hinst, name, desiredx, desiredy,
2283 1, TRUE, loadflags);
2289 /******************************************************************************
2290 * CopyImage (USER.390) Creates new image and copies attributes to it
2293 HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
2294 INT16 desiredy, UINT16 flags )
2296 return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
2297 (INT)desiredy, (UINT)flags);
2300 /******************************************************************************
2301 * CopyImage (USER32.@) Creates new image and copies attributes to it
2304 * hnd [I] Handle to image to copy
2305 * type [I] Type of image to copy
2306 * desiredx [I] Desired width of new image
2307 * desiredy [I] Desired height of new image
2308 * flags [I] Copy flags
2311 * Success: Handle to newly created image
2314 * FIXME: implementation still lacks nearly all features, see LR_*
2315 * defines in winuser.h
2317 HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
2318 INT desiredy, UINT flags )
2323 return BITMAP_CopyBitmap(hnd);
2325 return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
2327 /* Should call CURSORICON_ExtCopy but more testing
2328 * needs to be done before we change this
2330 return CopyCursor(hnd);
2336 /******************************************************************************
2337 * LoadBitmapW (USER32.@) Loads bitmap from the executable file
2340 * Success: Handle to specified bitmap
2343 HBITMAP WINAPI LoadBitmapW(
2344 HINSTANCE instance, /* [in] Handle to application instance */
2345 LPCWSTR name) /* [in] Address of bitmap resource name */
2347 return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2350 /**********************************************************************
2351 * LoadBitmapA (USER32.@)
2353 HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
2355 return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
2358 /**********************************************************************
2359 * LoadBitmap (USER.175)
2361 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, LPCSTR name )
2363 return LoadBitmapA( instance, name );