Changed CopyImage to accept desiredX, desiredY and LR_COPYFROMRESOURCE.

CURSORICON_FindBestIcon changed to find the correct icon.
ImageList_ReplaceIcon now calls CopyImage internally.
Assign a value for the hIconSm CLASS member (using CopyImage).
This commit is contained in:
Pierre Mageau 1999-09-04 11:16:48 +00:00 committed by Alexandre Julliard
parent 749a2c6c86
commit 4ac8db783d
6 changed files with 266 additions and 92 deletions

View file

@ -2104,6 +2104,7 @@ ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon)
{
HDC hdcImageList, hdcImage;
INT nIndex;
HICON hBestFitIcon;
HBITMAP hbmOldSrc, hbmOldDst;
ICONINFO ii;
BITMAP bmp;
@ -2115,7 +2116,12 @@ ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon)
if ((i >= himl->cCurImage) || (i < -1))
return -1;
GetIconInfo (hIcon, &ii);
hBestFitIcon = CopyImage(
hIcon, IMAGE_ICON,
himl->cx, himl->cy,
LR_COPYFROMRESOURCE);
GetIconInfo (hBestFitIcon, &ii);
if (ii.hbmMask == 0)
ERR("no mask!\n");
if (ii.hbmColor == 0)
@ -2159,6 +2165,8 @@ ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon)
SelectObject (hdcImage, hbmOldSrc);
SelectObject (hdcImageList, hbmOldDst);
if(hBestFitIcon)
DestroyIcon(hBestFitIcon);
if (hdcImageList)
DeleteDC (hdcImageList);
if (hdcImage)

View file

@ -79,6 +79,10 @@ extern HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
int width, int height, int colors,
BOOL fCursor, UINT loadflags);
extern HGLOBAL CURSORICON_ExtCopy(HGLOBAL handle, UINT type,
INT desiredx, INT desiredy,
UINT flags);
extern WORD WINAPI CURSORICON_Destroy( HGLOBAL16 handle, UINT16 flags );
extern void CURSORICON_FreeModuleIcons( HMODULE hModule );

View file

@ -238,6 +238,9 @@ BOOL WINAPI MAIN_UserInit(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserve
/* Initialize window procedures */
if (!WINPROC_Init()) return FALSE;
/* Initialize cursor/icons */
CURSORICON_Init();
/* Initialize built-in window classes */
if (!WIDGETS_Init()) return FALSE;
@ -247,9 +250,6 @@ BOOL WINAPI MAIN_UserInit(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserve
/* Initialize menus */
if (!MENU_Init()) return FALSE;
/* Initialize cursor/icons */
CURSORICON_Init();
/* Initialize message spying */
if (!SPY_Init()) return FALSE;

View file

@ -527,8 +527,11 @@ HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
case IMAGE_BITMAP:
return BITMAP_CopyBitmap(hnd);
case IMAGE_ICON:
return CopyIcon(hnd);
return CURSORICON_ExtCopy(hnd,type, desiredx, desiredy, flags);
case IMAGE_CURSOR:
/* Should call CURSORICON_ExtCopy but more testing
* needs to be done before we change this
*/
return CopyCursor(hnd);
}
return 0;

View file

@ -71,6 +71,7 @@ typedef struct tagICONCACHE
HMODULE hModule;
HRSRC hRsrc;
HRSRC hGroupRsrc;
HANDLE handle;
INT count;
@ -112,10 +113,46 @@ static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
return handle;
}
/*************************************************************************
* CURSORICON_FindCache
*
* Given a handle, find the coresponding cache element
*
* PARAMS
* Handle [I] handle to an Image
*
* RETURNS
* Success: The cache entry
* Failure: NULL
*
*/
static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
{
ICONCACHE *ptr;
ICONCACHE *pRet=NULL;
BOOL IsFound = FALSE;
int count;
EnterCriticalSection( &IconCrst );
for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
{
if ( handle == ptr->handle )
{
IsFound = TRUE;
pRet = ptr;
}
}
LeaveCriticalSection( &IconCrst );
return pRet;
}
/**********************************************************************
* CURSORICON_AddSharedIcon
*/
static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HANDLE handle )
static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
{
ICONCACHE *ptr = HeapAlloc( SystemHeap, 0, sizeof(ICONCACHE) );
if ( !ptr ) return;
@ -123,6 +160,7 @@ static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HANDLE handl
ptr->hModule = hModule;
ptr->hRsrc = hRsrc;
ptr->handle = handle;
ptr->hGroupRsrc = hGroupRsrc;
ptr->count = 1;
EnterCriticalSection( &IconCrst );
@ -193,8 +231,10 @@ void CURSORICON_FreeModuleIcons( HMODULE hModule )
static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
int height, int colors )
{
int i, maxcolors, maxwidth, maxheight;
int i;
CURSORICONDIRENTRY *entry, *bestEntry = NULL;
UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
UINT iTempXDiff, iTempYDiff, iTempColorDiff;
if (dir->idCount < 1)
{
@ -203,88 +243,36 @@ static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int widt
}
if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
/* First find the exact size with less colors */
maxcolors = 0;
/* Find Best Fit */
iTotalDiff = 0xFFFFFFFF;
iColorDiff = 0xFFFFFFFF;
for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
if ((entry->ResInfo.icon.bWidth == width) && (entry->ResInfo.icon.bHeight == height) &&
(entry->ResInfo.icon.bColorCount <= colors) && (entry->ResInfo.icon.bColorCount > maxcolors))
{
iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
if(iTotalDiff > (iTempXDiff + iTempYDiff))
{
iXDiff = iTempXDiff;
iYDiff = iTempYDiff;
iTotalDiff = iXDiff + iYDiff;
}
}
/* Find Best Colors for Best Fit */
for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
{
if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
{
iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
if(iColorDiff > iTempColorDiff)
{
bestEntry = entry;
maxcolors = entry->ResInfo.icon.bColorCount;
iColorDiff = iTempColorDiff;
}
if (bestEntry) return bestEntry;
/* First find the exact size with more colors */
maxcolors = 255;
for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
if ((entry->ResInfo.icon.bWidth == width) && (entry->ResInfo.icon.bHeight == height) &&
(entry->ResInfo.icon.bColorCount > colors) && (entry->ResInfo.icon.bColorCount <= maxcolors))
{
bestEntry = entry;
maxcolors = entry->ResInfo.icon.bColorCount;
}
if (bestEntry) return bestEntry;
/* Now find a smaller one with less colors */
maxcolors = maxwidth = maxheight = 0;
for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
if ((entry->ResInfo.icon.bWidth <= width) && (entry->ResInfo.icon.bHeight <= height) &&
(entry->ResInfo.icon.bWidth >= maxwidth) && (entry->ResInfo.icon.bHeight >= maxheight) &&
(entry->ResInfo.icon.bColorCount <= colors) && (entry->ResInfo.icon.bColorCount > maxcolors))
{
bestEntry = entry;
maxwidth = entry->ResInfo.icon.bWidth;
maxheight = entry->ResInfo.icon.bHeight;
maxcolors = entry->ResInfo.icon.bColorCount;
}
if (bestEntry) return bestEntry;
/* Now find a smaller one with more colors */
maxcolors = 255;
maxwidth = maxheight = 0;
for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
if ((entry->ResInfo.icon.bWidth <= width) && (entry->ResInfo.icon.bHeight <= height) &&
(entry->ResInfo.icon.bWidth >= maxwidth) && (entry->ResInfo.icon.bHeight >= maxheight) &&
(entry->ResInfo.icon.bColorCount > colors) && (entry->ResInfo.icon.bColorCount <= maxcolors))
{
bestEntry = entry;
maxwidth = entry->ResInfo.icon.bWidth;
maxheight = entry->ResInfo.icon.bHeight;
maxcolors = entry->ResInfo.icon.bColorCount;
}
if (bestEntry) return bestEntry;
/* Now find a larger one with less colors */
maxcolors = 0;
maxwidth = maxheight = 255;
for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
if ((entry->ResInfo.icon.bWidth <= maxwidth) && (entry->ResInfo.icon.bHeight <= maxheight) &&
(entry->ResInfo.icon.bColorCount <= colors) && (entry->ResInfo.icon.bColorCount > maxcolors))
{
bestEntry = entry;
maxwidth = entry->ResInfo.icon.bWidth;
maxheight = entry->ResInfo.icon.bHeight;
maxcolors = entry->ResInfo.icon.bColorCount;
}
if (bestEntry) return bestEntry;
/* Now find a larger one with more colors */
maxcolors = maxwidth = maxheight = 255;
for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
if ((entry->ResInfo.icon.bWidth <= maxwidth) && (entry->ResInfo.icon.bHeight <= maxheight) &&
(entry->ResInfo.icon.bColorCount > colors) && (entry->ResInfo.icon.bColorCount <= maxcolors))
{
bestEntry = entry;
maxwidth = entry->ResInfo.icon.bWidth;
maxheight = entry->ResInfo.icon.bHeight;
maxcolors = entry->ResInfo.icon.bColorCount;
}
}
return bestEntry;
}
@ -512,7 +500,16 @@ static HGLOBAL16 CURSORICON_CreateFromResource( HINSTANCE16 hInstance, HGLOBAL16
/* Create the XOR bitmap */
if (DoStretch) {
if ((hXorBits = CreateBitmap(width, height, 1, 1, NULL))) {
if(bIcon)
{
hXorBits = CreateCompatibleBitmap(hdc, width, height);
}
else
{
hXorBits = CreateBitmap(width, height, 1, 1, NULL);
}
if(hXorBits)
{
HBITMAP hOld;
HDC hMem = CreateCompatibleDC(hdc);
BOOL res;
@ -728,6 +725,7 @@ HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
else /* Load from resource */
{
HANDLE hGroupRsrc;
WORD wResId;
DWORD dwBytesInRes;
@ -743,7 +741,7 @@ HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
if (!(hRsrc = FindResourceW( hInstance, name,
fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW )))
return 0;
hGroupRsrc = hRsrc;
/* If shared icon, check whether it was already loaded */
if ( (loadflags & LR_SHARED)
@ -778,7 +776,7 @@ HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name,
/* If shared icon, add to icon cache */
if ( h && (loadflags & LR_SHARED) )
CURSORICON_AddSharedIcon( hInstance, hRsrc, h );
CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
}
return h;
@ -807,6 +805,149 @@ static HGLOBAL16 CURSORICON_Copy( HINSTANCE16 hInstance, HGLOBAL16 handle )
return hNew;
}
/*************************************************************************
* CURSORICON_ExtCopy
*
* Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
*
* PARAMS
* Handle [I] handle to an Image
* nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
* iDesiredCX [I] The Desired width of the Image
* iDesiredCY [I] The desired height of the Image
* nFlags [I] The flags from CopyImage
*
* RETURNS
* Success: The new handle of the Image
*
* NOTES
* LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
* LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
* LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
*
*
*/
HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType,
INT iDesiredCX, INT iDesiredCY,
UINT nFlags)
{
HGLOBAL16 hNew=0;
TRACE_(icon)("Handle %u, uType %u, iDesiredCX %i, iDesiredCY %i, nFlags %u\n",
Handle, nType, iDesiredCX, iDesiredCY, nFlags);
if(Handle == 0)
{
return 0;
}
/* Best Fit or Monochrome */
if( (nFlags & LR_COPYFROMRESOURCE
&& (iDesiredCX > 0 || iDesiredCY > 0))
|| nFlags & LR_MONOCHROME)
{
ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
/* Not Found in Cache, then do a strait copy
*/
if(pIconCache == NULL)
{
TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
hNew = CURSORICON_Copy(pTask->hInstance, Handle);
if(nFlags & LR_COPYFROMRESOURCE)
{
TRACE_(icon)("LR_COPYFROMRESOURCE: Failed to load from cache\n");
}
}
else
{
int iTargetCX, iTargetCY;
LPBYTE pBits;
HANDLE hMem;
HRSRC hRsrc;
DWORD dwBytesInRes;
WORD wResId;
CURSORICONDIR *pDir;
CURSORICONDIRENTRY *pDirEntry;
BOOL bIsIcon = (nType == IMAGE_ICON);
/* Completing iDesiredCX CY for Monochrome Bitmaps if needed
*/
if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
|| (iDesiredCX == 0 && iDesiredCY == 0))
{
iDesiredCY = GetSystemMetrics(bIsIcon ?
SM_CYICON : SM_CYCURSOR);
iDesiredCX = GetSystemMetrics(bIsIcon ?
SM_CXICON : SM_CXCURSOR);
}
/* Retreive the CURSORICONDIRENTRY
*/
if (!(hMem = LoadResource( pIconCache->hModule ,
pIconCache->hGroupRsrc)))
{
return 0;
}
if (!(pDir = (CURSORICONDIR*)LockResource( hMem )))
{
return 0;
}
/* Find Best Fit
*/
if(bIsIcon)
{
pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
pDir, iDesiredCX, iDesiredCY, 256);
}
else
{
pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
pDir, iDesiredCX, iDesiredCY, 1);
}
wResId = pDirEntry->wResId;
dwBytesInRes = pDirEntry->dwBytesInRes;
FreeResource(hMem);
TRACE_(icon)("ResID %u, BytesInRes %lu, Width %d, Height %d DX %d, DY %d\n",
wResId, dwBytesInRes, pDirEntry->ResInfo.icon.bWidth,
pDirEntry->ResInfo.icon.bHeight, iDesiredCX, iDesiredCY);
/* Get the Best Fit
*/
if (!(hRsrc = FindResourceW(pIconCache->hModule ,
MAKEINTRESOURCEW(wResId), bIsIcon ? RT_ICONW : RT_CURSORW)))
{
return 0;
}
if (!(hMem = LoadResource( pIconCache->hModule , hRsrc )))
{
return 0;
}
pBits = (LPBYTE)LockResource( hMem );
iTargetCY = GetSystemMetrics(SM_CYICON);
iTargetCX = GetSystemMetrics(SM_CXICON);
/* Create a New Icon with the proper dimension
*/
hNew = CURSORICON_CreateFromResource( 0, 0, pBits, dwBytesInRes,
bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
FreeResource(hMem);
}
}
else
{
TDB* pTask = (TDB *) GlobalLock16 (GetCurrentTask ());
hNew = CURSORICON_Copy(pTask->hInstance, Handle);
}
return hNew;
}
/***********************************************************************
* CURSORICON_IconToCursor
*

View file

@ -412,6 +412,7 @@ ATOM WINAPI RegisterClass16( const WNDCLASS16 *wc )
{
ATOM atom;
CLASS *classPtr;
int iSmIconWidth, iSmIconHeight;
HINSTANCE16 hInstance=GetExePtr(wc->hInstance);
if (!(atom = GlobalAddAtom16( wc->lpszClassName ))) return 0;
@ -431,8 +432,13 @@ ATOM WINAPI RegisterClass16( const WNDCLASS16 *wc )
HIWORD(wc->lpszClassName) ?
(char *)PTR_SEG_TO_LIN(wc->lpszClassName) : "" );
iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
classPtr->hIcon = wc->hIcon;
classPtr->hIconSm = 0;
classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
iSmIconWidth, iSmIconHeight,
LR_COPYFROMRESOURCE);
classPtr->hCursor = wc->hCursor;
classPtr->hbrBackground = wc->hbrBackground;
@ -455,6 +461,7 @@ ATOM WINAPI RegisterClassA(
const WNDCLASSA* wc /* Address of structure with class data */
) {
ATOM atom;
int iSmIconWidth, iSmIconHeight;
CLASS *classPtr;
if (!(atom = GlobalAddAtomA( wc->lpszClassName )))
@ -477,8 +484,13 @@ ATOM WINAPI RegisterClassA(
wc->cbWndExtra, classPtr,
HIWORD(wc->lpszClassName) ? wc->lpszClassName : "" );
classPtr->hIcon = (HICON16)wc->hIcon;
classPtr->hIconSm = 0;
iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
classPtr->hIcon = wc->hIcon;
classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
iSmIconWidth, iSmIconHeight,
LR_COPYFROMRESOURCE);
classPtr->hCursor = (HCURSOR16)wc->hCursor;
classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
@ -494,6 +506,7 @@ ATOM WINAPI RegisterClassA(
ATOM WINAPI RegisterClassW( const WNDCLASSW* wc )
{
ATOM atom;
int iSmIconWidth, iSmIconHeight;
CLASS *classPtr;
if (!(atom = GlobalAddAtomW( wc->lpszClassName )))
@ -516,8 +529,13 @@ ATOM WINAPI RegisterClassW( const WNDCLASSW* wc )
wc->hbrBackground, wc->style, wc->cbClsExtra,
wc->cbWndExtra, classPtr );
classPtr->hIcon = (HICON16)wc->hIcon;
classPtr->hIconSm = 0;
iSmIconWidth = GetSystemMetrics(SM_CXSMICON);
iSmIconHeight = GetSystemMetrics(SM_CYSMICON);
classPtr->hIcon = wc->hIcon;
classPtr->hIconSm = CopyImage(wc->hIcon, IMAGE_ICON,
iSmIconWidth, iSmIconHeight,
LR_COPYFROMRESOURCE);
classPtr->hCursor = (HCURSOR16)wc->hCursor;
classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;