Implemented LoadCursorFromFile, fixed DrawIconEx to support offscreen

drawing, fixed CURSORICON_CreateFromResource to support LR_ semantics.
This commit is contained in:
Turchanov Sergey 1998-10-18 13:42:55 +00:00 committed by Alexandre Julliard
parent 07d7d7986f
commit 62d6e98152
2 changed files with 293 additions and 114 deletions

View File

@ -48,11 +48,35 @@ typedef struct
CURSORICONDIRENTRY idEntries[1] WINE_PACKED; CURSORICONDIRENTRY idEntries[1] WINE_PACKED;
} CURSORICONDIR; } CURSORICONDIR;
typedef struct {
BYTE bWidth;
BYTE bHeight;
BYTE bColorCount;
BYTE bReserved;
WORD xHotspot;
WORD yHotspot;
DWORD dwDIBSize;
DWORD dwDIBOffset;
} CURSORICONFILEDIRENTRY;
typedef struct
{
WORD idReserved;
WORD idType;
WORD idCount;
CURSORICONFILEDIRENTRY idEntries[1];
} CURSORICONFILEDIR;
#pragma pack(4) #pragma pack(4)
extern HCURSOR16 CURSORICON_IconToCursor( HICON16 hIcon, extern HCURSOR16 CURSORICON_IconToCursor( HICON16 hIcon,
BOOL32 bSemiTransparent ); BOOL32 bSemiTransparent );
extern HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name,
int width, int height, int colors,
BOOL32 fCursor, UINT32 loadflags);
extern Cursor CURSORICON_XCursor; /* Current X cursor */ extern Cursor CURSORICON_XCursor; /* Current X cursor */
#endif /* __WINE_CURSORICON_H */ #endif /* __WINE_CURSORICON_H */

View File

@ -4,6 +4,7 @@
* Copyright 1995 Alexandre Julliard * Copyright 1995 Alexandre Julliard
* 1996 Martin Von Loewis * 1996 Martin Von Loewis
* 1997 Alex Korobka * 1997 Alex Korobka
* 1998 Turchanov Sergey
*/ */
/* /*
@ -24,6 +25,8 @@
* the X client instead of in the server like other bitmaps; however, * the X client instead of in the server like other bitmaps; however,
* some programs (notably Paint Brush) expect to be able to manipulate * some programs (notably Paint Brush) expect to be able to manipulate
* the bits directly :-( * the bits directly :-(
*
* FIXME: what are we going to do with animation and color (bpp > 1) cursors ?!
*/ */
#include <string.h> #include <string.h>
@ -36,6 +39,7 @@
#include "callback.h" #include "callback.h"
#include "cursoricon.h" #include "cursoricon.h"
#include "sysmetrics.h" #include "sysmetrics.h"
#include "global.h"
#include "module.h" #include "module.h"
#include "win.h" #include "win.h"
#include "debug.h" #include "debug.h"
@ -159,9 +163,11 @@ static ICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
* CURSORICON_FindBestCursor * CURSORICON_FindBestCursor
* *
* Find the cursor closest to the requested size. * Find the cursor closest to the requested size.
* FIXME: parameter 'color' ignored and entries with more than 1 bpp
* ignored too
*/ */
static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir, static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
int width, int height ) int width, int height, int color)
{ {
int i, maxwidth, maxheight; int i, maxwidth, maxheight;
CURSORDIRENTRY *entry, *bestEntry = NULL; CURSORDIRENTRY *entry, *bestEntry = NULL;
@ -178,7 +184,8 @@ static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
maxwidth = maxheight = 0; maxwidth = maxheight = 0;
for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++) for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
if ((entry->wWidth <= width) && (entry->wHeight <= height) && if ((entry->wWidth <= width) && (entry->wHeight <= height) &&
(entry->wWidth > maxwidth) && (entry->wHeight > maxheight)) (entry->wWidth > maxwidth) && (entry->wHeight > maxheight) &&
(entry->wBitCount == 1))
{ {
bestEntry = entry; bestEntry = entry;
maxwidth = entry->wWidth; maxwidth = entry->wWidth;
@ -190,7 +197,8 @@ static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
maxwidth = maxheight = 255; maxwidth = maxheight = 255;
for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++) for(i = 0,entry = &dir->idEntries[0].cursor; i < dir->idCount; i++,entry++)
if ((entry->wWidth < maxwidth) && (entry->wHeight < maxheight)) if ((entry->wWidth < maxwidth) && (entry->wHeight < maxheight) &&
(entry->wBitCount == 1))
{ {
bestEntry = entry; bestEntry = entry;
maxwidth = entry->wWidth; maxwidth = entry->wWidth;
@ -200,6 +208,74 @@ static CURSORDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
return bestEntry; return bestEntry;
} }
/*********************************************************************
* The main purpose of this function is to create fake resource directory
* and fake resource entries. There are several reasons for this:
* - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their
* fields
* There are some "bad" cursor files which do not have
* bColorCount initialized but instead one must read this info
* directly from corresponding DIB sections
* Note: wResId is index to array of pointer returned in ptrs (origin is 1)
*/
BOOL32 CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL32 fCursor,
CURSORICONDIR **res, LPBYTE **ptr)
{
LPBYTE _free;
CURSORICONFILEDIR *bits;
int entries, size, i;
*res = NULL;
*ptr = NULL;
if (!(bits = (CURSORICONFILEDIR *)VIRTUAL_MapFileW( filename ))) return FALSE;
if (!(entries = bits->idCount)) goto fail;
(int)_free = size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) *
(entries - 1);
for (i=0; i < entries; i++)
size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0);
if (!(*ptr = HeapAlloc( GetProcessHeap(), 0,
entries * sizeof (CURSORICONDIRENTRY*)))) goto fail;
if (!(*res = HeapAlloc( GetProcessHeap(), 0, size))) goto fail;
_free = (LPBYTE)(*res) + (int)_free;
memcpy((*res), bits, 6);
for (i=0; i<entries; i++)
{
((LPBYTE*)(*ptr))[i] = _free;
if (fCursor) {
(*res)->idEntries[i].cursor.wWidth=bits->idEntries[i].bWidth;
(*res)->idEntries[i].cursor.wHeight=bits->idEntries[i].bHeight;
(*res)->idEntries[i].cursor.wPlanes=1;
(*res)->idEntries[i].cursor.wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits +
bits->idEntries[i].dwDIBOffset))->biBitCount;
(*res)->idEntries[i].cursor.dwBytesInRes = bits->idEntries[i].dwDIBSize;
(*res)->idEntries[i].cursor.wResId=i+1;
((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot;
((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot;
_free+=sizeof(POINT16);
} else {
(*res)->idEntries[i].icon.bWidth=bits->idEntries[i].bWidth;
(*res)->idEntries[i].icon.bHeight=bits->idEntries[i].bHeight;
(*res)->idEntries[i].icon.bColorCount = bits->idEntries[i].bColorCount;
(*res)->idEntries[i].icon.wPlanes=1;
(*res)->idEntries[i].icon.wBitCount= ((LPBITMAPINFOHEADER)((LPBYTE)bits +
bits->idEntries[i].dwDIBOffset))->biBitCount;
(*res)->idEntries[i].icon.dwBytesInRes = bits->idEntries[i].dwDIBSize;
(*res)->idEntries[i].icon.wResId=i+1;
}
memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset,
(*res)->idEntries[i].icon.dwBytesInRes);
_free += (*res)->idEntries[i].icon.dwBytesInRes;
}
UnmapViewOfFile( bits );
return TRUE;
fail:
if (*res) HeapFree( GetProcessHeap(), 0, *res );
if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr );
UnmapViewOfFile( bits );
return FALSE;
}
/********************************************************************** /**********************************************************************
* CURSORICON_LoadDirEntry16 * CURSORICON_LoadDirEntry16
@ -224,7 +300,7 @@ static BOOL32 CURSORICON_LoadDirEntry16( HINSTANCE32 hInstance, SEGPTR name,
{ {
if (fCursor) if (fCursor)
entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir, entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
width, height ); width, height, 1);
else else
entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir, entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
width, height, colors ); width, height, colors );
@ -258,7 +334,7 @@ static BOOL32 CURSORICON_LoadDirEntry32( HINSTANCE32 hInstance, LPCWSTR name,
{ {
if (fCursor) if (fCursor)
entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir, entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
width, height ); width, height, 1);
else else
entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir, entry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
width, height, colors ); width, height, colors );
@ -274,13 +350,12 @@ static BOOL32 CURSORICON_LoadDirEntry32( HINSTANCE32 hInstance, LPCWSTR name,
* *
* Create a cursor or icon from in-memory resource template. * Create a cursor or icon from in-memory resource template.
* *
* FIXME: Adjust icon size when width and height are nonzero (stretchblt). * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
* Convert to mono when cFlag is LR_MONOCHROME. Do something
* with cbSize parameter as well. * with cbSize parameter as well.
*/ */
static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits, static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16 hObj, LPBYTE bits,
UINT32 cbSize, BOOL32 bIcon, DWORD dwVersion, UINT32 cbSize, BOOL32 bIcon, DWORD dwVersion,
INT32 width, INT32 height, UINT32 cFlag ) INT32 width, INT32 height, UINT32 loadflags )
{ {
int sizeAnd, sizeXor; int sizeAnd, sizeXor;
HBITMAP32 hAndBits = 0, hXorBits = 0; /* error condition for later */ HBITMAP32 hAndBits = 0, hXorBits = 0; /* error condition for later */
@ -288,10 +363,12 @@ static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16
POINT16 hotspot = { 0 ,0 }; POINT16 hotspot = { 0 ,0 };
BITMAPINFO *bmi; BITMAPINFO *bmi;
HDC32 hdc; HDC32 hdc;
BOOL32 DoStretch;
INT32 size;
TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n", TRACE(cursor,"%08x (%u bytes), ver %08x, %ix%i %s %s\n",
(unsigned)bits, cbSize, (unsigned)dwVersion, width, height, (unsigned)bits, cbSize, (unsigned)dwVersion, width, height,
bIcon ? "icon" : "cursor", cFlag ? "mono" : "" ); bIcon ? "icon" : "cursor", (loadflags & LR_MONOCHROME) ? "mono" : "" );
if (dwVersion == 0x00020000) if (dwVersion == 0x00020000)
{ {
FIXME(cursor,"\t2.xx resources are not supported\n"); FIXME(cursor,"\t2.xx resources are not supported\n");
@ -306,6 +383,12 @@ static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16
hotspot = *pt; hotspot = *pt;
bmi = (BITMAPINFO *)(pt + 1); bmi = (BITMAPINFO *)(pt + 1);
} }
size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
if (!width) width = bmi->bmiHeader.biWidth;
if (!height) height = bmi->bmiHeader.biHeight/2;
DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
(bmi->bmiHeader.biWidth != width);
/* Check bitmap header */ /* Check bitmap header */
@ -320,7 +403,6 @@ static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16
if( (hdc = GetDC32( 0 )) ) if( (hdc = GetDC32( 0 )) )
{ {
BITMAPINFO* pInfo; BITMAPINFO* pInfo;
INT32 size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
/* Make sure we have room for the monochrome bitmap later on. /* Make sure we have room for the monochrome bitmap later on.
* Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same
@ -333,16 +415,32 @@ static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16
* BYTE icAND[] // DIB bits for AND mask * BYTE icAND[] // DIB bits for AND mask
*/ */
if( (pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0, if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0,
MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))) ) MAX(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD)))))
{ {
memcpy( pInfo, bmi, size ); memcpy( pInfo, bmi, size );
pInfo->bmiHeader.biHeight /= 2; pInfo->bmiHeader.biHeight /= 2;
/* Create the XOR bitmap */ /* Create the XOR bitmap */
hXorBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader, CBM_INIT, if (DoStretch) {
(char*)bmi + size, pInfo, DIB_RGB_COLORS ); if ((hXorBits = CreateCompatibleBitmap32(hdc, width, height))) {
HBITMAP32 hOld;
HDC32 hMem = CreateCompatibleDC32(hdc);
BOOL32 res;
if (hMem) {
hOld = SelectObject32(hMem, hXorBits);
res = StretchDIBits32(hMem, 0, 0, width, height, 0, 0,
bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2,
(char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY);
SelectObject32(hMem, hOld);
DeleteDC32(hMem);
} else res = FALSE;
if (!res) { DeleteObject32(hXorBits); hXorBits = 0; }
}
} else hXorBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader,
CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
if( hXorBits ) if( hXorBits )
{ {
char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight * char* bits = (char *)bmi + size + bmi->bmiHeader.biHeight *
@ -369,8 +467,25 @@ static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16
/* Create the AND bitmap */ /* Create the AND bitmap */
hAndBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader, CBM_INIT, if (DoStretch) {
bits, pInfo, DIB_RGB_COLORS ); if ((hAndBits = CreateBitmap32(width, height, 1, 1, NULL))) {
HBITMAP32 hOld;
HDC32 hMem = CreateCompatibleDC32(hdc);
BOOL32 res;
if (hMem) {
hOld = SelectObject32(hMem, hAndBits);
res = StretchDIBits32(hMem, 0, 0, width, height, 0, 0,
pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight,
bits, pInfo, DIB_RGB_COLORS, SRCCOPY);
SelectObject32(hMem, hOld);
DeleteDC32(hMem);
} else res = FALSE;
if (!res) { DeleteObject32(hAndBits); hAndBits = 0; }
}
} else hAndBits = CreateDIBitmap32( hdc, &pInfo->bmiHeader,
CBM_INIT, bits, pInfo, DIB_RGB_COLORS );
if( !hAndBits ) DeleteObject32( hXorBits ); if( !hAndBits ) DeleteObject32( hXorBits );
} }
HeapFree( GetProcessHeap(), 0, pInfo ); HeapFree( GetProcessHeap(), 0, pInfo );
@ -385,7 +500,6 @@ static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16
} }
/* Now create the CURSORICONINFO structure */ /* Now create the CURSORICONINFO structure */
bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC ); bmpXor = (BITMAPOBJ *) GDI_GetObjPtr( hXorBits, BITMAP_MAGIC );
bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC ); bmpAnd = (BITMAPOBJ *) GDI_GetObjPtr( hAndBits, BITMAP_MAGIC );
sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes; sizeXor = bmpXor->bitmap.bmHeight * bmpXor->bitmap.bmWidthBytes;
@ -432,31 +546,18 @@ static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16
HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon, HICON16 WINAPI CreateIconFromResourceEx16( LPBYTE bits, UINT16 cbSize, BOOL16 bIcon,
DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag ) DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag )
{ {
TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() ); return CreateIconFromResourceEx32(bits, cbSize, bIcon, dwVersion,
if( pTask ) width, height, cFlag);
return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
width, height, cFlag );
return 0;
} }
/********************************************************************** /**********************************************************************
* CreateIconFromResource (USER32.76) * CreateIconFromResource (USER32.76)
* FIXME:
* bon@elektron.ikp.physik.tu-darmstadt.de 971130: Test with weditres
* showed only blank layout. Couldn't determine if this is a problem
* with CreateIconFromResource32 or the application. The application
* windows behaves strange (no redraw) before CreateIconFromResource32
*/ */
HICON32 WINAPI CreateIconFromResource32( LPBYTE bits, UINT32 cbSize, HICON32 WINAPI CreateIconFromResource32( LPBYTE bits, UINT32 cbSize,
BOOL32 bIcon, DWORD dwVersion) BOOL32 bIcon, DWORD dwVersion)
{ {
HICON32 ret; return CreateIconFromResourceEx32( bits, cbSize, bIcon, dwVersion, 0,0,0);
ret = CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, 0,0,0);
FIXME(icon,"probably only a stub\n");
TRACE(icon, "%s at %p size %d winver %d return 0x%04x\n",
(bIcon)?"Icon":"Cursor",bits,cbSize,bIcon,ret);
return ret;
} }
@ -468,7 +569,11 @@ HICON32 WINAPI CreateIconFromResourceEx32( LPBYTE bits, UINT32 cbSize,
INT32 width, INT32 height, INT32 width, INT32 height,
UINT32 cFlag ) UINT32 cFlag )
{ {
return CreateIconFromResourceEx16( bits, cbSize, bIcon, dwVersion, width, height, cFlag ); TDB* pTask = (TDB*)GlobalLock16( GetCurrentTask() );
if( pTask )
return CURSORICON_CreateFromResource( pTask->hInstance, 0, bits, cbSize, bIcon, dwVersion,
width, height, cFlag );
return 0;
} }
@ -479,7 +584,7 @@ HICON32 WINAPI CreateIconFromResourceEx32( LPBYTE bits, UINT32 cbSize,
*/ */
static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name, static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name,
INT32 width, INT32 height, INT32 colors, INT32 width, INT32 height, INT32 colors,
BOOL32 fCursor ) BOOL32 fCursor, UINT32 loadflags)
{ {
HGLOBAL16 handle; HGLOBAL16 handle;
HRSRC16 hRsrc; HRSRC16 hRsrc;
@ -522,65 +627,75 @@ static HGLOBAL16 CURSORICON_Load16( HINSTANCE16 hInstance, SEGPTR name,
* *
* Load a cursor or icon from a 32-bit resource. * Load a cursor or icon from a 32-bit resource.
*/ */
static HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name, HGLOBAL32 CURSORICON_Load32( HINSTANCE32 hInstance, LPCWSTR name,
int width, int height, int colors, int width, int height, int colors,
BOOL32 fCursor ) BOOL32 fCursor, UINT32 loadflags )
{ {
HANDLE32 handle; HANDLE32 handle, h = 0;
HANDLE32 hRsrc; HANDLE32 hRsrc;
CURSORICONDIRENTRY dirEntry; CURSORICONDIRENTRY dirEntry;
LPBYTE bits;
if(!hInstance) /* OEM cursor/icon */ if (!(loadflags & LR_LOADFROMFILE))
{ {
WORD resid; if (!hInstance) /* OEM cursor/icon */
if(HIWORD(name)) {
{ WORD resid;
LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name); if(HIWORD(name))
if( ansi[0]=='#') /*Check for '#xxx' name */
{ {
resid = atoi(ansi+1); LPSTR ansi = HEAP_strdupWtoA(GetProcessHeap(),0,name);
HeapFree( GetProcessHeap(), 0, ansi ); if( ansi[0]=='#') /*Check for '#xxx' name */
} {
else resid = atoi(ansi+1);
{ HeapFree( GetProcessHeap(), 0, ansi );
HeapFree( GetProcessHeap(), 0, ansi ); }
return 0; else
{
HeapFree( GetProcessHeap(), 0, ansi );
return 0;
}
} }
else resid = LOWORD(name);
return OBM_LoadCursorIcon(resid, fCursor);
} }
else resid = LOWORD(name);
return OBM_LoadCursorIcon(resid, fCursor);
}
/* Find the best entry in the directory */ /* Find the best entry in the directory */
if ( !CURSORICON_LoadDirEntry32( hInstance, name, width, height, if (!CURSORICON_LoadDirEntry32( hInstance, name, width, height,
colors, fCursor, &dirEntry ) ) return 0; colors, fCursor, &dirEntry ) ) return 0;
/* Load the resource */ /* Load the resource */
if ( (hRsrc = FindResource32W( hInstance, if (!(hRsrc = FindResource32W(hInstance,MAKEINTRESOURCE32W(dirEntry.icon.wResId),
MAKEINTRESOURCE32W( dirEntry.icon.wResId ), fCursor ? RT_CURSOR32W : RT_ICON32W ))) return 0;
fCursor ? RT_CURSOR32W : RT_ICON32W )) ) if (!(handle = LoadResource32( hInstance, hRsrc ))) return 0;
{ /* Hack to keep LoadCursor/Icon32() from spawning multiple
HANDLE32 h = 0; * copies of the same object.
if ( (handle = LoadResource32( hInstance, hRsrc )) ) */
{
/* Hack to keep LoadCursor/Icon32() from spawning multiple
* copies of the same object.
*/
#define pRsrcEntry ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc) #define pRsrcEntry ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)
if( !pRsrcEntry->ResourceHandle ) if( pRsrcEntry->ResourceHandle ) return pRsrcEntry->ResourceHandle;
{ bits = (LPBYTE)LockResource32( handle );
LPBYTE bits = (LPBYTE)LockResource32( handle ); h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes, !fCursor, 0x00030000, width, height, loadflags);
!fCursor, 0x00030000, width, height, LR_DEFAULTCOLOR ); pRsrcEntry->ResourceHandle = h;
pRsrcEntry->ResourceHandle = h;
}
else h = pRsrcEntry->ResourceHandle;
#undef pRsrcEntry
}
return h;
} }
return 0; else
{
CURSORICONDIR *res;
LPBYTE *ptr;
if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &res, &ptr))
return 0;
if (fCursor)
dirEntry = *(CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(res, width, height, 1);
else
dirEntry = *(CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(res, width, height, colors);
bits = ptr[dirEntry.icon.wResId-1];
h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry.icon.dwBytesInRes,
!fCursor, 0x00030000, width, height, loadflags);
HeapFree( GetProcessHeap(), 0, res );
HeapFree( GetProcessHeap(), 0, ptr );
}
return h;
#undef pRsrcEntry
} }
@ -690,7 +805,7 @@ HCURSOR16 CURSORICON_IconToCursor(HICON16 hIcon, BOOL32 bSemiTransparent)
if( !hRet ) /* fall back on default drag cursor */ if( !hRet ) /* fall back on default drag cursor */
hRet = CURSORICON_Copy( pTask->hInstance , hRet = CURSORICON_Copy( pTask->hInstance ,
CURSORICON_Load16(0,MAKEINTRESOURCE16(OCR_DRAGOBJECT), CURSORICON_Load16(0,MAKEINTRESOURCE16(OCR_DRAGOBJECT),
SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE) ); SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0) );
} }
return hRet; return hRet;
@ -710,7 +825,7 @@ HCURSOR16 WINAPI LoadCursor16( HINSTANCE16 hInstance, SEGPTR name )
hInstance, LOWORD(name) ); hInstance, LOWORD(name) );
return CURSORICON_Load16( hInstance, name, return CURSORICON_Load16( hInstance, name,
SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE); SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0);
} }
@ -728,7 +843,7 @@ HICON16 WINAPI LoadIcon16( HINSTANCE16 hInstance, SEGPTR name )
return CURSORICON_Load16( hInstance, name, return CURSORICON_Load16( hInstance, name,
SYSMETRICS_CXICON, SYSMETRICS_CYICON, SYSMETRICS_CXICON, SYSMETRICS_CYICON,
MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE ); MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE, 0);
} }
@ -1329,7 +1444,7 @@ INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
UINT16 retVal = 0; UINT16 retVal = 0;
if( dir && !dir->idReserved && (dir->idType & 3) ) if( dir && !dir->idReserved && (dir->idType & 3) )
{ {
int colors = (cFlag == LR_MONOCHROME) ? 2 : COLOR_GetSystemPaletteSize(); int colors = (cFlag & LR_MONOCHROME) ? 2 : COLOR_GetSystemPaletteSize();
if( bIcon ) if( bIcon )
{ {
ICONDIRENTRY* entry; ICONDIRENTRY* entry;
@ -1339,7 +1454,7 @@ INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE xdir, BOOL16 bIcon,
else else
{ {
CURSORDIRENTRY* entry; CURSORDIRENTRY* entry;
entry = CURSORICON_FindBestCursor( dir, width, height ); entry = CURSORICON_FindBestCursor( dir, width, height, 1);
if( entry ) retVal = entry->wResId; if( entry ) retVal = entry->wResId;
} }
} }
@ -1474,7 +1589,7 @@ HICON16 WINAPI LoadIconHandler( HGLOBAL16 hResource, BOOL16 bNew )
HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name) HCURSOR32 WINAPI LoadCursor32W(HINSTANCE32 hInstance, LPCWSTR name)
{ {
return CURSORICON_Load32( hInstance, name, return CURSORICON_Load32( hInstance, name,
SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE); SYSMETRICS_CXCURSOR, SYSMETRICS_CYCURSOR, 1, TRUE, 0);
} }
/*********************************************************************** /***********************************************************************
@ -1497,19 +1612,21 @@ HCURSOR32 WINAPI LoadCursor32A(HINSTANCE32 hInstance, LPCSTR name)
* LoadCursorFromFile32W (USER32.361) * LoadCursorFromFile32W (USER32.361)
*/ */
HCURSOR32 WINAPI LoadCursorFromFile32W (LPCWSTR name) HCURSOR32 WINAPI LoadCursorFromFile32W (LPCWSTR name)
{ FIXME(cursor, ":stub LoadCursorFromFile32W\n"); {
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return LoadImage32W(0, name, IMAGE_CURSOR, SYSMETRICS_CXCURSOR,
return 0; SYSMETRICS_CYCURSOR, LR_LOADFROMFILE);
} }
/*********************************************************************** /***********************************************************************
* LoadCursorFromFile32A (USER32.360) * LoadCursorFromFile32A (USER32.360)
*/ */
HCURSOR32 WINAPI LoadCursorFromFile32A (LPCSTR name) HCURSOR32 WINAPI LoadCursorFromFile32A (LPCSTR name)
{ FIXME(cursor, ":stub LoadCursorFromFile32A %s\n", name); {
SetLastError(ERROR_CALL_NOT_IMPLEMENTED); HCURSOR32 hcur;
return 0; LPWSTR u_name = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
hcur = LoadCursorFromFile32W(u_name);
HeapFree( GetProcessHeap(), 0, u_name );
return hcur;
} }
/*********************************************************************** /***********************************************************************
@ -1519,7 +1636,7 @@ HICON32 WINAPI LoadIcon32W(HINSTANCE32 hInstance, LPCWSTR name)
{ {
return CURSORICON_Load32( hInstance, name, return CURSORICON_Load32( hInstance, name,
SYSMETRICS_CXICON, SYSMETRICS_CYICON, SYSMETRICS_CXICON, SYSMETRICS_CYICON,
MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE ); MIN( 16, COLOR_GetSystemPaletteSize() ), FALSE, 0);
} }
/*********************************************************************** /***********************************************************************
@ -1607,7 +1724,8 @@ HICON32 WINAPI CreateIconIndirect(LPICONINFO iconinfo) {
/********************************************************************** /**********************************************************************
* DrawIconEx16 (USER.394) *
DrawIconEx16 (USER.394)
*/ */
BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon, BOOL16 WINAPI DrawIconEx16 (HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
INT16 cxWidth, INT16 cyWidth, UINT16 istep, INT16 cxWidth, INT16 cyWidth, UINT16 istep,
@ -1644,34 +1762,57 @@ BOOL32 WINAPI DrawIconEx32( HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
HBRUSH32 hbr, UINT32 flags ) HBRUSH32 hbr, UINT32 flags )
{ {
CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon); CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
HDC32 hMemDC = CreateCompatibleDC32 (hdc); HDC32 hDC_off = 0, hMemDC = CreateCompatibleDC32 (hdc);
BOOL32 result = FALSE; BOOL32 result = FALSE, DoOffscreen = FALSE;
HBITMAP32 hB_off = 0, hOld = 0;
if (!ptr) return FALSE;
if (istep) if (istep)
FIXME(icon, "Ignoring istep=%d\n", istep); FIXME(icon, "Ignoring istep=%d\n", istep);
if (hbr)
FIXME(icon, "Ignoring hbr=%x\n", hbr);
if (flags & DI_COMPAT) if (flags & DI_COMPAT)
FIXME(icon, "Ignoring flag DI_COMPAT\n"); FIXME(icon, "Ignoring flag DI_COMPAT\n");
if (hMemDC && ptr) /* Calculate the size of the destination image. */
if (cxWidth == 0)
if (flags & DI_DEFAULTSIZE)
cxWidth = GetSystemMetrics32 (SM_CXICON);
else
cxWidth = ptr->nWidth;
if (cyWidth == 0)
if (flags & DI_DEFAULTSIZE)
cyWidth = GetSystemMetrics32 (SM_CYICON);
else
cyWidth = ptr->nHeight;
if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <=
STOCK_HOLLOW_BRUSH)))
{
GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
if (object)
{
UINT16 magic = object->wMagic;
GDI_HEAP_UNLOCK(hbr);
DoOffscreen = magic == BRUSH_MAGIC;
}
}
if (DoOffscreen) {
RECT32 r = {0, 0, cxWidth, cxWidth};
hDC_off = CreateCompatibleDC32(hdc);
hB_off = CreateCompatibleBitmap32(hdc, cxWidth, cyWidth);
if (hDC_off && hB_off) {
hOld = SelectObject32(hDC_off, hB_off);
FillRect32(hDC_off, &r, hbr);
}
};
if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
{ {
HBITMAP32 hXorBits, hAndBits; HBITMAP32 hXorBits, hAndBits;
COLORREF oldFg, oldBg; COLORREF oldFg, oldBg;
INT32 nStretchMode; INT32 nStretchMode;
/* Calculate the size of the destination image. */
if (cxWidth == 0)
if (flags & DI_DEFAULTSIZE)
cxWidth = GetSystemMetrics32 (SM_CXICON);
else
cxWidth = ptr->nWidth;
if (cyWidth == 0)
if (flags & DI_DEFAULTSIZE)
cyWidth = GetSystemMetrics32 (SM_CYICON);
else
cyWidth = ptr->nHeight;
nStretchMode = SetStretchBltMode32 (hdc, STRETCH_DELETESCANS); nStretchMode = SetStretchBltMode32 (hdc, STRETCH_DELETESCANS);
hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight, hXorBits = CreateBitmap32 ( ptr->nWidth, ptr->nHeight,
@ -1688,10 +1829,18 @@ BOOL32 WINAPI DrawIconEx32( HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
{ {
HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits ); HBITMAP32 hBitTemp = SelectObject32( hMemDC, hAndBits );
if (flags & DI_MASK) if (flags & DI_MASK)
StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth, if (DoOffscreen)
StretchBlt32 (hDC_off, 0, 0, cxWidth, cyWidth,
hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
else
StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND); hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
SelectObject32( hMemDC, hXorBits ); SelectObject32( hMemDC, hXorBits );
if (flags & DI_IMAGE) if (flags & DI_IMAGE)
if (DoOffscreen)
StretchBlt32 (hDC_off, 0, 0, cxWidth, cyWidth,
hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
else
StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth, StretchBlt32 (hdc, x0, y0, cxWidth, cyWidth,
hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT); hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
SelectObject32( hMemDC, hBitTemp ); SelectObject32( hMemDC, hBitTemp );
@ -1703,8 +1852,14 @@ BOOL32 WINAPI DrawIconEx32( HDC32 hdc, INT32 x0, INT32 y0, HICON32 hIcon,
if (hXorBits) DeleteObject32( hXorBits ); if (hXorBits) DeleteObject32( hXorBits );
if (hAndBits) DeleteObject32( hAndBits ); if (hAndBits) DeleteObject32( hAndBits );
SetStretchBltMode32 (hdc, nStretchMode); SetStretchBltMode32 (hdc, nStretchMode);
if (DoOffscreen) {
BitBlt32(hdc, x0, y0, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
SelectObject32(hDC_off, hOld);
}
} }
if (hMemDC) DeleteDC32( hMemDC ); if (hMemDC) DeleteDC32( hMemDC );
if (hDC_off) DeleteDC32(hDC_off);
if (hB_off) DeleteObject32(hB_off);
GlobalUnlock16( hIcon ); GlobalUnlock16( hIcon );
return result; return result;
} }