2 * ImageList implementation
4 * Copyright 1998 Eric Kohl
6 * 2001 Michael Stefaniuc
9 * - Fix ImageList_DrawIndirect (xBitmap, yBitmap, rgbFg, rgbBk, dwRop).
10 * - Fix ImageList_GetIcon.
11 * - Fix ImageList_Write.
12 * - Fix ImageList_SetFilter (undocumented).
13 * BTW does anybody know anything about this function???
14 * - It removes 12 Bytes from the stack (3 Parameters).
15 * - First parameter SHOULD be a HIMAGELIST.
16 * - Second parameter COULD be an index?????
17 * - Third parameter.... ?????????????????????
20 * - ImageList_Draw, ImageList_DrawEx and ImageList_GetIcon use
21 * ImageList_DrawIndirect. Since ImageList_DrawIndirect is still
22 * partially implemented, the functions mentioned above will be
23 * limited in functionality too.
30 #include "wine/obj_base.h"
31 #include "wine/obj_storage.h"
33 #include "imagelist.h"
34 #include "debugtools.h"
36 DEFAULT_DEBUG_CHANNEL(imagelist);
39 #define MAX_OVERLAYIMAGE 15
41 /* internal image list data used for Drag & Drop operations */
46 /* position of the drag image relative to the window */
49 /* offset of the hotspot relative to the origin of the image */
52 /* is the drag image visible */
54 /* saved background */
58 static INTERNALDRAG InternalDrag = { 0, 0, 0, 0, 0, 0, FALSE, 0 };
62 /*************************************************************************
63 * IMAGELIST_InternalExpandBitmaps [Internal]
65 * Expands the bitmaps of an image list by the given number of images.
68 * himl [I] handle to image list
69 * nImageCount [I] number of images to add
75 * This function can NOT be used to reduce the number of images.
78 IMAGELIST_InternalExpandBitmaps (HIMAGELIST himl, INT nImageCount, INT cx, INT cy)
80 HDC hdcImageList, hdcBitmap;
82 INT nNewWidth, nNewCount;
84 if ((himl->cCurImage + nImageCount <= himl->cMaxImage)
88 if (cy == 0) cy = himl->cy;
89 nNewCount = himl->cCurImage + nImageCount + himl->cGrow;
90 nNewWidth = nNewCount * himl->cx;
92 TRACE("Create expanded bitmaps : himl=%p x=%d y=%d count=%d\n", himl, nNewWidth, cy, nNewCount);
93 hdcImageList = CreateCompatibleDC (0);
94 hdcBitmap = CreateCompatibleDC (0);
97 CreateBitmap (nNewWidth, cy, 1, himl->uBitsPixel, NULL);
98 if (hbmNewBitmap == 0)
99 ERR("creating new image bitmap (x=%d y=%d)!\n", nNewWidth, cy);
101 SelectObject (hdcImageList, himl->hbmImage);
102 SelectObject (hdcBitmap, hbmNewBitmap);
103 BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy,
104 hdcImageList, 0, 0, SRCCOPY);
106 DeleteObject (himl->hbmImage);
107 himl->hbmImage = hbmNewBitmap;
111 CreateBitmap (nNewWidth, cy, 1, 1, NULL);
113 if (hbmNewBitmap == 0)
114 ERR("creating new mask bitmap!\n");
116 SelectObject (hdcImageList, himl->hbmMask);
117 SelectObject (hdcBitmap, hbmNewBitmap);
118 BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy,
119 hdcImageList, 0, 0, SRCCOPY);
120 DeleteObject (himl->hbmMask);
121 himl->hbmMask = hbmNewBitmap;
124 himl->cMaxImage = nNewCount;
126 DeleteDC (hdcImageList);
127 DeleteDC (hdcBitmap);
131 /*************************************************************************
132 * IMAGELIST_InternalDraw [Internal]
134 * Draws the image in the ImageList (without the mask)
137 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
138 * cx [I] the width of the image to display
139 * cy............[I] the height of the image to display
145 * This function is used by ImageList_DrawIndirect, when it is
146 * required to draw only the Image (without the mask) to the screen.
148 * Blending and Overlays styles are accomplished by another function
151 IMAGELIST_InternalDraw(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
156 hImageDC = CreateCompatibleDC(0);
157 hOldBitmap = SelectObject(hImageDC, pimldp->himl->hbmImage);
158 BitBlt(pimldp->hdcDst,
159 pimldp->x, pimldp->y, cx, cy,
161 pimldp->himl->cx * pimldp->i, 0,
164 SelectObject(hImageDC, hOldBitmap);
169 /*************************************************************************
170 * IMAGELIST_InternalDrawMask [Internal]
172 * Draws the image in the ImageList with the mask
175 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
176 * cx [I] the width of the image to display
177 * cy............[I] the height of the image to display
183 * This function is used by ImageList_DrawIndirect, when it is
184 * required to draw the Image with the mask to the screen.
186 * Blending and Overlays styles are accomplished by another function.
189 IMAGELIST_InternalDrawMask(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
191 BOOL bUseCustomBackground, bBlendFlag;
192 HBRUSH hBrush, hOldBrush;
193 HDC hMaskDC, hImageDC;
194 HBITMAP hOldBitmapImage, hOldBitmapMask;
195 HIMAGELIST himlLocal = pimldp->himl;
196 COLORREF oldBkColor, oldFgColor;
197 UINT fStyle = pimldp->fStyle & (~ILD_OVERLAYMASK);
200 * We need a dc and bitmap to draw on that is
203 HDC hOffScreenDC = 0;
204 HBITMAP hOffScreenBmp = 0;
206 bUseCustomBackground = (himlLocal->clrBk != CLR_NONE);
207 bBlendFlag = (fStyle & ILD_BLEND50 ) || (fStyle & ILD_BLEND25);
209 hImageDC = CreateCompatibleDC(0);
210 hMaskDC = CreateCompatibleDC(0);
212 /* Create a compatible DC. */
213 hOffScreenDC = CreateCompatibleDC( pimldp->hdcDst );
217 hOffScreenBmp = CreateCompatibleBitmap( pimldp->hdcDst, cx, cy );
220 SelectObject( hOffScreenDC, hOffScreenBmp );
227 hOldBitmapImage = SelectObject(hImageDC, himlLocal->hbmImage);
228 hOldBitmapMask = SelectObject(hMaskDC, himlLocal->hbmMask);
231 * Get a copy of the image for the masking operations.
232 * We will use the copy, and this dc for all the various
233 * blitting, and then do one final blit to the screen dc.
234 * This should clean up most of the flickering.
236 BitBlt( hOffScreenDC, 0, 0, cx, cy, pimldp->hdcDst, pimldp->x,
240 * Draw the Background for the appropriate Styles
242 if( bUseCustomBackground && (fStyle == ILD_NORMAL || fStyle & ILD_IMAGE
246 hBrush = CreateSolidBrush (himlLocal->clrBk);
247 hOldBrush = SelectObject (pimldp->hdcDst, hBrush);
249 PatBlt( hOffScreenDC, pimldp->x, pimldp->y, cx, cy, PATCOPY );
251 DeleteObject (SelectObject (pimldp->hdcDst, hOldBrush));
255 * Draw Image Transparently over the current background
257 if(fStyle == ILD_NORMAL || (fStyle & ILD_TRANSPARENT) ||
258 ((fStyle & ILD_IMAGE) && bUseCustomBackground) || bBlendFlag)
260 * To obtain a transparent look, background color should be set
261 * to white and foreground color to black when blting the
265 oldBkColor = SetBkColor( hOffScreenDC, RGB( 0xff, 0xff, 0xff ) );
266 oldFgColor = SetTextColor( hOffScreenDC, RGB( 0, 0, 0 ) );
268 BitBlt( hOffScreenDC, 0, 0, cx, cy,hMaskDC, himlLocal->cx * pimldp->i,
271 BitBlt( hOffScreenDC, 0, 0, cx, cy, hImageDC,himlLocal->cx * pimldp->i,
277 * Draw the image when no Background is specified
279 else if((fStyle & ILD_IMAGE) && !bUseCustomBackground)
281 BitBlt( hOffScreenDC, 0, 0, cx, cy, hImageDC,
282 himlLocal->cx * pimldp->i, 0, SRCCOPY);
285 * Draw the mask with or without a background
287 else if(fStyle & ILD_MASK)
289 BitBlt( hOffScreenDC, 0, 0, cx, cy, hMaskDC, himlLocal->cx * pimldp->i,
290 0, bUseCustomBackground ? SRCCOPY : SRCAND);
294 * Blit the bitmap to the screen now.
296 BitBlt( pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
297 hOffScreenDC, 0, 0, SRCCOPY);
300 SelectObject(hImageDC, hOldBitmapImage);
301 SelectObject(hMaskDC, hOldBitmapMask);
308 DeleteDC( hOffScreenDC );
309 DeleteObject( hOffScreenBmp );
314 /*************************************************************************
315 * IMAGELIST_InternalDrawBlend [Internal]
317 * Draws the Blend over the current image
320 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
321 * cx [I] the width of the image to display
322 * cy............[I] the height of the image to display
328 * This functions is used by ImageList_DrawIndirect, when it is
329 * required to add the blend to the current image.
333 IMAGELIST_InternalDrawBlend(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
336 HDC hBlendMaskDC,hMaskDC;
337 HBRUSH hBlendColorBrush, hBlendBrush, hOldBrush;
338 HBITMAP hBlendMaskBitmap, hOldBitmap;
339 COLORREF clrBlend, OldTextColor, OldBkColor;
340 HIMAGELIST himlLocal = pimldp->himl;
342 clrBlend = GetSysColor (COLOR_HIGHLIGHT);
343 if (!(pimldp->rgbFg == CLR_DEFAULT))
345 clrBlend = pimldp->rgbFg;
347 /* Create the blend Mask
349 hBlendMaskDC = CreateCompatibleDC(0);
350 hBlendBrush = pimldp->fStyle & ILD_BLEND50 ?
351 himlLocal->hbrBlend50 : himlLocal->hbrBlend25;
353 hBlendMaskBitmap = CreateBitmap(cx, cy, 1, 1, NULL);
354 hOldBitmap = SelectObject(hBlendMaskDC, hBlendMaskBitmap);
356 hOldBrush = (HBRUSH) SelectObject(hBlendMaskDC, hBlendBrush);
357 PatBlt(hBlendMaskDC, 0, 0, cx, cy, PATCOPY);
358 SelectObject(hBlendMaskDC, hOldBrush);
360 /* Modify the blend mask if an Image Mask exist
362 if(pimldp->himl->hbmMask != 0)
364 HBITMAP hOldMaskBitmap;
365 hMaskDC = CreateCompatibleDC(0);
366 hOldMaskBitmap = (HBITMAP) SelectObject(hMaskDC, himlLocal->hbmMask);
371 himlLocal->cx * pimldp->i,0,
372 0x220326); /* NOTSRCAND */
380 SelectObject(hMaskDC, hOldMaskBitmap);
384 /* Apply blend to the current image given the BlendMask
386 OldTextColor = SetTextColor(pimldp->hdcDst, 0);
387 OldBkColor = SetBkColor(pimldp->hdcDst, RGB(255,255,255));
388 hBlendColorBrush = CreateSolidBrush(clrBlend);
389 hOldBrush = (HBRUSH) SelectObject (pimldp->hdcDst, hBlendColorBrush);
391 BitBlt (pimldp->hdcDst,
392 pimldp->x, pimldp->y, cx, cy,
395 0xB8074A); /* PSDPxax */
397 SelectObject(pimldp->hdcDst, hOldBrush);
398 SetTextColor(pimldp->hdcDst, OldTextColor);
399 SetBkColor(pimldp->hdcDst, OldBkColor);
400 SelectObject(hBlendMaskDC, hOldBitmap);
401 DeleteDC(hBlendMaskDC);
402 DeleteObject(hBlendMaskBitmap);
403 DeleteObject(hBlendColorBrush);
406 /*************************************************************************
407 * IMAGELIST_InternalDrawOverlay [Internal]
409 * Draws the overlay image
412 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
413 * cx [I] the width of the image to display
414 * cy............[I] the height of the image to display
420 * This functions is used by ImageList_DrawIndirect, when it is
421 * required to draw the overlay
426 IMAGELIST_InternalDrawOverlay(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
432 nOvlIdx = (pimldp->fStyle & ILD_OVERLAYMASK) >> 8;
433 if ((nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE))
435 nOvlIdx = pimldp->himl->nOvlIdx[nOvlIdx - 1];
436 if ((nOvlIdx >= 0) && (nOvlIdx <= pimldp->himl->cCurImage))
438 hImageDC = CreateCompatibleDC(0);
439 if (pimldp->himl->hbmMask)
441 hOldBitmap = (HBITMAP) SelectObject (hImageDC,
442 pimldp->himl->hbmMask);
444 BitBlt (pimldp->hdcDst,
445 pimldp->x, pimldp->y, cx, cy,
446 hImageDC, pimldp->himl->cx * nOvlIdx, 0,
449 SelectObject(hImageDC, hOldBitmap);
451 hOldBitmap = (HBITMAP) SelectObject (hImageDC,
452 pimldp->himl->hbmImage);
454 BitBlt (pimldp->hdcDst,
455 pimldp->x, pimldp->y, cx, cy,
457 pimldp->himl->cx * nOvlIdx, 0,
460 SelectObject(hImageDC, hOldBitmap);
467 /*************************************************************************
468 * ImageList_Add [COMCTL32.40]
470 * Add an image or images to an image list.
473 * himl [I] handle to image list
474 * hbmImage [I] handle to image bitmap
475 * hbmMask [I] handle to mask bitmap
478 * Success: Index of the first new image.
483 ImageList_Add (HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
485 HDC hdcImage, hdcBitmap;
486 INT nFirstIndex, nImageCount;
489 HBITMAP hOldBitmapImage, hOldBitmap;
491 TRACE("himl=%p hbmimage=%x hbmmask=%x\n", himl, hbmImage, hbmMask);
492 if (!himl || !hbmImage)
495 GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
496 nImageCount = bmp.bmWidth / himl->cx;
498 IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight);
500 nStartX = himl->cCurImage * himl->cx;
502 hdcImage = CreateCompatibleDC(0);
503 hdcBitmap = CreateCompatibleDC(0);
505 hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
506 hOldBitmap = SelectObject(hdcBitmap, hbmImage);
508 /* Copy result to the imagelist
510 BitBlt (hdcImage, nStartX, 0, bmp.bmWidth, bmp.bmHeight,
511 hdcBitmap, 0, 0, SRCCOPY);
515 HDC hdcMask, hdcTemp, hOldBitmapMask, hOldBitmapTemp;
517 hdcMask = CreateCompatibleDC (0);
518 hdcTemp = CreateCompatibleDC(0);
519 hOldBitmapMask = (HBITMAP) SelectObject(hdcMask, himl->hbmMask);
520 hOldBitmapTemp = (HBITMAP) SelectObject(hdcTemp, hbmMask);
523 nStartX, 0, bmp.bmWidth, bmp.bmHeight,
528 SelectObject(hdcTemp, hOldBitmapTemp);
531 /* Remove the background from the image
534 nStartX, 0, bmp.bmWidth, bmp.bmHeight,
537 0x220326); /* NOTSRCAND */
539 SelectObject(hdcMask, hOldBitmapMask);
543 SelectObject(hdcImage, hOldBitmapImage);
544 SelectObject(hdcBitmap, hOldBitmap);
548 nFirstIndex = himl->cCurImage;
549 himl->cCurImage += nImageCount;
555 /*************************************************************************
556 * ImageList_AddIcon [COMCTL32.41]
558 * Adds an icon to an image list.
561 * himl [I] handle to image list
562 * hIcon [I] handle to icon
565 * Success: index of the new image
570 ImageList_AddIcon (HIMAGELIST himl, HICON hIcon)
572 return ImageList_ReplaceIcon (himl, -1, hIcon);
576 /*************************************************************************
577 * ImageList_AddMasked [COMCTL32.42]
579 * Adds an image or images to an image list and creates a mask from the
580 * specified bitmap using the mask color.
583 * himl [I] handle to image list.
584 * hBitmap [I] handle to bitmap
585 * clrMask [I] mask color.
588 * Success: Index of the first new image.
593 ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
595 HDC hdcImage, hdcMask, hdcBitmap;
596 INT nIndex, nImageCount, nMaskXOffset=0;
598 HBITMAP hOldBitmap, hOldBitmapMask, hOldBitmapImage;
599 HBITMAP hMaskBitmap=0;
602 TRACE("himl=%p hbitmap=%x clrmask=%lx\n", himl, hBitmap, clrMask);
606 if (!GetObjectA (hBitmap, sizeof(BITMAP), &bmp))
609 nImageCount = bmp.bmWidth / himl->cx;
611 IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight);
613 nIndex = himl->cCurImage;
614 himl->cCurImage += nImageCount;
616 hdcMask = CreateCompatibleDC (0);
617 hdcImage = CreateCompatibleDC(0);
618 hdcBitmap = CreateCompatibleDC(0);
621 hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
622 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
625 hOldBitmapMask = SelectObject(hdcMask, himl->hbmMask);
626 nMaskXOffset = nIndex * himl->cx;
631 Create a temp Mask so we can remove the background of
632 the Image (Windows does this even if there is no mask)
634 hMaskBitmap = CreateBitmap(bmp.bmWidth, bmp.bmHeight, 1, 1, NULL);
635 hOldBitmapMask = SelectObject(hdcMask, hMaskBitmap);
638 /* create monochrome image to the mask bitmap */
639 bkColor = (clrMask != CLR_DEFAULT) ? clrMask :
640 GetPixel (hdcBitmap, 0, 0);
641 SetBkColor (hdcBitmap, bkColor);
643 nMaskXOffset, 0, bmp.bmWidth, bmp.bmHeight,
647 SetBkColor(hdcBitmap, RGB(255,255,255));
648 /*Remove the background from the image
651 WINDOWS BUG ALERT!!!!!!
652 The statement below should not be done in common practice
653 but this is how ImageList_AddMasked works in Windows.
654 It overwrites the original bitmap passed, this was discovered
655 by using the same bitmap to iterate the different styles
656 on windows where it failed (BUT ImageList_Add is OK)
657 This is here in case some apps rely on this bug
660 0, 0, bmp.bmWidth, bmp.bmHeight,
663 0x220326); /* NOTSRCAND */
664 /* Copy result to the imagelist
667 nIndex * himl->cx, 0, bmp.bmWidth, bmp.bmHeight,
673 SelectObject(hdcMask,hOldBitmapMask);
674 SelectObject(hdcImage, hOldBitmapImage);
675 SelectObject(hdcBitmap, hOldBitmap);
681 DeleteObject(hMaskBitmap);
688 /*************************************************************************
689 * ImageList_BeginDrag [COMCTL32.43]
691 * Creates a temporary image list that contains one image. It will be used
695 * himlTrack [I] handle to the source image list
696 * iTrack [I] index of the drag image in the source image list
697 * dxHotspot [I] X position of the hot spot of the drag image
698 * dyHotspot [I] Y position of the hot spot of the drag image
706 ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
707 INT dxHotspot, INT dyHotspot)
712 TRACE("(himlTrack=%p iTrack=%d dx=%d dy=%d)\n", himlTrack, iTrack,
713 dxHotspot, dyHotspot);
715 if (himlTrack == NULL)
718 if (InternalDrag.himl)
719 ImageList_EndDrag ();
724 InternalDrag.himl = ImageList_Create (cx, cy, himlTrack->flags, 1, 1);
725 if (InternalDrag.himl == NULL) {
726 ERR("Error creating drag image list!\n");
730 InternalDrag.dxHotspot = dxHotspot;
731 InternalDrag.dyHotspot = dyHotspot;
733 hdcSrc = CreateCompatibleDC (0);
734 hdcDst = CreateCompatibleDC (0);
737 SelectObject (hdcSrc, himlTrack->hbmImage);
738 SelectObject (hdcDst, InternalDrag.himl->hbmImage);
739 BitBlt (hdcDst, 0, 0, cx, cy, hdcSrc, iTrack * cx, 0, SRCCOPY);
742 SelectObject (hdcSrc, himlTrack->hbmMask);
743 SelectObject (hdcDst, InternalDrag.himl->hbmMask);
744 BitBlt (hdcDst, 0, 0, cx, cy, hdcSrc, iTrack * cx, 0, SRCCOPY);
749 InternalDrag.himl->cCurImage = 1;
755 /*************************************************************************
756 * ImageList_Copy [COMCTL32.44]
758 * Copies an image of the source image list to an image of the
759 * destination image list. Images can be copied or swapped.
762 * himlDst [I] handle to the destination image list
763 * iDst [I] destination image index.
764 * himlSrc [I] handle to the source image list
765 * iSrc [I] source image index
766 * uFlags [I] flags for the copy operation
773 * Copying from one image list to another is possible. The original
774 * implementation just copies or swaps within one image list.
775 * Could this feature become a bug??? ;-)
779 ImageList_Copy (HIMAGELIST himlDst, INT iDst, HIMAGELIST himlSrc,
780 INT iSrc, INT uFlags)
784 TRACE("iDst=%d iSrc=%d\n", iDst, iSrc);
786 if ((himlSrc == NULL) || (himlDst == NULL))
788 if ((iDst < 0) || (iDst >= himlDst->cCurImage))
790 if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage))
793 hdcSrc = CreateCompatibleDC (0);
794 if (himlDst == himlSrc)
797 hdcDst = CreateCompatibleDC (0);
799 if (uFlags & ILCF_SWAP) {
801 HBITMAP hbmTempImage, hbmTempMask;
803 /* create temporary bitmaps */
804 hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
805 himlSrc->uBitsPixel, NULL);
806 hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
809 /* copy (and stretch) destination to temporary bitmaps.(save) */
811 SelectObject (hdcSrc, himlDst->hbmImage);
812 SelectObject (hdcDst, hbmTempImage);
813 StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
814 hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
817 SelectObject (hdcSrc, himlDst->hbmMask);
818 SelectObject (hdcDst, hbmTempMask);
819 StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
820 hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
823 /* copy (and stretch) source to destination */
825 SelectObject (hdcSrc, himlSrc->hbmImage);
826 SelectObject (hdcDst, himlDst->hbmImage);
827 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
828 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
831 SelectObject (hdcSrc, himlSrc->hbmMask);
832 SelectObject (hdcDst, himlDst->hbmMask);
833 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
834 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
837 /* copy (without stretching) temporary bitmaps to source (restore) */
839 SelectObject (hdcSrc, hbmTempImage);
840 SelectObject (hdcDst, himlSrc->hbmImage);
841 BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
842 hdcSrc, 0, 0, SRCCOPY);
844 SelectObject (hdcSrc, hbmTempMask);
845 SelectObject (hdcDst, himlSrc->hbmMask);
846 BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
847 hdcSrc, 0, 0, SRCCOPY);
849 /* delete temporary bitmaps */
850 DeleteObject (hbmTempMask);
851 DeleteObject (hbmTempImage);
855 SelectObject (hdcSrc, himlSrc->hbmImage);
856 if (himlSrc == himlDst)
859 SelectObject (hdcDst, himlDst->hbmImage);
860 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
861 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
865 SelectObject (hdcSrc, himlSrc->hbmMask);
866 if (himlSrc == himlDst)
869 SelectObject (hdcDst, himlDst->hbmMask);
870 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
871 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
876 if (himlSrc != himlDst)
883 /*************************************************************************
884 * ImageList_Create [COMCTL32.45] Creates a new image list.
887 * cx [I] image height
889 * flags [I] creation flags
890 * cInitial [I] initial number of images in the image list
891 * cGrow [I] number of images by which image list grows
894 * Success: Handle to the created image list
899 ImageList_Create (INT cx, INT cy, UINT flags,
900 INT cInitial, INT cGrow)
906 static WORD aBitBlend25[] =
907 {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00};
909 static WORD aBitBlend50[] =
910 {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
912 TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow);
914 himl = (HIMAGELIST)COMCTL32_Alloc (sizeof(struct _IMAGELIST));
921 himl->cMaxImage = cInitial + cGrow;
922 himl->cInitial = cInitial;
925 himl->clrFg = CLR_DEFAULT;
926 himl->clrBk = CLR_NONE;
928 /* initialize overlay mask indices */
929 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
930 himl->nOvlIdx[nCount] = -1;
932 hdc = CreateCompatibleDC (0);
933 himl->uBitsPixel = (UINT)GetDeviceCaps (hdc, BITSPIXEL);
936 TRACE("Image: %d Bits per Pixel\n", himl->uBitsPixel);
938 if (himl->cMaxImage > 0) {
940 CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
941 1, himl->uBitsPixel, NULL);
942 if (himl->hbmImage == 0) {
943 ERR("Error creating image bitmap!\n");
950 if ( (himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) {
951 himl->hbmMask = CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
953 if (himl->hbmMask == 0) {
954 ERR("Error creating mask bitmap!\n");
956 DeleteObject (himl->hbmImage);
963 /* create blending brushes */
964 hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend25);
965 himl->hbrBlend25 = CreatePatternBrush (hbmTemp);
966 DeleteObject (hbmTemp);
968 hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend50);
969 himl->hbrBlend50 = CreatePatternBrush (hbmTemp);
970 DeleteObject (hbmTemp);
972 TRACE("created imagelist %p\n", himl);
977 /*************************************************************************
978 * ImageList_Destroy [COMCTL32.46]
980 * Destroys an image list.
983 * himl [I] handle to image list
991 ImageList_Destroy (HIMAGELIST himl)
996 /* delete image bitmaps */
998 DeleteObject (himl->hbmImage);
1000 DeleteObject (himl->hbmMask);
1002 /* delete blending brushes */
1003 if (himl->hbrBlend25)
1004 DeleteObject (himl->hbrBlend25);
1005 if (himl->hbrBlend50)
1006 DeleteObject (himl->hbrBlend50);
1008 COMCTL32_Free (himl);
1014 /*************************************************************************
1015 * ImageList_DragEnter [COMCTL32.47]
1017 * Locks window update and displays the drag image at the given position.
1020 * hwndLock [I] handle of the window that owns the drag image.
1021 * x [I] X position of the drag image.
1022 * y [I] Y position of the drag image.
1029 * The position of the drag image is relative to the window, not
1034 ImageList_DragEnter (HWND hwndLock, INT x, INT y)
1036 TRACE("(hwnd=%#x x=%d y=%d)\n", hwndLock, x, y);
1038 if (InternalDrag.himl == NULL)
1042 InternalDrag.hwnd = hwndLock;
1044 InternalDrag.hwnd = GetDesktopWindow ();
1049 /* draw the drag image and save the background */
1050 if (!ImageList_DragShowNolock(TRUE)) {
1058 /*************************************************************************
1059 * ImageList_DragLeave [COMCTL32.48]
1061 * Unlocks window update and hides the drag image.
1064 * hwndLock [I] handle of the window that owns the drag image.
1072 ImageList_DragLeave (HWND hwndLock)
1075 InternalDrag.hwnd = hwndLock;
1077 InternalDrag.hwnd = GetDesktopWindow ();
1079 ImageList_DragShowNolock (FALSE);
1085 /*************************************************************************
1086 * ImageList_DragMove [COMCTL32.49]
1088 * Moves the drag image.
1091 * x [I] X position of the drag image.
1092 * y [I] Y position of the drag image.
1099 * The position of the drag image is relative to the window, not
1103 * The drag image should be drawn semitransparent.
1107 ImageList_DragMove (INT x, INT y)
1109 TRACE("(x=%d y=%d)\n", x, y);
1111 if (!InternalDrag.himl) {
1115 /* draw/update the drag image */
1116 if (InternalDrag.bShow) {
1120 HBITMAP hbmOffScreen;
1121 INT origNewX, origNewY;
1122 INT origOldX, origOldY;
1123 INT origRegX, origRegY;
1124 INT sizeRegX, sizeRegY;
1127 /* calculate the update region */
1128 origNewX = x - InternalDrag.dxHotspot;
1129 origNewY = y - InternalDrag.dyHotspot;
1130 origOldX = InternalDrag.x - InternalDrag.dxHotspot;
1131 origOldY = InternalDrag.y - InternalDrag.dyHotspot;
1132 origRegX = min(origNewX, origOldX);
1133 origRegY = min(origNewY, origOldY);
1134 sizeRegX = InternalDrag.himl->cx + abs(x - InternalDrag.x);
1135 sizeRegY = InternalDrag.himl->cy + abs(y - InternalDrag.y);
1137 hdcDrag = GetDCEx(InternalDrag.hwnd, 0,
1138 DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
1139 hdcOffScreen = CreateCompatibleDC(hdcDrag);
1140 hdcBg = CreateCompatibleDC(hdcDrag);
1142 hbmOffScreen = CreateCompatibleBitmap(hdcDrag, sizeRegX, sizeRegY);
1143 SelectObject(hdcOffScreen, hbmOffScreen);
1144 SelectObject(hdcBg, InternalDrag.hbmBg);
1146 /* get the actual background of the update region */
1147 BitBlt(hdcOffScreen, 0, 0, sizeRegX, sizeRegY, hdcDrag,
1148 origRegX, origRegY, SRCCOPY);
1149 /* erase the old image */
1150 BitBlt(hdcOffScreen, origOldX - origRegX, origOldY - origRegY,
1151 InternalDrag.himl->cx, InternalDrag.himl->cy, hdcBg, 0, 0,
1153 /* save the background */
1154 BitBlt(hdcBg, 0, 0, InternalDrag.himl->cx, InternalDrag.himl->cy,
1155 hdcOffScreen, origNewX - origRegX, origNewY - origRegY, SRCCOPY);
1156 /* draw the image */
1157 /* FIXME: image should be drawn semitransparent */
1158 ImageList_Draw(InternalDrag.himl, 0, hdcOffScreen, origNewX - origRegX,
1159 origNewY - origRegY, ILD_NORMAL);
1160 /* draw the update region to the screen */
1161 BitBlt(hdcDrag, origRegX, origRegY, sizeRegX, sizeRegY,
1162 hdcOffScreen, 0, 0, SRCCOPY);
1165 DeleteDC(hdcOffScreen);
1166 DeleteObject(hbmOffScreen);
1167 ReleaseDC(InternalDrag.hwnd, hdcDrag);
1170 /* update the image position */
1178 /*************************************************************************
1179 * ImageList_DragShowNolock [COMCTL32.50]
1181 * Shows or hides the drag image.
1184 * bShow [I] TRUE shows the drag image, FALSE hides it.
1191 * The drag image should be drawn semitransparent.
1195 ImageList_DragShowNolock (BOOL bShow)
1201 TRACE("bShow=0x%X!\n", bShow);
1203 /* DragImage is already visible/hidden */
1204 if ((InternalDrag.bShow && bShow) || (!InternalDrag.bShow && !bShow)) {
1208 /* position of the origin of the DragImage */
1209 x = InternalDrag.x - InternalDrag.dxHotspot;
1210 y = InternalDrag.y - InternalDrag.dyHotspot;
1212 hdcDrag = GetDCEx (InternalDrag.hwnd, 0,
1213 DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
1218 hdcBg = CreateCompatibleDC(hdcDrag);
1219 if (!InternalDrag.hbmBg) {
1220 InternalDrag.hbmBg = CreateCompatibleBitmap(hdcDrag,
1221 InternalDrag.himl->cx, InternalDrag.himl->cy);
1223 SelectObject(hdcBg, InternalDrag.hbmBg);
1226 /* save the background */
1227 BitBlt(hdcBg, 0, 0, InternalDrag.himl->cx, InternalDrag.himl->cy,
1228 hdcDrag, x, y, SRCCOPY);
1229 /* show the image */
1230 /* FIXME: this should be drawn semitransparent */
1231 ImageList_Draw(InternalDrag.himl, 0, hdcDrag, x, y, ILD_NORMAL);
1233 /* hide the image */
1234 BitBlt(hdcDrag, x, y, InternalDrag.himl->cx, InternalDrag.himl->cy,
1235 hdcBg, 0, 0, SRCCOPY);
1238 InternalDrag.bShow = !InternalDrag.bShow;
1241 ReleaseDC (InternalDrag.hwnd, hdcDrag);
1246 /*************************************************************************
1247 * ImageList_Draw [COMCTL32.51] Draws an image.
1250 * himl [I] handle to image list
1252 * hdc [I] handle to device context
1255 * fStyle [I] drawing flags
1262 * Calls ImageList_DrawIndirect.
1265 * ImageList_DrawIndirect.
1269 ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc,
1270 INT x, INT y, UINT fStyle)
1272 IMAGELISTDRAWPARAMS imldp;
1274 imldp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
1284 imldp.rgbBk = CLR_DEFAULT;
1285 imldp.rgbFg = CLR_DEFAULT;
1286 imldp.fStyle = fStyle;
1289 return ImageList_DrawIndirect (&imldp);
1293 /*************************************************************************
1294 * ImageList_DrawEx [COMCTL32.52]
1296 * Draws an image and allows to use extended drawing features.
1299 * himl [I] handle to image list
1301 * hdc [I] handle to device context
1304 * xOffs [I] X offset
1305 * yOffs [I] Y offset
1306 * rgbBk [I] background color
1307 * rgbFg [I] foreground color
1308 * fStyle [I] drawing flags
1315 * Calls ImageList_DrawIndirect.
1318 * ImageList_DrawIndirect.
1322 ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y,
1323 INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg,
1326 IMAGELISTDRAWPARAMS imldp;
1328 imldp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
1338 imldp.rgbBk = rgbBk;
1339 imldp.rgbFg = rgbFg;
1340 imldp.fStyle = fStyle;
1343 return ImageList_DrawIndirect (&imldp);
1347 /*************************************************************************
1348 * ImageList_DrawIndirect [COMCTL32.53]
1350 * Draws an image using ...
1353 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
1361 ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
1365 Do some Error Checking
1369 if (pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS))
1371 if (pimldp->himl == NULL)
1373 if ((pimldp->i < 0) || (pimldp->i >= pimldp->himl->cCurImage)) {
1374 ERR("%d not within range (max %d)\n",pimldp->i,pimldp->himl->cCurImage-1);
1378 Get the Height and Width to display
1380 cx = (pimldp->cx == 0) ? pimldp->himl->cx : pimldp->cx;
1381 cy = (pimldp->cy == 0) ? pimldp->himl->cy : pimldp->cy;
1385 if(pimldp->himl->hbmMask != 0)
1387 IMAGELIST_InternalDrawMask(pimldp, cx, cy);
1391 IMAGELIST_InternalDraw(pimldp, cx, cy);
1394 Apply the blend if needed to the Image
1396 if((pimldp->fStyle & ILD_BLEND50)
1397 || (pimldp->fStyle & ILD_BLEND25))
1399 IMAGELIST_InternalDrawBlend(pimldp, cx, cy);
1402 Apply the Overlay if needed
1404 if (pimldp->fStyle & ILD_OVERLAYMASK)
1406 IMAGELIST_InternalDrawOverlay(pimldp, cx, cy);
1413 /*************************************************************************
1414 * ImageList_Duplicate [COMCTL32.54] Duplicates an image list.
1417 * himlSrc [I] source image list handle
1420 * Success: Handle of duplicated image list.
1425 ImageList_Duplicate (HIMAGELIST himlSrc)
1430 if (himlSrc == NULL) {
1431 ERR("Invalid image list handle!\n");
1435 himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
1436 himlSrc->cInitial, himlSrc->cGrow);
1440 hdcSrc = CreateCompatibleDC (0);
1441 hdcDst = CreateCompatibleDC (0);
1442 SelectObject (hdcSrc, himlSrc->hbmImage);
1443 SelectObject (hdcDst, himlDst->hbmImage);
1444 BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy,
1445 hdcSrc, 0, 0, SRCCOPY);
1447 if (himlDst->hbmMask)
1449 SelectObject (hdcSrc, himlSrc->hbmMask);
1450 SelectObject (hdcDst, himlDst->hbmMask);
1451 BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx,
1452 himlSrc->cy, hdcSrc, 0, 0, SRCCOPY);
1458 himlDst->cCurImage = himlSrc->cCurImage;
1459 himlDst->cMaxImage = himlSrc->cMaxImage;
1465 /*************************************************************************
1466 * ImageList_EndDrag [COMCTL32.55] Finishes a drag operation.
1468 * Finishes a drag operation.
1479 ImageList_EndDrag (void)
1481 /* cleanup the InternalDrag struct */
1482 InternalDrag.hwnd = 0;
1483 ImageList_Destroy (InternalDrag.himl);
1484 InternalDrag.himl = 0;
1487 InternalDrag.dxHotspot = 0;
1488 InternalDrag.dyHotspot = 0;
1489 InternalDrag.bShow = FALSE;
1490 DeleteObject(InternalDrag.hbmBg);
1491 InternalDrag.hbmBg = 0;
1497 /*************************************************************************
1498 * ImageList_GetBkColor [COMCTL32.56]
1500 * Returns the background color of an image list.
1503 * himl [I] Image list handle.
1506 * Success: background color
1511 ImageList_GetBkColor (HIMAGELIST himl)
1520 /*************************************************************************
1521 * ImageList_GetDragImage [COMCTL32.57]
1523 * Returns the handle to the internal drag image list.
1526 * ppt [O] Pointer to the drag position. Can be NULL.
1527 * pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
1530 * Success: Handle of the drag image list.
1535 ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot)
1537 if (InternalDrag.himl) {
1539 ppt->x = InternalDrag.x;
1540 ppt->y = InternalDrag.y;
1543 pptHotspot->x = InternalDrag.dxHotspot;
1544 pptHotspot->y = InternalDrag.dyHotspot;
1546 return (InternalDrag.himl);
1553 /*************************************************************************
1554 * ImageList_GetIcon [COMCTL32.59]
1556 * Creates an icon from a masked image of an image list.
1559 * himl [I] handle to image list
1561 * flags [I] drawing style flags
1564 * Success: icon handle
1569 ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle)
1573 HBITMAP hOldSrcBitmap,hOldDstBitmap;
1576 if ((himl == NULL) || (i < 0) || (i >= himl->cCurImage)) {
1577 FIXME("(%p,%d,%x), params out of range!\n",himl,i,fStyle);
1581 hdcSrc = CreateCompatibleDC(0);
1582 hdcDst = CreateCompatibleDC(0);
1585 ii.hbmMask = CreateCompatibleBitmap (hdcDst, himl->cx, himl->cy);
1588 hOldDstBitmap = (HBITMAP)SelectObject (hdcDst, ii.hbmMask);
1589 if (himl->hbmMask) {
1590 SelectObject (hdcSrc, himl->hbmMask);
1591 BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1592 hdcSrc, i * himl->cx, 0, SRCCOPY);
1595 PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS);
1598 hOldSrcBitmap = (HBITMAP)SelectObject (hdcSrc, himl->hbmImage);
1599 ii.hbmColor = CreateCompatibleBitmap (hdcSrc, himl->cx, himl->cy);
1600 SelectObject (hdcDst, ii.hbmColor);
1601 BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1602 hdcSrc, i * himl->cx, 0, SRCCOPY);
1605 * CreateIconIndirect requires us to deselect the bitmaps from
1606 * the DCs before calling
1608 SelectObject(hdcSrc, hOldSrcBitmap);
1609 SelectObject(hdcDst, hOldDstBitmap);
1611 hIcon = CreateIconIndirect (&ii);
1615 DeleteObject (ii.hbmMask);
1616 DeleteObject (ii.hbmColor);
1622 /*************************************************************************
1623 * ImageList_GetIconSize [COMCTL32.60]
1625 * Retrieves the size of an image in an image list.
1628 * himl [I] handle to image list
1629 * cx [O] pointer to the image width.
1630 * cy [O] pointer to the image height.
1637 * All images in an image list have the same size.
1641 ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy)
1645 if ((himl->cx <= 0) || (himl->cy <= 0))
1657 /*************************************************************************
1658 * ImageList_GetImageCount [COMCTL32.61]
1660 * Returns the number of images in an image list.
1663 * himl [I] handle to image list
1666 * Success: Number of images.
1671 ImageList_GetImageCount (HIMAGELIST himl)
1676 return himl->cCurImage;
1680 /*************************************************************************
1681 * ImageList_GetImageInfo [COMCTL32.62]
1683 * Returns information about an image in an image list.
1686 * himl [I] handle to image list
1688 * pImageInfo [O] pointer to the image information
1696 ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
1698 if ((himl == NULL) || (pImageInfo == NULL))
1700 if ((i < 0) || (i >= himl->cCurImage))
1703 pImageInfo->hbmImage = himl->hbmImage;
1704 pImageInfo->hbmMask = himl->hbmMask;
1706 pImageInfo->rcImage.top = 0;
1707 pImageInfo->rcImage.bottom = himl->cy;
1708 pImageInfo->rcImage.left = i * himl->cx;
1709 pImageInfo->rcImage.right = (i+1) * himl->cx;
1715 /*************************************************************************
1716 * ImageList_GetImageRect [COMCTL32.63]
1718 * Retrieves the rectangle of the specified image in an image list.
1721 * himl [I] handle to image list
1723 * lpRect [O] pointer to the image rectangle
1730 * This is an UNDOCUMENTED function!!!
1734 ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect)
1736 if ((himl == NULL) || (lpRect == NULL))
1738 if ((i < 0) || (i >= himl->cCurImage))
1741 lpRect->left = i * himl->cx;
1743 lpRect->right = lpRect->left + himl->cx;
1744 lpRect->bottom = himl->cy;
1750 /*************************************************************************
1751 * ImageList_LoadImage [COMCTL32.64]
1752 * ImageList_LoadImageA [COMCTL32.65]
1754 * Creates an image list from a bitmap, icon or cursor.
1757 * hi [I] instance handle
1758 * lpbmp [I] name or id of the image
1759 * cx [I] width of each image
1760 * cGrow [I] number of images to expand
1761 * clrMask [I] mask color
1762 * uType [I] type of image to load
1763 * uFlags [I] loading flags
1766 * Success: handle to the loaded image list
1774 ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx, INT cGrow,
1775 COLORREF clrMask, UINT uType, UINT uFlags)
1777 HIMAGELIST himl = NULL;
1781 handle = LoadImageA (hi, lpbmp, uType, 0, 0, uFlags);
1783 ERR("Error loading image!\n");
1787 if (uType == IMAGE_BITMAP) {
1789 GetObjectA (handle, sizeof(BITMAP), &bmp);
1791 /* To match windows behavior, if cx is set to zero and
1792 the flag DI_DEFAULTSIZE is specified, cx becomes the
1793 system metric value for icons. If the flag is not specified
1794 the function sets the size to the height of the bitmap */
1797 if (uFlags & DI_DEFAULTSIZE)
1798 cx = GetSystemMetrics (SM_CXICON);
1803 nImageCount = bmp.bmWidth / cx;
1805 himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1806 nImageCount, cGrow);
1807 ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1809 else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1813 GetIconInfo (handle, &ii);
1814 GetObjectA (ii.hbmColor, sizeof(BITMAP), (LPVOID)&bmp);
1815 himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1816 ILC_MASK | ILC_COLOR, 1, cGrow);
1817 ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1818 DeleteObject (ii.hbmColor);
1819 DeleteObject (ii.hbmMask);
1822 DeleteObject (handle);
1828 /*************************************************************************
1829 * ImageList_LoadImageW [COMCTL32.66]
1831 * Creates an image list from a bitmap, icon or cursor.
1834 * hi [I] instance handle
1835 * lpbmp [I] name or id of the image
1836 * cx [I] width of each image
1837 * cGrow [I] number of images to expand
1838 * clrMask [I] mask color
1839 * uType [I] type of image to load
1840 * uFlags [I] loading flags
1843 * Success: handle to the loaded image list
1851 ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow,
1852 COLORREF clrMask, UINT uType, UINT uFlags)
1854 HIMAGELIST himl = NULL;
1858 handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags);
1860 ERR("Error loading image!\n");
1864 if (uType == IMAGE_BITMAP) {
1866 GetObjectA (handle, sizeof(BITMAP), &bmp);
1867 nImageCount = bmp.bmWidth / cx;
1869 himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1870 nImageCount, cGrow);
1871 ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1873 else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1877 GetIconInfo (handle, &ii);
1878 GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
1879 himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1880 ILC_MASK | ILC_COLOR, 1, cGrow);
1881 ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1882 DeleteObject (ii.hbmColor);
1883 DeleteObject (ii.hbmMask);
1886 DeleteObject (handle);
1892 /*************************************************************************
1893 * ImageList_Merge [COMCTL32.67]
1895 * Creates a new image list that contains a merged image from the specified
1896 * images of both source image lists.
1899 * himl1 [I] handle to first image list
1900 * i1 [I] first image index
1901 * himl2 [I] handle to second image list
1902 * i2 [I] second image index
1903 * dx [I] X offset of the second image relative to the first.
1904 * dy [I] Y offset of the second image relative to the first.
1907 * Success: handle of the merged image list.
1912 ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
1915 HIMAGELIST himlDst = NULL;
1916 HDC hdcSrcImage, hdcDstImage;
1918 INT xOff1, yOff1, xOff2, yOff2;
1921 TRACE("(himl1=%p i1=%d himl2=%p i2=%d dx=%d dy=%d)\n", himl1, i1, himl2,
1924 if ((himl1 == NULL) || (himl2 == NULL))
1928 if ((i1 < 0) || (i1 >= himl1->cCurImage)) {
1929 ERR("Index 1 out of range! %d\n", i1);
1933 if ((i2 < 0) || (i2 >= himl2->cCurImage)) {
1934 ERR("Index 2 out of range! %d\n", i2);
1939 cxDst = max (himl1->cx, dx + himl2->cx);
1944 cxDst = max (himl2->cx, himl1->cx - dx);
1949 cxDst = max (himl1->cx, himl2->cx);
1955 cyDst = max (himl1->cy, dy + himl2->cy);
1960 cyDst = max (himl2->cy, himl1->cy - dy);
1965 cyDst = max (himl1->cy, himl2->cy);
1970 himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
1973 hdcSrcImage = CreateCompatibleDC (0);
1974 hdcDstImage = CreateCompatibleDC (0);
1975 nX1 = i1 * himl1->cx;
1976 nX2 = i2 * himl2->cx;
1979 SelectObject (hdcSrcImage, himl1->hbmImage);
1980 SelectObject (hdcDstImage, himlDst->hbmImage);
1981 BitBlt (hdcDstImage, 0, 0, cxDst, cyDst,
1982 hdcSrcImage, 0, 0, BLACKNESS);
1983 BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy,
1984 hdcSrcImage, nX1, 0, SRCCOPY);
1986 SelectObject (hdcSrcImage, himl2->hbmMask);
1987 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1988 hdcSrcImage, nX2, 0, SRCAND);
1990 SelectObject (hdcSrcImage, himl2->hbmImage);
1991 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1992 hdcSrcImage, nX2, 0, SRCPAINT);
1995 SelectObject (hdcSrcImage, himl1->hbmMask);
1996 SelectObject (hdcDstImage, himlDst->hbmMask);
1997 BitBlt (hdcDstImage, 0, 0, cxDst, cyDst,
1998 hdcSrcImage, 0, 0, WHITENESS);
1999 BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy,
2000 hdcSrcImage, nX1, 0, SRCCOPY);
2002 SelectObject (hdcSrcImage, himl2->hbmMask);
2003 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
2004 hdcSrcImage, nX2, 0, SRCAND);
2006 DeleteDC (hdcSrcImage);
2007 DeleteDC (hdcDstImage);
2008 himlDst->cCurImage = 1;
2015 /* helper for _read_bitmap currently unused */
2017 static int may_use_dibsection(HDC hdc) {
2018 int bitspixel = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES);
2023 return GetDeviceCaps(hdc,CAPS1) & C1_DIBENGINE;
2027 /* helper for ImageList_Read, see comments below */
2028 static HBITMAP _read_bitmap(LPSTREAM pstm,int ilcFlag,int cx,int cy) {
2030 BITMAPFILEHEADER bmfh;
2031 BITMAPINFOHEADER bmih;
2032 int bitsperpixel,palspace,longsperline,width,height;
2033 LPBITMAPINFOHEADER bmihc = NULL;
2035 HBITMAP hbitmap = 0;
2036 LPBYTE bits = NULL,nbits = NULL;
2037 int nbytesperline,bytesperline;
2039 if (!SUCCEEDED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL)) ||
2040 (bmfh.bfType != (('M'<<8)|'B')) ||
2041 !SUCCEEDED(IStream_Read ( pstm, &bmih, sizeof(bmih), NULL)) ||
2042 (bmih.biSize != sizeof(bmih))
2046 bitsperpixel = bmih.biPlanes * bmih.biBitCount;
2047 if (bitsperpixel<=8)
2048 palspace = (1<<bitsperpixel)*sizeof(RGBQUAD);
2051 width = bmih.biWidth;
2052 height = bmih.biHeight;
2053 bmihc = (LPBITMAPINFOHEADER)LocalAlloc(LMEM_ZEROINIT,sizeof(bmih)+palspace);
2054 memcpy(bmihc,&bmih,sizeof(bmih));
2055 longsperline = ((width*bitsperpixel+31)&~0x1f)>>5;
2056 bmihc->biSizeImage = (longsperline*height)<<2;
2058 /* read the palette right after the end of the bitmapinfoheader */
2060 if (!SUCCEEDED(IStream_Read ( pstm, bmihc+1, palspace, NULL)))
2064 #if 0 /* Magic for NxM -> 1x(N*M) not implemented for DIB Sections */
2065 if ((bitsperpixel>1) &&
2066 ((ilcFlag!=ILC_COLORDDB) && (!ilcFlag || may_use_dibsection(xdc)))
2068 hbitmap = CreateDIBSection(xdc,(BITMAPINFO*)bmihc,0,(LPVOID*)&bits,0,0);
2071 if (!SUCCEEDED(IStream_Read( pstm, bits, bmihc->biSizeImage, NULL)))
2077 int i,nwidth,nheight;
2079 nwidth = width*(height/cy);
2082 if (bitsperpixel==1)
2083 hbitmap = CreateBitmap(nwidth,nheight,1,1,NULL);
2085 hbitmap = CreateCompatibleBitmap(xdc,nwidth,nheight);
2087 /* Might be a bit excessive memory use here */
2088 bits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage);
2089 nbits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage);
2090 if (!SUCCEEDED(IStream_Read ( pstm, bits, bmihc->biSizeImage, NULL)))
2093 /* Copy the NxM bitmap into a 1x(N*M) bitmap we need, linewise */
2094 /* Do not forget that windows bitmaps are bottom->top */
2095 bytesperline = longsperline*4;
2096 nbytesperline = (height/cy)*bytesperline;
2097 for (i=0;i<height;i++) {
2099 nbits+((height-1-i)%cy)*nbytesperline+(i/cy)*bytesperline,
2100 bits+bytesperline*(height-1-i),
2104 bmihc->biWidth = nwidth;
2105 bmihc->biHeight = nheight;
2106 if (!SetDIBits(xdc,hbitmap,0,nheight,nbits,(BITMAPINFO*)bmihc,0))
2108 LocalFree((HLOCAL)nbits);
2109 LocalFree((HLOCAL)bits);
2113 if (xdc) ReleaseDC(0,xdc);
2114 if (bmihc) LocalFree((HLOCAL)bmihc);
2117 DeleteObject(hbitmap);
2124 /*************************************************************************
2125 * ImageList_Read [COMCTL32.68]
2127 * Reads an image list from a stream.
2130 * pstm [I] pointer to a stream
2133 * Success: handle to image list
2136 * The format is like this:
2137 * ILHEAD ilheadstruct;
2139 * for the color image part:
2140 * BITMAPFILEHEADER bmfh;
2141 * BITMAPINFOHEADER bmih;
2142 * only if it has a palette:
2143 * RGBQUAD rgbs[nr_of_paletted_colors];
2145 * BYTE colorbits[imagesize];
2147 * the following only if the ILC_MASK bit is set in ILHEAD.ilFlags:
2148 * BITMAPFILEHEADER bmfh_mask;
2149 * BITMAPINFOHEADER bmih_mask;
2150 * only if it has a palette (it usually does not):
2151 * RGBQUAD rgbs[nr_of_paletted_colors];
2153 * BYTE maskbits[imagesize];
2155 * CAVEAT: Those images are within a NxM bitmap, not the 1xN we expect.
2156 * _read_bitmap needs to convert them.
2158 HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
2162 HBITMAP hbmColor=0,hbmMask=0;
2165 if (!SUCCEEDED(IStream_Read (pstm, &ilHead, sizeof(ILHEAD), NULL)))
2167 if (ilHead.usMagic != (('L' << 8) | 'I'))
2169 if (ilHead.usVersion != 0x101) /* probably version? */
2173 FIXME(" ilHead.cCurImage = %d\n",ilHead.cCurImage);
2174 FIXME(" ilHead.cMaxImage = %d\n",ilHead.cMaxImage);
2175 FIXME(" ilHead.cGrow = %d\n",ilHead.cGrow);
2176 FIXME(" ilHead.cx = %d\n",ilHead.cx);
2177 FIXME(" ilHead.cy = %d\n",ilHead.cy);
2178 FIXME(" ilHead.flags = %x\n",ilHead.flags);
2179 FIXME(" ilHead.ovls[0] = %d\n",ilHead.ovls[0]);
2180 FIXME(" ilHead.ovls[1] = %d\n",ilHead.ovls[1]);
2181 FIXME(" ilHead.ovls[2] = %d\n",ilHead.ovls[2]);
2182 FIXME(" ilHead.ovls[3] = %d\n",ilHead.ovls[3]);
2185 hbmColor = _read_bitmap(pstm,ilHead.flags & ~ILC_MASK,ilHead.cx,ilHead.cy);
2188 if (ilHead.flags & ILC_MASK) {
2189 hbmMask = _read_bitmap(pstm,0,ilHead.cx,ilHead.cy);
2191 DeleteObject(hbmColor);
2196 himl = ImageList_Create (
2204 DeleteObject(hbmColor);
2205 DeleteObject(hbmMask);
2208 himl->hbmImage = hbmColor;
2209 himl->hbmMask = hbmMask;
2210 himl->cCurImage = ilHead.cCurImage;
2211 himl->cMaxImage = ilHead.cMaxImage;
2213 ImageList_SetBkColor(himl,ilHead.bkcolor);
2215 ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1);
2220 /*************************************************************************
2221 * ImageList_Remove [COMCTL32.69] Removes an image from an image list
2224 * himl [I] image list handle
2233 ImageList_Remove (HIMAGELIST himl, INT i)
2235 HBITMAP hbmNewImage, hbmNewMask;
2240 ERR("Invalid image list handle!\n");
2244 if ((i < -1) || (i >= himl->cCurImage)) {
2245 ERR("index out of range! %d\n", i);
2249 if (himl->cCurImage == 0) {
2250 ERR("image list is already empty!\n");
2256 TRACE("remove all!\n");
2258 himl->cMaxImage = himl->cInitial + himl->cGrow;
2259 himl->cCurImage = 0;
2260 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2261 himl->nOvlIdx[nCount] = -1;
2263 DeleteObject (himl->hbmImage);
2265 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2266 1, himl->uBitsPixel, NULL);
2268 if (himl->hbmMask) {
2269 DeleteObject (himl->hbmMask);
2271 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2276 /* delete one image */
2277 TRACE("Remove single image! %d\n", i);
2279 /* create new bitmap(s) */
2280 cxNew = (himl->cCurImage + himl->cGrow - 1) * himl->cx;
2282 TRACE(" - Number of images: %d / %d (Old/New)\n",
2283 himl->cCurImage, himl->cCurImage - 1);
2284 TRACE(" - Max. number of images: %d / %d (Old/New)\n",
2285 himl->cMaxImage, himl->cCurImage + himl->cGrow - 1);
2288 CreateBitmap (cxNew, himl->cy, 1, himl->uBitsPixel, NULL);
2291 hbmNewMask = CreateBitmap (cxNew, himl->cy, 1, 1, NULL);
2293 hbmNewMask = 0; /* Just to keep compiler happy! */
2295 hdcSrc = CreateCompatibleDC (0);
2296 hdcDst = CreateCompatibleDC (0);
2298 /* copy all images and masks prior to the "removed" image */
2300 TRACE("Pre image copy: Copy %d images\n", i);
2302 SelectObject (hdcSrc, himl->hbmImage);
2303 SelectObject (hdcDst, hbmNewImage);
2304 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2305 hdcSrc, 0, 0, SRCCOPY);
2307 if (himl->hbmMask) {
2308 SelectObject (hdcSrc, himl->hbmMask);
2309 SelectObject (hdcDst, hbmNewMask);
2310 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2311 hdcSrc, 0, 0, SRCCOPY);
2315 /* copy all images and masks behind the removed image */
2316 if (i < himl->cCurImage - 1) {
2317 TRACE("Post image copy!\n");
2318 SelectObject (hdcSrc, himl->hbmImage);
2319 SelectObject (hdcDst, hbmNewImage);
2320 BitBlt (hdcDst, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx,
2321 himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2323 if (himl->hbmMask) {
2324 SelectObject (hdcSrc, himl->hbmMask);
2325 SelectObject (hdcDst, hbmNewMask);
2326 BitBlt (hdcDst, i * himl->cx, 0,
2327 (himl->cCurImage - i - 1) * himl->cx,
2328 himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2335 /* delete old images and insert new ones */
2336 DeleteObject (himl->hbmImage);
2337 himl->hbmImage = hbmNewImage;
2338 if (himl->hbmMask) {
2339 DeleteObject (himl->hbmMask);
2340 himl->hbmMask = hbmNewMask;
2344 himl->cMaxImage = himl->cCurImage + himl->cGrow;
2351 /*************************************************************************
2352 * ImageList_Replace [COMCTL32.70]
2354 * Replaces an image in an image list with a new image.
2357 * himl [I] handle to image list
2359 * hbmImage [I] handle to image bitmap
2360 * hbmMask [I] handle to mask bitmap. Can be NULL.
2368 ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage,
2371 HDC hdcImageList, hdcImage;
2375 ERR("Invalid image list handle!\n");
2379 if ((i >= himl->cMaxImage) || (i < 0)) {
2380 ERR("Invalid image index!\n");
2384 hdcImageList = CreateCompatibleDC (0);
2385 hdcImage = CreateCompatibleDC (0);
2386 GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
2389 SelectObject (hdcImageList, himl->hbmImage);
2390 SelectObject (hdcImage, hbmImage);
2392 StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2393 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2398 SelectObject (hdcImageList, himl->hbmMask);
2399 SelectObject (hdcImage, hbmMask);
2401 StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2402 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2405 /* Remove the background from the image
2407 SelectObject (hdcImageList, himl->hbmImage);
2408 StretchBlt (hdcImageList,
2409 i*himl->cx, 0, himl->cx, himl->cy,
2411 0, 0, bmp.bmWidth, bmp.bmHeight,
2412 0x220326); /* NOTSRCAND */
2415 DeleteDC (hdcImage);
2416 DeleteDC (hdcImageList);
2422 /*************************************************************************
2423 * ImageList_ReplaceIcon [COMCTL32.75]
2425 * Replaces an image in an image list using an icon.
2428 * himl [I] handle to image list
2430 * hIcon [I] handle to icon
2433 * Success: index of the replaced image
2438 ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon)
2440 HDC hdcImageList, hdcImage;
2443 HBITMAP hbmOldSrc, hbmOldDst;
2447 TRACE("(0x%lx 0x%x 0x%x)\n", (DWORD)himl, i, hIcon);
2451 if ((i >= himl->cMaxImage) || (i < -1))
2454 hBestFitIcon = CopyImage(
2457 LR_COPYFROMRESOURCE);
2459 GetIconInfo (hBestFitIcon, &ii);
2460 if (ii.hbmMask == 0)
2462 if (ii.hbmColor == 0)
2464 GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
2467 if (himl->cCurImage + 1 > himl->cMaxImage)
2468 IMAGELIST_InternalExpandBitmaps (himl, 1, 0, 0);
2470 nIndex = himl->cCurImage;
2476 hdcImageList = CreateCompatibleDC (0);
2477 TRACE("hdcImageList=0x%x!\n", hdcImageList);
2478 if (hdcImageList == 0)
2479 ERR("invalid hdcImageList!\n");
2481 hdcImage = CreateCompatibleDC (0);
2482 TRACE("hdcImage=0x%x!\n", hdcImage);
2484 ERR("invalid hdcImage!\n");
2486 hbmOldDst = SelectObject (hdcImageList, himl->hbmImage);
2487 SetTextColor( hdcImageList, RGB(0,0,0));
2488 SetBkColor( hdcImageList, RGB(255,255,255));
2489 hbmOldSrc = SelectObject (hdcImage, ii.hbmColor);
2490 StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2491 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2493 if (himl->hbmMask) {
2494 SelectObject (hdcImageList, himl->hbmMask);
2495 SelectObject (hdcImage, ii.hbmMask);
2496 StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2497 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2500 SelectObject (hdcImage, hbmOldSrc);
2501 SelectObject (hdcImageList, hbmOldDst);
2504 DestroyIcon(hBestFitIcon);
2506 DeleteDC (hdcImageList);
2508 DeleteDC (hdcImage);
2510 DeleteObject (ii.hbmColor);
2512 DeleteObject (ii.hbmMask);
2518 /*************************************************************************
2519 * ImageList_SetBkColor [COMCTL32.76]
2521 * Sets the background color of an image list.
2524 * himl [I] handle to image list
2525 * clrBk [I] background color
2528 * Success: previous background color
2533 ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
2540 clrOldBk = himl->clrBk;
2541 himl->clrBk = clrBk;
2546 /*************************************************************************
2547 * ImageList_SetDragCursorImage [COMCTL32.77]
2549 * Combines the specified image with the current drag image
2552 * himlDrag [I] handle to drag image list
2553 * iDrag [I] drag image index
2554 * dxHotspot [I] X position of the hot spot
2555 * dyHotspot [I] Y position of the hot spot
2562 * When this function is called and the drag image is visible, a
2563 * short flickering occurs but this matches the Win9x behavior. It is
2564 * possible to fix the flickering using code like in ImageList_DragMove.
2568 ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag,
2569 INT dxHotspot, INT dyHotspot)
2571 HIMAGELIST himlTemp;
2575 if (InternalDrag.himl == NULL)
2578 TRACE(" dxH=%d dyH=%d nX=%d nY=%d\n",
2579 dxHotspot, dyHotspot, InternalDrag.dxHotspot, InternalDrag.dyHotspot);
2581 visible = InternalDrag.bShow;
2583 /* Calculate the offset between the origin of the old image and the
2584 * origin of the second image.
2585 * dxHotspot, dyHotspot is the offset of THE Hotspot (there is only one
2586 * hotspot) to the origin of the second image.
2587 * See M$DN for details */
2588 dx = InternalDrag.dxHotspot - dxHotspot;
2589 dy = InternalDrag.dyHotspot - dyHotspot;
2590 himlTemp = ImageList_Merge (InternalDrag.himl, 0, himlDrag, iDrag, dx, dy);
2593 /* hide the drag image */
2594 ImageList_DragShowNolock(FALSE);
2596 if ((InternalDrag.himl->cx != himlTemp->cx) ||
2597 (InternalDrag.himl->cy != himlTemp->cy)) {
2598 /* the size of the drag image changed, invalidate the buffer */
2599 DeleteObject(InternalDrag.hbmBg);
2600 InternalDrag.hbmBg = 0;
2603 ImageList_Destroy (InternalDrag.himl);
2604 InternalDrag.himl = himlTemp;
2606 /* update the InternalDragOffset, if the origin of the
2607 * DragImage was changed by ImageList_Merge. */
2608 if (dx > InternalDrag.dxHotspot) {
2609 InternalDrag.dxHotspot = dx;
2611 if (dy > InternalDrag.dyHotspot) {
2612 InternalDrag.dyHotspot = dy;
2616 /* show the drag image */
2617 ImageList_DragShowNolock(TRUE);
2624 /*************************************************************************
2625 * ImageList_SetFilter [COMCTL32.78]
2627 * Sets a filter (or does something completely different)!!???
2630 * himl [I] handle to image list
2636 * Failure: FALSE ???
2639 * This is an UNDOCUMENTED function!!!!
2644 ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter)
2646 FIXME("(%p 0x%x 0x%lx):empty stub!\n",
2653 /*************************************************************************
2654 * ImageList_SetIconSize [COMCTL32.80]
2656 * Sets the image size of the bitmap and deletes all images.
2659 * himl [I] handle to image list
2660 * cx [I] image width
2661 * cy [I] image height
2669 ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy)
2676 /* remove all images */
2677 himl->cMaxImage = himl->cInitial + himl->cGrow;
2678 himl->cCurImage = 0;
2682 /* initialize overlay mask indices */
2683 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2684 himl->nOvlIdx[nCount] = -1;
2686 DeleteObject (himl->hbmImage);
2688 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2689 1, himl->uBitsPixel, NULL);
2691 if (himl->hbmMask) {
2692 DeleteObject (himl->hbmMask);
2694 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2702 /*************************************************************************
2703 * ImageList_SetImageCount [COMCTL32.81]
2705 * Resizes an image list to the specified number of images.
2708 * himl [I] handle to image list
2709 * iImageCount [I] number of images in the image list
2717 ImageList_SetImageCount (HIMAGELIST himl, INT iImageCount)
2719 HDC hdcImageList, hdcBitmap;
2720 HBITMAP hbmNewBitmap;
2721 INT nNewCount, nCopyCount;
2725 if (himl->cCurImage >= iImageCount)
2727 if (himl->cMaxImage > iImageCount)
2730 nNewCount = iImageCount + himl->cGrow;
2731 nCopyCount = min(himl->cCurImage, iImageCount);
2733 hdcImageList = CreateCompatibleDC (0);
2734 hdcBitmap = CreateCompatibleDC (0);
2736 hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2737 1, himl->uBitsPixel, NULL);
2738 if (hbmNewBitmap != 0)
2740 SelectObject (hdcImageList, himl->hbmImage);
2741 SelectObject (hdcBitmap, hbmNewBitmap);
2744 BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2745 hdcImageList, 0, 0, SRCCOPY);
2747 /* delete 'empty' image space */
2748 SetBkColor (hdcBitmap, RGB(255, 255, 255));
2749 SetTextColor (hdcBitmap, RGB(0, 0, 0));
2750 PatBlt (hdcBitmap, nCopyCount * himl->cx, 0,
2751 (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2753 DeleteObject (himl->hbmImage);
2754 himl->hbmImage = hbmNewBitmap;
2757 ERR("Could not create new image bitmap !\n");
2761 hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2763 if (hbmNewBitmap != 0)
2765 SelectObject (hdcImageList, himl->hbmMask);
2766 SelectObject (hdcBitmap, hbmNewBitmap);
2769 BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2770 hdcImageList, 0, 0, SRCCOPY);
2772 /* delete 'empty' image space */
2773 SetBkColor (hdcBitmap, RGB(255, 255, 255));
2774 SetTextColor (hdcBitmap, RGB(0, 0, 0));
2775 PatBlt (hdcBitmap, nCopyCount * himl->cx, 0,
2776 (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2778 DeleteObject (himl->hbmMask);
2779 himl->hbmMask = hbmNewBitmap;
2782 ERR("Could not create new mask bitmap!\n");
2785 DeleteDC (hdcImageList);
2786 DeleteDC (hdcBitmap);
2788 /* Update max image count and current image count */
2789 himl->cMaxImage = nNewCount;
2790 if (himl->cCurImage > nCopyCount)
2791 himl->cCurImage = nCopyCount;
2797 /*************************************************************************
2798 * ImageList_SetOverlayImage [COMCTL32.82]
2800 * Assigns an overlay mask index to an existing image in an image list.
2803 * himl [I] handle to image list
2804 * iImage [I] image index
2805 * iOverlay [I] overlay mask index
2813 ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay)
2817 if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
2819 if ((iImage!=-1) && ((iImage < 0) || (iImage > himl->cCurImage)))
2821 himl->nOvlIdx[iOverlay - 1] = iImage;
2826 /*************************************************************************
2827 * ImageList_Write [COMCTL32.83]
2829 * Writes an image list to a stream.
2832 * himl [I] handle to image list
2833 * pstm [O] Pointer to a stream.
2840 * This function can not be implemented yet, because
2841 * IStream32::Write is not implemented.
2848 ImageList_Write (HIMAGELIST himl, LPSTREAM pstm)
2853 FIXME("empty stub!\n");