3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * PROJECT: ReactOS user32.dll
22 * FILE: lib/user32/windows/icon.c
24 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * 09-05-2001 CSH Created
29 /* INCLUDES ******************************************************************/
37 /* FUNCTIONS *****************************************************************/
40 ICON_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot)
49 hXORBitmap = CreateDIBitmap(hDC, &IconImage->icHeader, CBM_INIT,
50 ImageData, (BITMAPINFO*)IconImage, DIB_RGB_COLORS);
52 //make ImageData point to the start of the AND image data
53 ImageData = ((PBYTE)ImageData) + (((IconImage->icHeader.biWidth *
54 IconImage->icHeader.biBitCount + 31) & ~31) >> 3) *
55 (IconImage->icHeader.biHeight );
57 //create a BITMAPINFO header for the monocrome part of the icon
58 bwBIH = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof (BITMAPINFOHEADER)+2*sizeof(RGBQUAD));
60 bwBIH->bmiHeader.biBitCount = 1;
61 bwBIH->bmiHeader.biWidth = IconImage->icHeader.biWidth;
62 bwBIH->bmiHeader.biHeight = IconImage->icHeader.biHeight;
63 bwBIH->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
64 bwBIH->bmiHeader.biPlanes = 1;
65 bwBIH->bmiHeader.biSizeImage = (((IconImage->icHeader.biWidth * 1 + 31) & ~31) >> 3) *
66 (IconImage->icHeader.biHeight );
67 bwBIH->bmiHeader.biCompression = BI_RGB;
68 bwBIH->bmiHeader.biClrImportant = 0;
69 bwBIH->bmiHeader.biClrUsed = 0;
70 bwBIH->bmiHeader.biXPelsPerMeter = 0;
71 bwBIH->bmiHeader.biYPelsPerMeter = 0;
73 bwBIH->bmiColors[0].rgbBlue = 0;
74 bwBIH->bmiColors[0].rgbGreen = 0;
75 bwBIH->bmiColors[0].rgbRed = 0;
76 bwBIH->bmiColors[0].rgbReserved = 0;
78 bwBIH->bmiColors[1].rgbBlue = 0xff;
79 bwBIH->bmiColors[1].rgbGreen = 0xff;
80 bwBIH->bmiColors[1].rgbRed = 0xff;
81 bwBIH->bmiColors[1].rgbReserved = 0;
84 hANDBitmap = CreateDIBitmap(hDC, &bwBIH->bmiHeader, CBM_INIT,
85 ImageData, bwBIH, DIB_RGB_COLORS);
87 RtlFreeHeap(RtlGetProcessHeap(), 0, bwBIH);
89 IconInfo.fIcon = TRUE;
90 IconInfo.xHotspot = xHotspot;
91 IconInfo.yHotspot = yHotspot;
92 IconInfo.hbmColor = hXORBitmap;
93 IconInfo.hbmMask = hANDBitmap;
95 //Create the icon based on everything we have so far
96 hIcon = CreateIconIndirect(&IconInfo);
99 DeleteObject(hXORBitmap);
100 DeleteObject(hANDBitmap);
115 NtUserGetIconInfo(hIcon, &IconInfo.fIcon,
120 return CreateIconIndirect(&IconInfo);
135 CONST BYTE *lpbANDbits,
136 CONST BYTE *lpbXORbits)
138 DPRINT("hInstance not used in this implementation\n");
139 return NtGdiCreateIcon(TRUE,
156 CreateIconFromResource(
162 return CreateIconFromResourceEx( presbits, dwResSize, fIcon, dwVer, 0,0,0);
171 CreateIconFromResourceEx(
180 ICONIMAGE* SafeIconImage;
189 DPRINT("dwVersion, cxDesired, cyDesired are all ignored in this implementation!\n");
193 wXHotspot = (WORD)*pbIconBits;
195 wYHotspot = (WORD)*pbIconBits;
201 wXHotspot = cxDesired / 2;
202 wYHotspot = cyDesired / 2;
205 //get an safe copy of the icon data
206 SafeIconImage = RtlAllocateHeap(RtlGetProcessHeap(), 0, cbIconBits);
207 memcpy(SafeIconImage, pbIconBits, cbIconBits);
209 //take into acount the origonal hight was for both the AND and XOR images
210 SafeIconImage->icHeader.biHeight /= 2;
212 if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
214 BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;
215 ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
216 HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE);
220 ColourCount = (SafeIconImage->icHeader.biBitCount <= 8) ?
221 (1 << SafeIconImage->icHeader.biBitCount) : 0;
222 HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD);
225 //make data point to the start of the XOR image data
226 Data = (PBYTE)SafeIconImage + HeaderSize;
228 //get a handle to the screen dc, the icon we create is going to be compatable with this
229 hScreenDc = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
230 if (hScreenDc == NULL)
232 RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
236 hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, cxDesired, cyDesired, wXHotspot, wYHotspot);
237 RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
253 NtGdiGetObject( piconinfo->hbmMask, sizeof(BITMAP), &bmMask );
254 NtGdiGetObject( piconinfo->hbmColor, sizeof(BITMAP), &bmColor );
256 return NtGdiCreateIcon(piconinfo->fIcon,
276 return NtGdiDeleteObject(hIcon);
291 return DrawIconEx (hDC, X, Y, hIcon, 0, 0, 0, NULL, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE);
294 /* Ported from WINE20030408 */
308 HBRUSH hbrFlickerFreeDraw,
313 HDC hDC_off = 0, hMemDC;
314 BOOL result = FALSE, DoOffscreen;
315 HBITMAP hB_off = 0, hOld = 0;
317 if (!NtUserGetIconInfo(hIcon, &IconInfo.fIcon,
324 NtGdiGetObject(IconInfo.hbmColor, sizeof(BITMAP), &XORBitmap);
326 DPRINT("(hdc=%p,pos=%d.%d,hicon=%p,extend=%d.%d,istep=%d,br=%p,flags=0x%08x)\n",
327 hdc,xLeft,yTop,hIcon,cxWidth,cyWidth,istepIfAniCur,hbrFlickerFreeDraw,diFlags );
329 hMemDC = CreateCompatibleDC (hdc);
330 if (diFlags & DI_COMPAT)
331 DPRINT("Ignoring flag DI_COMPAT\n");
338 // Calculate the size of the destination image.
341 if (diFlags & DI_DEFAULTSIZE)
342 cxWidth = GetSystemMetrics (SM_CXICON);
344 cxWidth = XORBitmap.bmWidth;
348 if (diFlags & DI_DEFAULTSIZE)
349 cyWidth = GetSystemMetrics (SM_CYICON);
351 cyWidth = XORBitmap.bmHeight;
354 DoOffscreen = (GetObjectType( hbrFlickerFreeDraw ) == OBJ_BRUSH);
365 DbgPrint("in DrawIconEx calling: CreateCompatibleDC\n");
366 hDC_off = CreateCompatibleDC(hdc);
368 DbgPrint("in DrawIconEx calling: CreateCompatibleBitmap\n");
369 hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth);
370 if (hDC_off && hB_off)
372 DbgPrint("in DrawIconEx calling: SelectObject\n");
373 hOld = SelectObject(hDC_off, hB_off);
375 DbgPrint("in DrawIconEx calling: FillRect\n");
376 FillRect(hDC_off, &r, hbrFlickerFreeDraw);
380 if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
382 COLORREF oldFg, oldBg;
385 nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
387 oldFg = SetTextColor( hdc, RGB(0,0,0) );
389 oldBg = SetBkColor( hdc, RGB(255,255,255) );
391 if (IconInfo.hbmColor && IconInfo.hbmMask)
393 HBITMAP hBitTemp = SelectObject( hMemDC, IconInfo.hbmMask );
394 if (diFlags & DI_MASK)
397 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
398 hMemDC, 0, 0, XORBitmap.bmWidth, XORBitmap.bmHeight, SRCAND);
400 StretchBlt (hdc, xLeft, yTop, cxWidth, cyWidth,
401 hMemDC, 0, 0, XORBitmap.bmWidth, XORBitmap.bmHeight, SRCAND);
403 SelectObject( hMemDC, IconInfo.hbmColor );
404 if (diFlags & DI_IMAGE)
407 StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
408 hMemDC, 0, 0, XORBitmap.bmWidth, XORBitmap.bmHeight, SRCPAINT);
410 StretchBlt (hdc, xLeft, yTop, cxWidth, cyWidth,
411 hMemDC, 0, 0, XORBitmap.bmWidth, XORBitmap.bmHeight, SRCPAINT);
413 SelectObject( hMemDC, hBitTemp );
417 SetTextColor( hdc, oldFg );
418 SetBkColor( hdc, oldBg );
419 if (IconInfo.hbmColor)
420 DeleteObject( IconInfo.hbmColor );
422 if (IconInfo.hbmMask)
423 DeleteObject( IconInfo.hbmMask );
425 SetStretchBltMode (hdc, nStretchMode);
429 BitBlt(hdc, xLeft, yTop, cxWidth, cyWidth, hDC_off, 0, 0, SRCCOPY);
430 SelectObject(hDC_off, hOld);
439 DeleteObject(hB_off);
458 SetLastError(ERROR_NOACCESS);
462 res = NtUserGetIconInfo(hIcon,
464 &piconinfo->xHotspot,
465 &piconinfo->yHotspot,
467 &piconinfo->hbmColor);
469 RtlCopyMemory(piconinfo, &IconInfo, sizeof(ICONINFO));
483 return(LoadImageA(hInstance, lpIconName, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE));
496 return(LoadImageW(hInstance, lpIconName, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE));
505 LookupIconIdFromDirectory(
509 return LookupIconIdFromDirectoryEx( presbits, fIcon,
510 fIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
511 fIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), LR_DEFAULTCOLOR );
514 /* Ported from WINE20030408 */
516 CURSORICON_FindBestCursor( CURSORICONDIR *dir, int width, int height, int colors)
519 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
520 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
521 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
523 if (dir->idCount < 1)
525 DPRINT("Empty directory!\n");
528 if (dir->idCount == 1)
529 return &dir->idEntries[0]; /* No choice... */
532 iTotalDiff = 0xFFFFFFFF;
533 iColorDiff = 0xFFFFFFFF;
534 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
536 iTempXDiff = abs(width - entry->bWidth);
537 iTempYDiff = abs(height - entry->bHeight);
539 if(iTotalDiff > (iTempXDiff + iTempYDiff))
543 iTotalDiff = iXDiff + iYDiff;
547 /* Find Best Colors for Best Fit */
548 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
550 if(abs(width - entry->bWidth) == (int) iXDiff &&
551 abs(height - entry->bHeight) == (int) iYDiff)
553 iTempColorDiff = abs(colors - entry->bColorCount);
555 if(iColorDiff > iTempColorDiff)
558 iColorDiff = iTempColorDiff;
566 /* Ported from WINE20030408 */
568 CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width, int height, int colors)
571 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
572 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
573 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
575 if (dir->idCount < 1)
577 DPRINT("Empty directory!\n");
580 if (dir->idCount == 1)
581 return &dir->idEntries[0]; /* No choice... */
584 iTotalDiff = 0xFFFFFFFF;
585 iColorDiff = 0xFFFFFFFF;
586 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
588 iTempXDiff = abs(width - entry->bWidth);
590 iTempYDiff = abs(height - entry->bHeight);
592 if(iTotalDiff > (iTempXDiff + iTempYDiff))
596 iTotalDiff = iXDiff + iYDiff;
600 /* Find Best Colors for Best Fit */
601 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
603 if(abs(width - entry->bWidth) == (int) iXDiff &&
604 abs(height - entry->bHeight) == (int) iYDiff)
606 iTempColorDiff = abs(colors - entry->bColorCount);
607 if(iColorDiff > iTempColorDiff)
610 iColorDiff = iTempColorDiff;
618 /* Ported from WINE20030408 */
624 LookupIconIdFromDirectoryEx(
631 GRPCURSORICONDIR *dir = (GRPCURSORICONDIR*)presbits;
634 if( dir && !dir->idReserved && (dir->idType & 3) )
636 GRPCURSORICONDIRENTRY* entry;
642 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
646 palEnts = 16; //use this until GetSystemPaletteEntries works
647 colors = (Flags & LR_MONOCHROME) ? 2 : palEnts;
651 entry = (GRPCURSORICONDIRENTRY*)CURSORICON_FindBestIcon( (CURSORICONDIR*)dir,
661 DbgPrint("invalid resource directory\n");