/* $Id$
*
* PROJECT: ReactOS user32.dll
- * FILE: lib/user32/windows/input.c
- * PURPOSE: Input
+ * FILE: lib/user32/windows/icon.c
+ * PURPOSE: Icon
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* UPDATE HISTORY:
* 09-05-2001 CSH Created
#include <windows.h>
#include <user32.h>
+#include <string.h>
+#include <stdlib.h>
#include <debug.h>
/* FUNCTIONS *****************************************************************/
HICON
+ICON_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot)
+{
+ HANDLE hXORBitmap;
+ HANDLE hANDBitmap;
+ BITMAPINFO* bwBIH;
+ ICONINFO IconInfo;
+ HICON hIcon;
+
+ //load the XOR bitmap
+ hXORBitmap = CreateDIBitmap(hDC, &IconImage->icHeader, CBM_INIT,
+ ImageData, (BITMAPINFO*)IconImage, DIB_RGB_COLORS);
+
+ //make ImageData point to the start of the AND image data
+ ImageData = ((PBYTE)ImageData) + (((IconImage->icHeader.biWidth *
+ IconImage->icHeader.biBitCount + 31) & ~31) >> 3) *
+ (IconImage->icHeader.biHeight );
+
+ //create a BITMAPINFO header for the monocrome part of the icon
+ bwBIH = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (BITMAPINFOHEADER)+2*sizeof(RGBQUAD));
+
+ bwBIH->bmiHeader.biBitCount = 1;
+ bwBIH->bmiHeader.biWidth = IconImage->icHeader.biWidth;
+ bwBIH->bmiHeader.biHeight = IconImage->icHeader.biHeight;
+ bwBIH->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bwBIH->bmiHeader.biPlanes = 1;
+ bwBIH->bmiHeader.biSizeImage = (((IconImage->icHeader.biWidth * 1 + 31) & ~31) >> 3) *
+ (IconImage->icHeader.biHeight );
+ bwBIH->bmiHeader.biCompression = BI_RGB;
+ bwBIH->bmiHeader.biClrImportant = 0;
+ bwBIH->bmiHeader.biClrUsed = 0;
+ bwBIH->bmiHeader.biXPelsPerMeter = 0;
+ bwBIH->bmiHeader.biYPelsPerMeter = 0;
+
+ bwBIH->bmiColors[0].rgbBlue = 0;
+ bwBIH->bmiColors[0].rgbGreen = 0;
+ bwBIH->bmiColors[0].rgbRed = 0;
+ bwBIH->bmiColors[0].rgbReserved = 0;
+
+ bwBIH->bmiColors[1].rgbBlue = 0xff;
+ bwBIH->bmiColors[1].rgbGreen = 0xff;
+ bwBIH->bmiColors[1].rgbRed = 0xff;
+ bwBIH->bmiColors[1].rgbReserved = 0;
+
+ //load the AND bitmap
+ hANDBitmap = CreateDIBitmap(hDC, &bwBIH->bmiHeader, CBM_INIT,
+ ImageData, bwBIH, DIB_RGB_COLORS);
+
+ RtlFreeHeap(RtlGetProcessHeap(), 0, bwBIH);
+
+ IconInfo.fIcon = TRUE;
+ IconInfo.xHotspot = xHotspot;
+ IconInfo.yHotspot = yHotspot;
+ IconInfo.hbmColor = hXORBitmap;
+ IconInfo.hbmMask = hANDBitmap;
+
+ //Create the icon based on everything we have so far
+ hIcon = CreateIconIndirect(&IconInfo);
+
+ //clean up
+ DeleteObject(hXORBitmap);
+ DeleteObject(hANDBitmap);
+
+ return hIcon;
+}
+
+
+/*
+ * @implemented
+ */
+HICON
STDCALL
CopyIcon(
HICON hIcon)
{
- return (HICON)0;
+ ICONINFO IconInfo;
+ NtUserGetIconInfo(hIcon, &IconInfo.fIcon,
+ &IconInfo.xHotspot,
+ &IconInfo.yHotspot,
+ &IconInfo.hbmMask,
+ &IconInfo.hbmColor);
+ return CreateIconIndirect(&IconInfo);
}
+
+
+/*
+ * @implemented
+ */
HICON
STDCALL
CreateIcon(
CONST BYTE *lpbANDbits,
CONST BYTE *lpbXORbits)
{
- return (HICON)0;
+ DPRINT("hInstance not used in this implementation\n");
+ return NtGdiCreateIcon(TRUE,
+ nWidth,
+ nHeight,
+ cPlanes,
+ cBitsPixel,
+ nWidth/2,
+ nHeight/2,
+ lpbANDbits,
+ lpbXORbits);
}
+
+/*
+ * @implemented
+ */
HICON
STDCALL
CreateIconFromResource(
WINBOOL fIcon,
DWORD dwVer)
{
- return (HICON)0;
+ return CreateIconFromResourceEx( presbits, dwResSize, fIcon, dwVer, 0,0,0);
}
+
+/*
+ * @implemented
+ */
HICON
STDCALL
CreateIconFromResourceEx(
int cyDesired,
UINT uFlags)
{
- return (HICON)0;
+ ICONIMAGE* SafeIconImage;
+ HICON hIcon;
+ ULONG HeaderSize;
+ ULONG ColourCount;
+ PVOID Data;
+ HDC hScreenDc;
+ WORD wXHotspot;
+ WORD wYHotspot;
+
+ DPRINT("dwVersion, cxDesired, cyDesired are all ignored in this implementation!\n");
+
+ if (!fIcon)
+ {
+ wXHotspot = (WORD)*pbIconBits;
+ pbIconBits+=2;
+ wYHotspot = (WORD)*pbIconBits;
+ pbIconBits+=2;
+ cbIconBits-=4;
+ }
+ else
+ {
+ wXHotspot = cxDesired / 2;
+ wYHotspot = cyDesired / 2;
+ }
+
+ //get an safe copy of the icon data
+ SafeIconImage = RtlAllocateHeap(RtlGetProcessHeap(), 0, cbIconBits);
+ memcpy(SafeIconImage, pbIconBits, cbIconBits);
+
+ //take into acount the origonal hight was for both the AND and XOR images
+ SafeIconImage->icHeader.biHeight /= 2;
+
+ if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
+ {
+ BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;
+ ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
+ HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE);
+ }
+ else
+ {
+ ColourCount = (SafeIconImage->icHeader.biBitCount <= 8) ?
+ (1 << SafeIconImage->icHeader.biBitCount) : 0;
+ HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD);
+ }
+
+ //make data point to the start of the XOR image data
+ Data = (PBYTE)SafeIconImage + HeaderSize;
+
+ //get a handle to the screen dc, the icon we create is going to be compatable with this
+ hScreenDc = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
+ if (hScreenDc == NULL)
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
+ return(NULL);
+ }
+
+ hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, cxDesired, cyDesired, wXHotspot, wYHotspot);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
+ return hIcon;
}
+
+/*
+ * @implemented
+ */
HICON
STDCALL
CreateIconIndirect(
PICONINFO piconinfo)
{
- return (HICON)0;
+ BITMAP bmMask;
+ BITMAP bmColor;
+
+ NtGdiGetObject( piconinfo->hbmMask, sizeof(BITMAP), &bmMask );
+ NtGdiGetObject( piconinfo->hbmColor, sizeof(BITMAP), &bmColor );
+
+ return NtGdiCreateIcon(piconinfo->fIcon,
+ bmColor.bmWidth,
+ bmColor.bmHeight,
+ bmColor.bmPlanes,
+ bmColor.bmBitsPixel,
+ piconinfo->xHotspot,
+ piconinfo->yHotspot,
+ bmMask.bmBits,
+ bmColor.bmBits);
}
+
+
+/*
+ * @implemented
+ */
WINBOOL
STDCALL
DestroyIcon(
HICON hIcon)
{
- return FALSE;
+ return NtGdiDeleteObject(hIcon);
}
+
+
+/*
+ * @implemented
+ */
WINBOOL
STDCALL
DrawIcon(
int Y,
HICON hIcon)
{
- return FALSE;
+ return DrawIconEx (hDC, X, Y, hIcon, 0, 0, 0, NULL, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE);
}
+/* Ported from WINE20030408 */
+/*
+ * @implemented
+ */
WINBOOL
STDCALL
DrawIconEx(
HBRUSH hbrFlickerFreeDraw,
UINT diFlags)
{
- return FALSE;
+ ICONINFO IconInfo;
+ BITMAP XORBitmap;
+ HDC hDC_off = 0, hMemDC;
+ BOOL result = FALSE, DoOffscreen;
+ HBITMAP hB_off = 0, hOld = 0;
+
+ if (!NtUserGetIconInfo(hIcon, &IconInfo.fIcon,
+ &IconInfo.xHotspot,
+ &IconInfo.yHotspot,
+ &IconInfo.hbmMask,
+ &IconInfo.hbmColor))
+ return FALSE;
+
+ NtGdiGetObject(IconInfo.hbmColor, sizeof(BITMAP), &XORBitmap);
+
+ DPRINT("(hdc=%p,pos=%d.%d,hicon=%p,extend=%d.%d,istep=%d,br=%p,flags=0x%08x)\n",
+ hdc,xLeft,yTop,hIcon,cxWidth,cyWidth,istepIfAniCur,hbrFlickerFreeDraw,diFlags );
+
+ hMemDC = CreateCompatibleDC (hdc);
+ if (diFlags & DI_COMPAT)
+ DPRINT("Ignoring flag DI_COMPAT\n");
+
+ if (!diFlags)
+ {
+ diFlags = DI_NORMAL;
+ }
+
+ // Calculate the size of the destination image.
+ if (cxWidth == 0)
+ {
+ if (diFlags & DI_DEFAULTSIZE)
+ cxWidth = GetSystemMetrics (SM_CXICON);
+ else
+ cxWidth = XORBitmap.bmWidth;
+ }
+ if (cyWidth == 0)
+ {
+ if (diFlags & DI_DEFAULTSIZE)
+ cyWidth = GetSystemMetrics (SM_CYICON);
+ else
+ cyWidth = XORBitmap.bmHeight;
+ }
+
+ DoOffscreen = (GetObjectType( hbrFlickerFreeDraw ) == OBJ_BRUSH);
+
+ if (DoOffscreen)
+ {
+ RECT r;
+
+ r.left = 0;
+ r.top = 0;
+ r.right = cxWidth;
+ r.bottom = cxWidth;
+
+ DbgPrint("in DrawIconEx calling: CreateCompatibleDC\n");
+ hDC_off = CreateCompatibleDC(hdc);
+
+ DbgPrint("in DrawIconEx calling: CreateCompatibleBitmap\n");
+ hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
+ if (hDC_off && hB_off)
+ {
+ DbgPrint("in DrawIconEx calling: SelectObject\n");
+ hOld = SelectObject(hDC_off, hB_off);
+
+ DbgPrint("in DrawIconEx calling: FillRect\n");
+ FillRect(hDC_off, &r, hbrFlickerFreeDraw);
+ }
+ }
+
+ if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
+ {
+ COLORREF oldFg, oldBg;
+ INT nStretchMode;
+
+ nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
+
+ oldFg = SetTextColor( hdc, RGB(0,0,0) );
+
+ oldBg = SetBkColor( hdc, RGB(255,255,255) );
+
+ if (IconInfo.hbmColor && IconInfo.hbmMask)
+ {
+ HBITMAP hBitTemp = SelectObject( hMemDC, IconInfo.hbmMask );
+ if (diFlags & DI_MASK)
+ {
+ if (DoOffscreen)
+ StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
+ hMemDC, 0, 0, XORBitmap.bmWidth, XORBitmap.bmHeight, SRCAND);
+ else
+ StretchBlt (hdc, xLeft, yTop, cxWidth, cyWidth,
+ hMemDC, 0, 0, XORBitmap.bmWidth, XORBitmap.bmHeight, SRCAND);
+ }
+ SelectObject( hMemDC, IconInfo.hbmColor );
+ if (diFlags & DI_IMAGE)
+ {
+ if (DoOffscreen)
+ StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
+ hMemDC, 0, 0, XORBitmap.bmWidth, XORBitmap.bmHeight, SRCPAINT);
+ else
+ StretchBlt (hdc, xLeft, yTop, cxWidth, cyWidth,
+ hMemDC, 0, 0, XORBitmap.bmWidth, XORBitmap.bmHeight, SRCPAINT);
+ }
+ SelectObject( hMemDC, hBitTemp );
+ result = TRUE;
+ }
+
+ SetTextColor( hdc, oldFg );
+ SetBkColor( hdc, oldBg );
+ if (IconInfo.hbmColor)
+ DeleteObject( IconInfo.hbmColor );
+
+ if (IconInfo.hbmMask)
+ DeleteObject( IconInfo.hbmMask );
+
+ SetStretchBltMode (hdc, nStretchMode);
+
+ if (DoOffscreen)
+ {
+ BitBlt(hdc, xLeft, yTop, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
+ SelectObject(hDC_off, hOld);
+ }
+ }
+
+ if (hMemDC)
+ DeleteDC( hMemDC );
+ if (hDC_off)
+ DeleteDC(hDC_off);
+ if (hB_off)
+ DeleteObject(hB_off);
+ return result;
}
+
+
+/*
+ * @implemented
+ */
WINBOOL
STDCALL
GetIconInfo(
HICON hIcon,
PICONINFO piconinfo)
{
- return FALSE;
+ ICONINFO IconInfo;
+ WINBOOL res;
+
+ if(!piconinfo)
+ {
+ SetLastError(ERROR_NOACCESS);
+ return FALSE;
+ }
+
+ res = NtUserGetIconInfo(hIcon,
+ &piconinfo->fIcon,
+ &piconinfo->xHotspot,
+ &piconinfo->yHotspot,
+ &piconinfo->hbmMask,
+ &piconinfo->hbmColor);
+ if(res)
+ RtlCopyMemory(piconinfo, &IconInfo, sizeof(ICONINFO));
+ return res;
}
+
+
+/*
+ * @implemented
+ */
HICON
STDCALL
LoadIconA(
HINSTANCE hInstance,
LPCSTR lpIconName)
{
- return (HICON)0;
+ return(LoadImageA(hInstance, lpIconName, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE));
}
+
+/*
+ * @implemented
+ */
HICON
STDCALL
LoadIconW(
HINSTANCE hInstance,
LPCWSTR lpIconName)
{
- return (HICON)0;
+ return(LoadImageW(hInstance, lpIconName, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE));
}
+
+
+/*
+ * @implemented
+ */
int
STDCALL
LookupIconIdFromDirectory(
PBYTE presbits,
WINBOOL fIcon)
{
- return 0;
+ return LookupIconIdFromDirectoryEx( presbits, fIcon,
+ fIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
+ fIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), LR_DEFAULTCOLOR );
+}
+
+/* Ported from WINE20030408 */
+CURSORICONDIRENTRY*
+CURSORICON_FindBestCursor( CURSORICONDIR *dir, int width, int height, int colors)
+{
+ int i;
+ CURSORICONDIRENTRY *entry, *bestEntry = NULL;
+ UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
+ UINT iTempXDiff, iTempYDiff, iTempColorDiff;
+
+ if (dir->idCount < 1)
+ {
+ DPRINT("Empty directory!\n");
+ return NULL;
+ }
+ if (dir->idCount == 1)
+ return &dir->idEntries[0]; /* No choice... */
+
+ /* Find Best Fit */
+ iTotalDiff = 0xFFFFFFFF;
+ iColorDiff = 0xFFFFFFFF;
+ for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
+ {
+ iTempXDiff = abs(width - entry->bWidth);
+ iTempYDiff = abs(height - entry->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->bWidth) == (int) iXDiff &&
+ abs(height - entry->bHeight) == (int) iYDiff)
+ {
+ iTempColorDiff = abs(colors - entry->bColorCount);
+
+ if(iColorDiff > iTempColorDiff)
+ {
+ bestEntry = entry;
+ iColorDiff = iTempColorDiff;
+ }
+ }
+ }
+
+ return bestEntry;
+}
+
+/* Ported from WINE20030408 */
+CURSORICONDIRENTRY*
+CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width, int height, int colors)
+{
+ int i;
+ CURSORICONDIRENTRY *entry, *bestEntry = NULL;
+ UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
+ UINT iTempXDiff, iTempYDiff, iTempColorDiff;
+
+ if (dir->idCount < 1)
+ {
+ DPRINT("Empty directory!\n");
+ return NULL;
+ }
+ if (dir->idCount == 1)
+ return &dir->idEntries[0]; /* No choice... */
+
+ /* Find Best Fit */
+ iTotalDiff = 0xFFFFFFFF;
+ iColorDiff = 0xFFFFFFFF;
+ for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
+ {
+ iTempXDiff = abs(width - entry->bWidth);
+
+ iTempYDiff = abs(height - entry->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->bWidth) == (int) iXDiff &&
+ abs(height - entry->bHeight) == (int) iYDiff)
+ {
+ iTempColorDiff = abs(colors - entry->bColorCount);
+ if(iColorDiff > iTempColorDiff)
+ {
+ bestEntry = entry;
+ iColorDiff = iTempColorDiff;
+ }
+ }
+ }
+
+ return bestEntry;
}
+/* Ported from WINE20030408 */
+/*
+ * @implemented
+ */
int
STDCALL
LookupIconIdFromDirectoryEx(
int cyDesired,
UINT Flags)
{
- return 0;
+ GRPCURSORICONDIR *dir = (GRPCURSORICONDIR*)presbits;
+ UINT retVal = 0;
+
+ if( dir && !dir->idReserved && (dir->idType & 3) )
+ {
+ GRPCURSORICONDIRENTRY* entry;
+ HDC hdc;
+ UINT palEnts;
+ int colors;
+ hdc = GetDC(0);
+#if 0
+ palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
+ if (palEnts == 0)
+ palEnts = 256;
+#endif
+ palEnts = 16; //use this until GetSystemPaletteEntries works
+ colors = (Flags & LR_MONOCHROME) ? 2 : palEnts;
+
+ ReleaseDC(0, hdc);
+
+ entry = (GRPCURSORICONDIRENTRY*)CURSORICON_FindBestIcon( (CURSORICONDIR*)dir,
+ cxDesired,
+ cyDesired,
+ colors );
+
+ if( entry )
+ retVal = entry->nID;
+ }
+ else
+ {
+ DbgPrint("invalid resource directory\n");
+ }
+ return retVal;
}