2 * ImageList implementation
4 * Copyright 1998 Eric Kohl
7 * - Fix ImageList_DrawIndirect (xBitmap, yBitmap, rgbFg, rgbBk, dwRop).
8 * - Fix ImageList_GetIcon.
9 * - Fix drag functions.
10 * - Fix ImageList_Read and ImageList_Write.
11 * - Fix ImageList_SetFilter (undocumented).
12 * BTW does anybody know anything about this function???
13 * - It removes 12 Bytes from the stack (3 Parameters).
14 * - First parameter SHOULD be a HIMAGELIST.
15 * - Second parameter COULD be an index?????
16 * - Third parameter.... ?????????????????????
19 * - ImageList_Draw, ImageList_DrawEx and ImageList_GetIcon use
20 * ImageList_DrawIndirect. Since ImageList_DrawIndirect is still
21 * partially imlemented, the functions mentioned above will be
22 * limited in functionality too.
25 /* This must be defined because the HIMAGELIST type is just a pointer
26 * to the _IMAGELIST data structure. But M$ does not want us to know
27 * anything about its contents. Applications just see a pointer to
28 * an empty structure. It's just to keep compatibility.
30 #define __WINE_IMAGELIST_C
33 #include "wine/obj_base.h"
34 #include "wine/obj_storage.h"
35 #include "imagelist.h"
37 #include "debugtools.h"
40 DEFAULT_DEBUG_CHANNEL(imagelist)
43 #define _MAX(a,b) (((a)>(b))?(a):(b))
44 #define _MIN(a,b) (((a)>(b))?(b):(a))
46 #define MAX_OVERLAYIMAGE 15
49 /* internal image list data used for Drag & Drop operations */
51 static HIMAGELIST himlInternalDrag = NULL;
52 static INT nInternalDragHotspotX = 0;
53 static INT nInternalDragHotspotY = 0;
55 static HWND hwndInternalDrag = 0;
56 static INT xInternalPos = 0;
57 static INT yInternalPos = 0;
59 static HDC hdcBackBuffer = 0;
60 static HBITMAP hbmBackBuffer = 0;
63 /*************************************************************************
64 * IMAGELIST_InternalExpandBitmaps [Internal]
66 * Expands the bitmaps of an image list by the given number of images.
69 * himl [I] handle to image list
70 * nImageCount [I] number of images to add
76 * This function can NOT be used to reduce the number of images.
79 IMAGELIST_InternalExpandBitmaps (HIMAGELIST himl, INT nImageCount)
81 HDC hdcImageList, hdcBitmap;
83 INT nNewWidth, nNewCount;
85 TRACE("Create expanded bitmaps!\n");
87 nNewCount = himl->cCurImage + nImageCount + himl->cGrow;
88 nNewWidth = nNewCount * himl->cx;
90 hdcImageList = CreateCompatibleDC (0);
91 hdcBitmap = CreateCompatibleDC (0);
94 CreateBitmap (nNewWidth, himl->cy, 1, himl->uBitsPixel, NULL);
95 if (hbmNewBitmap == 0)
96 ERR("creating new image bitmap!\n");
98 SelectObject (hdcImageList, himl->hbmImage);
99 SelectObject (hdcBitmap, hbmNewBitmap);
100 BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, himl->cy,
101 hdcImageList, 0, 0, SRCCOPY);
103 DeleteObject (himl->hbmImage);
104 himl->hbmImage = hbmNewBitmap;
108 CreateBitmap (nNewWidth, himl->cy, 1, 1, NULL);
110 if (hbmNewBitmap == 0)
111 ERR("creating new mask bitmap!");
113 SelectObject (hdcImageList, himl->hbmMask);
114 SelectObject (hdcBitmap, hbmNewBitmap);
115 BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, himl->cy,
116 hdcImageList, 0, 0, SRCCOPY);
117 DeleteObject (himl->hbmMask);
118 himl->hbmMask = hbmNewBitmap;
121 himl->cMaxImage = nNewCount;
123 DeleteDC (hdcImageList);
124 DeleteDC (hdcBitmap);
128 /*************************************************************************
129 * IMAGELIST_InternalDraw [Internal]
131 * Draws the image in the ImageList (without the mask)
134 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
135 * cx [I] the width of the image to display
136 * cy............[I] the height of the image to display
142 * This functions is used by ImageList_DrawIndirect, when it is
143 * required to draw only the Image (without the mask) to the screen.
145 * Blending and Overlays styles are accomplised by another function
148 IMAGELIST_InternalDraw(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
152 hImageDC = CreateCompatibleDC(0);
153 hOldBitmap = SelectObject(hImageDC, pimldp->himl->hbmImage);
154 BitBlt(pimldp->hdcDst,
155 pimldp->x, pimldp->y, cx, cy,
157 pimldp->himl->cx * pimldp->i, 0,
160 SelectObject(hImageDC, hOldBitmap);
165 /*************************************************************************
166 * IMAGELIST_InternalDrawMask [Internal]
168 * Draws the image in the ImageList witht the mask
171 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
172 * cx [I] the width of the image to display
173 * cy............[I] the height of the image to display
179 * This functions is used by ImageList_DrawIndirect, when it is
180 * required to draw the Image with the mask to the screen.
182 * Blending and Overlays styles are accomplised by another function.
185 IMAGELIST_InternalDrawMask(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
187 HDC hMaskDC, hImageDC;
188 BOOL bUseCustomBackground, bBlendFlag;
189 HBRUSH hBrush, hOldBrush;
190 HBITMAP hOldBitmapImage, hOldBitmapMask;
191 HIMAGELIST himlLocal = pimldp->himl;
192 COLORREF oldBkColor, oldFgColor;
194 bUseCustomBackground = (himlLocal->clrBk != CLR_NONE);
195 bBlendFlag = (pimldp->fStyle & ILD_BLEND50 )
196 || (pimldp->fStyle & ILD_BLEND25);
198 hImageDC = CreateCompatibleDC(0);
199 hMaskDC = CreateCompatibleDC(0);
201 hOldBitmapImage = SelectObject(hImageDC, himlLocal->hbmImage);
202 hOldBitmapMask = SelectObject(hMaskDC, himlLocal->hbmMask);
203 /* Draw the Background for the appropriate Styles
205 if( bUseCustomBackground && (pimldp->fStyle == ILD_NORMAL
206 || pimldp->fStyle & ILD_IMAGE
209 hBrush = CreateSolidBrush (himlLocal->clrBk);
210 hOldBrush = SelectObject (pimldp->hdcDst, hBrush);
211 PatBlt (pimldp->hdcDst,
212 pimldp->x, pimldp->y, cx, cy,
215 DeleteObject (SelectObject (pimldp->hdcDst, hOldBrush));
218 /* Draw Image Transparently over the current background
220 if(pimldp->fStyle == ILD_NORMAL
221 || pimldp->fStyle & ILD_TRANSPARENT
222 || ((pimldp->fStyle & ILD_IMAGE) && bUseCustomBackground)
225 /* to obtain a transparent look, background color should be set
226 to white and foreground color to black when blting the
228 oldBkColor = SetBkColor(pimldp->hdcDst, RGB(0xff, 0xff, 0xff));
229 oldFgColor = SetTextColor(pimldp->hdcDst, RGB(0, 0, 0));
231 BitBlt(pimldp->hdcDst,
232 pimldp->x, pimldp->y, cx, cy,
234 himlLocal->cx * pimldp->i, 0,
237 BitBlt(pimldp->hdcDst,
238 pimldp->x, pimldp->y, cx, cy,
240 himlLocal->cx * pimldp->i, 0,
243 SetBkColor(pimldp->hdcDst, oldBkColor);
244 SetTextColor(pimldp->hdcDst, oldFgColor);
246 /* Draw the image when no Background is specified
248 else if(pimldp->fStyle & ILD_IMAGE && !bUseCustomBackground)
250 BitBlt(pimldp->hdcDst,
251 pimldp->x, pimldp->y, cx, cy,
253 himlLocal->cx * pimldp->i, 0,
256 /* Draw the mask with or without a background
258 else if(pimldp->fStyle & ILD_MASK)
260 BitBlt(pimldp->hdcDst,
261 pimldp->x, pimldp->y, cx, cy,
263 himlLocal->cx * pimldp->i, 0,
264 bUseCustomBackground ? SRCCOPY : SRCAND);
266 SelectObject(hImageDC, hOldBitmapImage);
267 SelectObject(hMaskDC, hOldBitmapMask);
272 /*************************************************************************
273 * IMAGELIST_InternalDrawBlend [Internal]
275 * Draws the Blend over the current image
278 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
279 * cx [I] the width of the image to display
280 * cy............[I] the height of the image to display
286 * This functions is used by ImageList_DrawIndirect, when it is
287 * required to add the blend to the current image.
291 IMAGELIST_InternalDrawBlend(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
294 HDC hBlendMaskDC,hMaskDC;
295 HBRUSH hBlendColorBrush, hBlendBrush, hOldBrush;
296 HBITMAP hBlendMaskBitmap, hOldBitmap;
297 COLORREF clrBlend, OldTextColor, OldBkColor;
298 HIMAGELIST himlLocal = pimldp->himl;
300 clrBlend = GetSysColor (COLOR_HIGHLIGHT);
301 if (!(pimldp->rgbFg == CLR_DEFAULT))
303 clrBlend = pimldp->rgbFg;
305 /* Create the blend Mask
307 hBlendMaskDC = CreateCompatibleDC(0);
308 hBlendBrush = pimldp->fStyle & ILD_BLEND50 ?
309 himlLocal->hbrBlend50 : himlLocal->hbrBlend25;
311 hBlendMaskBitmap = CreateBitmap(cx, cy, 1, 1, NULL);
312 hOldBitmap = SelectObject(hBlendMaskDC, hBlendMaskBitmap);
314 hOldBrush = (HBRUSH) SelectObject(hBlendMaskDC, hBlendBrush);
315 PatBlt(hBlendMaskDC, 0, 0, cx, cy, PATCOPY);
316 SelectObject(hBlendMaskDC, hOldBrush);
318 /* Modify the blend mask if an Image Mask exist
320 if(pimldp->himl->hbmMask != 0)
322 HBITMAP hOldMaskBitmap;
323 hMaskDC = CreateCompatibleDC(0);
324 hOldMaskBitmap = (HBITMAP) SelectObject(hMaskDC, himlLocal->hbmMask);
329 himlLocal->cx * pimldp->i,0,
330 0x220326); /* NOTSRCAND */
338 SelectObject(hMaskDC, hOldMaskBitmap);
342 /* Apply blend to the current image given the BlendMask
344 OldTextColor = SetTextColor(pimldp->hdcDst, 0);
345 OldBkColor = SetBkColor(pimldp->hdcDst, RGB(255,255,255));
346 hBlendColorBrush = CreateSolidBrush(clrBlend);
347 hOldBrush = (HBRUSH) SelectObject (pimldp->hdcDst, hBlendColorBrush);
349 BitBlt (pimldp->hdcDst,
350 pimldp->x, pimldp->y, cx, cy,
353 0xB8074A); /* PSDPxax */
355 SelectObject(pimldp->hdcDst, hOldBrush);
356 SetTextColor(pimldp->hdcDst, OldTextColor);
357 SetBkColor(pimldp->hdcDst, OldBkColor);
358 SelectObject(hBlendMaskDC, hOldBitmap);
359 DeleteDC(hBlendMaskDC);
360 DeleteObject(hBlendMaskBitmap);
361 DeleteObject(hBlendColorBrush);
364 /*************************************************************************
365 * IMAGELIST_InternalDrawOverlay [Internal]
367 * Draws the overlay image
370 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
371 * cx [I] the width of the image to display
372 * cy............[I] the height of the image to display
378 * This functions is used by ImageList_DrawIndirect, when it is
379 * required to draw the overlay
384 IMAGELIST_InternalDrawOverlay(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
390 nOvlIdx = (pimldp->fStyle & 0x0700) >> 8;
391 if ((nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE))
393 nOvlIdx = pimldp->himl->nOvlIdx[nOvlIdx - 1];
394 if ((nOvlIdx >= 0) && (nOvlIdx <= pimldp->himl->cCurImage))
396 hImageDC = CreateCompatibleDC(0);
397 if (pimldp->himl->hbmMask)
399 hOldBitmap = (HBITMAP) SelectObject (hImageDC,
400 pimldp->himl->hbmMask);
402 BitBlt (pimldp->hdcDst,
403 pimldp->x, pimldp->y, cx, cy,
404 hImageDC, pimldp->himl->cx * nOvlIdx, 0,
407 SelectObject(hImageDC, hOldBitmap);
409 hOldBitmap = (HBITMAP) SelectObject (hImageDC,
410 pimldp->himl->hbmImage);
412 BitBlt (pimldp->hdcDst,
413 pimldp->x, pimldp->y, cx, cy,
415 pimldp->himl->cx * nOvlIdx, 0,
418 SelectObject(hImageDC, hOldBitmap);
428 /*************************************************************************
429 * ImageList_Add [COMCTL32.39]
431 * Add an image or images to an image list.
434 * himl [I] handle to image list
435 * hbmImage [I] handle to image bitmap
436 * hbmMask [I] handle to mask bitmap
439 * Success: Index of the first new image.
444 ImageList_Add (HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
446 HDC hdcImage, hdcBitmap;
447 INT nFirstIndex, nImageCount;
450 HBITMAP hOldBitmapImage, hOldBitmap;
452 if (!himl || !hbmImage)
455 GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
456 nImageCount = bmp.bmWidth / himl->cx;
458 if (himl->cCurImage + nImageCount >= himl->cMaxImage)
459 IMAGELIST_InternalExpandBitmaps (himl, nImageCount);
461 nStartX = himl->cCurImage * himl->cx;
463 hdcImage = CreateCompatibleDC(0);
464 hdcBitmap = CreateCompatibleDC(0);
466 hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
467 hOldBitmap = SelectObject(hdcBitmap, hbmImage);
469 /* Copy result to the imagelist
471 BitBlt (hdcImage, nStartX, 0, bmp.bmWidth, himl->cy,
472 hdcBitmap, 0, 0, SRCCOPY);
476 HDC hdcMask, hdcTemp, hOldBitmapMask, hOldBitmapTemp;
478 hdcMask = CreateCompatibleDC (0);
479 hdcTemp = CreateCompatibleDC(0);
480 hOldBitmapMask = (HBITMAP) SelectObject(hdcMask, himl->hbmMask);
481 hOldBitmapTemp = (HBITMAP) SelectObject(hdcTemp, hbmMask);
484 nStartX, 0, bmp.bmWidth, himl->cy,
489 SelectObject(hdcTemp, hOldBitmapTemp);
492 /* Remove the background from the image
495 nStartX, 0, bmp.bmWidth, himl->cy,
498 0x220326); /* NOTSRCAND */
500 SelectObject(hdcMask, hOldBitmapMask);
504 SelectObject(hdcImage, hOldBitmapImage);
505 SelectObject(hdcBitmap, hOldBitmap);
509 nFirstIndex = himl->cCurImage;
510 himl->cCurImage += nImageCount;
516 /*************************************************************************
517 * ImageList_AddIcon [COMCTL32.40]
519 * Adds an icon to an image list.
522 * himl [I] handle to image list
523 * hIcon [I] handle to icon
526 * Success: index of the new image
531 ImageList_AddIcon (HIMAGELIST himl, HICON hIcon)
533 return ImageList_ReplaceIcon (himl, -1, hIcon);
537 /*************************************************************************
538 * ImageList_AddMasked [COMCTL32.41]
540 * Adds an image or images to an image list and creates a mask from the
541 * specified bitmap using the mask color.
544 * himl [I] handle to image list.
545 * hBitmap [I] handle to bitmap
546 * clrMask [I] mask color.
549 * Success: Index of the first new image.
554 ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
556 HDC hdcImage, hdcMask, hdcBitmap;
557 INT nIndex, nImageCount, nMaskXOffset=0;
559 HBITMAP hOldBitmap, hOldBitmapMask, hOldBitmapImage;
560 HBITMAP hMaskBitmap=0;
566 if (!GetObjectA (hBitmap, sizeof(BITMAP), &bmp))
569 nImageCount = bmp.bmWidth / himl->cx;
571 if (himl->cCurImage + nImageCount >= himl->cMaxImage)
573 IMAGELIST_InternalExpandBitmaps (himl, nImageCount);
576 nIndex = himl->cCurImage;
577 himl->cCurImage += nImageCount;
579 hdcMask = CreateCompatibleDC (0);
580 hdcImage = CreateCompatibleDC(0);
581 hdcBitmap = CreateCompatibleDC(0);
584 hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
585 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
588 hOldBitmapMask = SelectObject(hdcMask, himl->hbmMask);
589 nMaskXOffset = nIndex * himl->cx;
594 Create a temp Mask so we can remove the background of
595 the Image (Windows does this even if there is no mask)
597 hMaskBitmap = CreateBitmap(bmp.bmWidth, himl->cy, 1, 1, NULL);
598 hOldBitmapMask = SelectObject(hdcMask, hMaskBitmap);
601 /* create monochrome image to the mask bitmap */
602 bkColor = (clrMask != CLR_DEFAULT) ? clrMask :
603 GetPixel (hdcBitmap, 0, 0);
604 SetBkColor (hdcBitmap, bkColor);
606 nMaskXOffset, 0, bmp.bmWidth, himl->cy,
610 SetBkColor(hdcBitmap, RGB(255,255,255));
611 /*Remove the background from the image
614 WINDOWS BUG ALERT!!!!!!
615 The statement below should not be done in common practice
616 but this is how ImageList_AddMasked works in Windows.
617 It overwrites the original bitmap passed, this was discovered
618 by using the same bitmap to itterated the different styles
619 on windows where it failed (BUT ImageList_Add is OK)
620 This is here in case some apps really on this bug
623 0, 0, bmp.bmWidth, himl->cy,
626 0x220326); /* NOTSRCAND */
627 /* Copy result to the imagelist
630 nIndex * himl->cx, 0, bmp.bmWidth, himl->cy,
636 SelectObject(hdcMask,hOldBitmapMask);
637 SelectObject(hdcImage, hOldBitmapImage);
638 SelectObject(hdcBitmap, hOldBitmap);
644 DeleteObject(hMaskBitmap);
651 /*************************************************************************
652 * ImageList_BeginDrag [COMCTL32.42]
654 * Creates a temporary image list that contains one image. It will be used
658 * himlTrack [I] handle to the source image list
659 * iTrack [I] index of the drag image in the source image list
660 * dxHotspot [I] X position of the hot spot of the drag image
661 * dyHotspot [I] Y position of the hot spot of the drag image
669 ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
670 INT dxHotspot, INT dyHotspot)
674 FIXME("partially implemented!\n");
676 if (himlTrack == NULL)
679 if (himlInternalDrag)
680 ImageList_EndDrag ();
683 ImageList_Create (himlTrack->cx, himlTrack->cy,
684 himlTrack->flags, 1, 1);
685 if (himlInternalDrag == NULL) {
686 ERR("Error creating drag image list!\n");
690 nInternalDragHotspotX = dxHotspot;
691 nInternalDragHotspotY = dyHotspot;
693 hdcSrc = CreateCompatibleDC (0);
694 hdcDst = CreateCompatibleDC (0);
697 SelectObject (hdcSrc, himlTrack->hbmImage);
698 SelectObject (hdcDst, himlInternalDrag->hbmImage);
699 StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
700 iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
703 SelectObject (hdcSrc, himlTrack->hbmMask);
704 SelectObject (hdcDst, himlInternalDrag->hbmMask);
705 StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
706 iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
711 himlInternalDrag->cCurImage = 1;
717 /*************************************************************************
718 * ImageList_Copy [COMCTL32.43]
720 * Copies an image of the source image list to an image of the
721 * destination image list. Images can be copied or swapped.
724 * himlDst [I] handle to the destination image list
725 * iDst [I] destination image index.
726 * himlSrc [I] handle to the source image list
727 * iSrc [I] source image index
728 * uFlags [I] flags for the copy operation
735 * Copying from one image list to another is possible. The original
736 * implementation just copies or swapps within one image list.
737 * Could this feature become a bug??? ;-)
741 ImageList_Copy (HIMAGELIST himlDst, INT iDst, HIMAGELIST himlSrc,
742 INT iSrc, INT uFlags)
746 TRACE("iDst=%d iSrc=%d\n", iDst, iSrc);
748 if ((himlSrc == NULL) || (himlDst == NULL))
750 if ((iDst < 0) || (iDst >= himlDst->cCurImage))
752 if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage))
755 hdcSrc = CreateCompatibleDC (0);
756 if (himlDst == himlSrc)
759 hdcDst = CreateCompatibleDC (0);
761 if (uFlags & ILCF_SWAP) {
763 HBITMAP hbmTempImage, hbmTempMask;
765 /* create temporary bitmaps */
766 hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
767 himlSrc->uBitsPixel, NULL);
768 hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
771 /* copy (and stretch) destination to temporary bitmaps.(save) */
773 SelectObject (hdcSrc, himlDst->hbmImage);
774 SelectObject (hdcDst, hbmTempImage);
775 StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
776 hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
779 SelectObject (hdcSrc, himlDst->hbmMask);
780 SelectObject (hdcDst, hbmTempMask);
781 StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
782 hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
785 /* copy (and stretch) source to destination */
787 SelectObject (hdcSrc, himlSrc->hbmImage);
788 SelectObject (hdcDst, himlDst->hbmImage);
789 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
790 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
793 SelectObject (hdcSrc, himlSrc->hbmMask);
794 SelectObject (hdcDst, himlDst->hbmMask);
795 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
796 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
799 /* copy (without stretching) temporary bitmaps to source (restore) */
801 SelectObject (hdcSrc, hbmTempImage);
802 SelectObject (hdcDst, himlSrc->hbmImage);
803 BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
804 hdcSrc, 0, 0, SRCCOPY);
806 SelectObject (hdcSrc, hbmTempMask);
807 SelectObject (hdcDst, himlSrc->hbmMask);
808 BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
809 hdcSrc, 0, 0, SRCCOPY);
811 /* delete temporary bitmaps */
812 DeleteObject (hbmTempMask);
813 DeleteObject (hbmTempImage);
817 SelectObject (hdcSrc, himlSrc->hbmImage);
818 if (himlSrc == himlDst)
821 SelectObject (hdcDst, himlDst->hbmImage);
822 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
823 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
827 SelectObject (hdcSrc, himlSrc->hbmMask);
828 if (himlSrc == himlDst)
831 SelectObject (hdcDst, himlDst->hbmMask);
832 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
833 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
838 if (himlSrc != himlDst)
845 /*************************************************************************
846 * ImageList_Create [COMCTL32.44] Creates a new image list.
849 * cx [I] image height
851 * flags [I] creation flags
852 * cInitial [I] initial number of images in the image list
853 * cGrow [I] number of images by which image list grows
856 * Success: Handle to the created image list
861 ImageList_Create (INT cx, INT cy, UINT flags,
862 INT cInitial, INT cGrow)
868 static WORD aBitBlend25[] =
869 {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00};
871 static WORD aBitBlend50[] =
872 {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
874 TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow);
876 himl = (HIMAGELIST)COMCTL32_Alloc (sizeof(struct _IMAGELIST));
883 himl->cMaxImage = cInitial + cGrow;
884 himl->cInitial = cInitial;
887 himl->clrFg = CLR_DEFAULT;
888 himl->clrBk = CLR_NONE;
890 /* initialize overlay mask indices */
891 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
892 himl->nOvlIdx[nCount] = -1;
894 hdc = CreateCompatibleDC (0);
895 himl->uBitsPixel = (UINT)GetDeviceCaps (hdc, BITSPIXEL);
898 TRACE("Image: %d Bits per Pixel\n", himl->uBitsPixel);
900 if (himl->cMaxImage > 0) {
902 CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
903 1, himl->uBitsPixel, NULL);
904 if (himl->hbmImage == 0) {
905 ERR("Error creating image bitmap!\n");
912 if ( (himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) {
913 himl->hbmMask = CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
915 if (himl->hbmMask == 0) {
916 ERR("Error creating mask bitmap!\n");
918 DeleteObject (himl->hbmImage);
925 /* create blending brushes */
926 hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend25);
927 himl->hbrBlend25 = CreatePatternBrush (hbmTemp);
928 DeleteObject (hbmTemp);
930 hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend50);
931 himl->hbrBlend50 = CreatePatternBrush (hbmTemp);
932 DeleteObject (hbmTemp);
938 /*************************************************************************
939 * ImageList_Destroy [COMCTL32.45]
941 * Destroys an image list.
944 * himl [I] handle to image list
952 ImageList_Destroy (HIMAGELIST himl)
957 /* delete image bitmaps */
959 DeleteObject (himl->hbmImage);
961 DeleteObject (himl->hbmMask);
963 /* delete blending brushes */
964 if (himl->hbrBlend25)
965 DeleteObject (himl->hbrBlend25);
966 if (himl->hbrBlend50)
967 DeleteObject (himl->hbrBlend50);
969 COMCTL32_Free (himl);
975 /*************************************************************************
976 * ImageList_DragEnter [COMCTL32.46]
978 * Locks window update and displays the drag image at the given position.
981 * hwndLock [I] handle of the window that owns the drag image.
982 * x [I] X position of the drag image.
983 * y [I] Y position of the drag image.
990 * The position of the drag image is relative to the window, not
995 ImageList_DragEnter (HWND hwndLock, INT x, INT y)
997 if (himlInternalDrag == NULL)
1001 hwndInternalDrag = hwndLock;
1003 hwndInternalDrag = GetDesktopWindow ();
1008 hdcBackBuffer = CreateCompatibleDC (0);
1009 hbmBackBuffer = CreateCompatibleBitmap (hdcBackBuffer,
1010 himlInternalDrag->cx, himlInternalDrag->cy);
1012 ImageList_DragShowNolock (TRUE);
1018 /*************************************************************************
1019 * ImageList_DragLeave [COMCTL32.47]
1021 * Unlocks window update and hides the drag image.
1024 * hwndLock [I] handle of the window that owns the drag image.
1032 ImageList_DragLeave (HWND hwndLock)
1035 hwndInternalDrag = hwndLock;
1037 hwndInternalDrag = GetDesktopWindow ();
1039 ImageList_DragShowNolock (FALSE);
1041 DeleteDC (hdcBackBuffer);
1042 DeleteObject (hbmBackBuffer);
1048 /*************************************************************************
1049 * ImageList_DragMove [COMCTL32.48]
1051 * Moves the drag image.
1054 * x [I] X position of the drag image.
1055 * y [I] Y position of the drag image.
1062 * The position of the drag image is relative to the window, not
1067 ImageList_DragMove (INT x, INT y)
1069 ImageList_DragShowNolock (FALSE);
1074 ImageList_DragShowNolock (TRUE);
1080 /*************************************************************************
1081 * ImageList_DragShowNolock [COMCTL32.49]
1083 * Shows or hides the drag image.
1086 * bShow [I] TRUE shows the drag image, FALSE hides it.
1097 ImageList_DragShowNolock (BOOL bShow)
1101 FIXME("semi-stub!\n");
1102 TRACE("bShow=0x%X!\n", bShow);
1104 hdcDrag = GetDCEx (hwndInternalDrag, 0,
1105 DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
1108 /* show drag image */
1110 /* save background */
1112 /* draw drag image */
1116 /* hide drag image */
1118 /* restore background */
1122 ReleaseDC (hwndInternalDrag, hdcDrag);
1128 /*************************************************************************
1129 * ImageList_Draw [COMCTL32.50] Draws an image.
1132 * himl [I] handle to image list
1134 * hdc [I] handle to device context
1137 * fStyle [I] drawing flags
1144 * Calls ImageList_DrawIndirect.
1147 * ImageList_DrawIndirect.
1151 ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc,
1152 INT x, INT y, UINT fStyle)
1154 IMAGELISTDRAWPARAMS imldp;
1156 imldp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
1166 imldp.rgbBk = CLR_DEFAULT;
1167 imldp.rgbFg = CLR_DEFAULT;
1168 imldp.fStyle = fStyle;
1171 return ImageList_DrawIndirect (&imldp);
1175 /*************************************************************************
1176 * ImageList_DrawEx [COMCTL32.51]
1178 * Draws an image and allows to use extended drawing features.
1181 * himl [I] handle to image list
1183 * hdc [I] handle to device context
1186 * xOffs [I] X offset
1187 * yOffs [I] Y offset
1188 * rgbBk [I] background color
1189 * rgbFg [I] foreground color
1190 * fStyle [I] drawing flags
1197 * Calls ImageList_DrawIndirect.
1200 * ImageList_DrawIndirect.
1204 ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y,
1205 INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg,
1208 IMAGELISTDRAWPARAMS imldp;
1210 imldp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
1220 imldp.rgbBk = rgbBk;
1221 imldp.rgbFg = rgbFg;
1222 imldp.fStyle = fStyle;
1225 return ImageList_DrawIndirect (&imldp);
1229 /*************************************************************************
1230 * ImageList_DrawIndirect [COMCTL32.52]
1232 * Draws an image using ...
1235 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
1243 ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
1247 Do some Error Checking
1251 if (pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS))
1253 if (pimldp->himl == NULL)
1255 if ((pimldp->i < 0) || (pimldp->i > pimldp->himl->cCurImage))
1258 Get the Height and Width to display
1260 cx = (pimldp->cx == 0) ? pimldp->himl->cx : pimldp->cx;
1261 cy = (pimldp->cy == 0) ? pimldp->himl->cy : pimldp->cy;
1265 if(pimldp->himl->hbmMask != 0)
1267 IMAGELIST_InternalDrawMask(pimldp, cx, cy);
1271 IMAGELIST_InternalDraw(pimldp, cx, cy);
1274 Apply the blend if needed to the Image
1276 if((pimldp->fStyle & ILD_BLEND50)
1277 || (pimldp->fStyle & ILD_BLEND25))
1279 IMAGELIST_InternalDrawBlend(pimldp, cx, cy);
1282 Apply the Overlay if needed
1284 if (pimldp->fStyle & 0x0700)
1286 IMAGELIST_InternalDrawOverlay(pimldp, cx, cy);
1293 /*************************************************************************
1294 * ImageList_Duplicate [COMCTL32.53] Duplicates an image list.
1297 * himlSrc [I] source image list handle
1300 * Success: Handle of duplicated image list.
1305 ImageList_Duplicate (HIMAGELIST himlSrc)
1310 if (himlSrc == NULL) {
1311 ERR("Invalid image list handle!\n");
1315 himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
1316 himlSrc->cInitial, himlSrc->cGrow);
1320 hdcSrc = CreateCompatibleDC (0);
1321 hdcDst = CreateCompatibleDC (0);
1322 SelectObject (hdcSrc, himlSrc->hbmImage);
1323 SelectObject (hdcDst, himlDst->hbmImage);
1324 BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy,
1325 hdcSrc, 0, 0, SRCCOPY);
1327 if (himlDst->hbmMask)
1329 SelectObject (hdcSrc, himlSrc->hbmMask);
1330 SelectObject (hdcDst, himlDst->hbmMask);
1331 BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx,
1332 himlSrc->cy, hdcSrc, 0, 0, SRCCOPY);
1343 /*************************************************************************
1344 * ImageList_EndDrag [COMCTL32.54] Finishes a drag operation.
1346 * Finishes a drag operation.
1360 ImageList_EndDrag (void)
1362 FIXME("semi-stub!\n");
1364 if (himlInternalDrag)
1367 ImageList_Destroy (himlInternalDrag);
1368 himlInternalDrag = NULL;
1370 nInternalDragHotspotX = 0;
1371 nInternalDragHotspotY = 0;
1379 /*************************************************************************
1380 * ImageList_GetBkColor [COMCTL32.55]
1382 * Returns the background color of an image list.
1385 * himl [I] Image list handle.
1388 * Success: background color
1393 ImageList_GetBkColor (HIMAGELIST himl)
1402 /*************************************************************************
1403 * ImageList_GetDragImage [COMCTL32.56]
1405 * Returns the handle to the internal drag image list.
1408 * ppt [O] Pointer to the drag position. Can be NULL.
1409 * pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
1412 * Success: Handle of the drag image list.
1420 ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot)
1422 FIXME("semi-stub!\n");
1424 if (himlInternalDrag)
1425 return (himlInternalDrag);
1431 /*************************************************************************
1432 * ImageList_GetIcon [COMCTL32.57]
1434 * Creates an icon from a masked image of an image list.
1437 * himl [I] handle to image list
1439 * flags [I] drawing style flags
1442 * Success: icon handle
1447 ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle)
1451 HBITMAP hOldSrcBitmap,hOldDstBitmap;
1454 if ((himl == NULL) || (i < 0) || (i >= himl->cCurImage))
1457 hdcSrc = CreateCompatibleDC(0);
1458 hdcDst = CreateCompatibleDC(0);
1461 ii.hbmMask = CreateCompatibleBitmap (hdcDst, himl->cx, himl->cy);
1464 hOldDstBitmap = (HBITMAP)SelectObject (hdcDst, ii.hbmMask);
1465 if (himl->hbmMask) {
1466 SelectObject (hdcSrc, himl->hbmMask);
1467 BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1468 hdcSrc, i * himl->cx, 0, SRCCOPY);
1471 PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS);
1474 hOldSrcBitmap = (HBITMAP)SelectObject (hdcSrc, himl->hbmImage);
1475 ii.hbmColor = CreateCompatibleBitmap (hdcSrc, himl->cx, himl->cy);
1476 SelectObject (hdcDst, ii.hbmColor);
1477 BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1478 hdcSrc, i * himl->cx, 0, SRCCOPY);
1481 * CreateIconIndirect requires us to deselect the bitmaps from
1482 * the DCs before calling
1484 SelectObject(hdcSrc, hOldSrcBitmap);
1485 SelectObject(hdcDst, hOldDstBitmap);
1487 hIcon = CreateIconIndirect (&ii);
1491 DeleteObject (ii.hbmMask);
1492 DeleteObject (ii.hbmColor);
1498 /*************************************************************************
1499 * ImageList_GetIconSize [COMCTL32.58]
1501 * Retrieves the size of an image in an image list.
1504 * himl [I] handle to image list
1505 * cx [O] pointer to the image width.
1506 * cy [O] pointer to the image height.
1513 * All images in an image list have the same size.
1517 ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy)
1521 if ((himl->cx <= 0) || (himl->cy <= 0))
1533 /*************************************************************************
1534 * ImageList_GetImageCount [COMCTL32.59]
1536 * Returns the number of images in an image list.
1539 * himl [I] handle to image list
1542 * Success: Number of images.
1547 ImageList_GetImageCount (HIMAGELIST himl)
1552 return himl->cCurImage;
1556 /*************************************************************************
1557 * ImageList_GetImageInfo [COMCTL32.60]
1559 * Returns information about an image in an image list.
1562 * himl [I] handle to image list
1564 * pImageInfo [O] pointer to the image information
1572 ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
1574 if ((himl == NULL) || (pImageInfo == NULL))
1576 if ((i < 0) || (i >= himl->cCurImage))
1579 pImageInfo->hbmImage = himl->hbmImage;
1580 pImageInfo->hbmMask = himl->hbmMask;
1582 pImageInfo->rcImage.top = 0;
1583 pImageInfo->rcImage.bottom = himl->cy;
1584 pImageInfo->rcImage.left = i * himl->cx;
1585 pImageInfo->rcImage.right = (i+1) * himl->cx;
1591 /*************************************************************************
1592 * ImageList_GetImageRect [COMCTL32.61]
1594 * Retrieves the rectangle of the specified image in an image list.
1597 * himl [I] handle to image list
1599 * lpRect [O] pointer to the image rectangle
1606 * This is an UNDOCUMENTED function!!!
1610 ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect)
1612 if ((himl == NULL) || (lpRect == NULL))
1614 if ((i < 0) || (i >= himl->cCurImage))
1617 lpRect->left = i * himl->cx;
1619 lpRect->right = lpRect->left + himl->cx;
1620 lpRect->bottom = himl->cy;
1626 /*************************************************************************
1627 * ImageList_LoadImage32A [COMCTL32.63][COMCTL32.62]
1629 * Creates an image list from a bitmap, icon or cursor.
1632 * hi [I] instance handle
1633 * lpbmp [I] name or id of the image
1634 * cx [I] width of each image
1635 * cGrow [I] number of images to expand
1636 * clrMask [I] mask color
1637 * uType [I] type of image to load
1638 * uFlags [I] loading flags
1641 * Success: handle to the loaded image list
1649 ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx, INT cGrow,
1650 COLORREF clrMask, UINT uType, UINT uFlags)
1652 HIMAGELIST himl = NULL;
1656 handle = LoadImageA (hi, lpbmp, uType, 0, 0, uFlags);
1658 ERR("Error loading image!\n");
1662 if (uType == IMAGE_BITMAP) {
1664 GetObjectA (handle, sizeof(BITMAP), &bmp);
1666 /* To match windows behavior, if cx is set to zero and
1667 the flag DI_DEFAULTSIZE is specified, cx becomes the
1668 system metric value for icons. If the flag is not specified
1669 the function sets the size to the height of the bitmap */
1672 if (uFlags & DI_DEFAULTSIZE)
1673 cx = GetSystemMetrics (SM_CXICON);
1678 nImageCount = bmp.bmWidth / cx;
1680 himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1681 nImageCount, cGrow);
1682 ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1684 else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1688 GetIconInfo (handle, &ii);
1689 GetObjectA (ii.hbmColor, sizeof(BITMAP), (LPVOID)&bmp);
1690 himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1691 ILC_MASK | ILC_COLOR, 1, cGrow);
1692 ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1693 DeleteObject (ii.hbmColor);
1694 DeleteObject (ii.hbmMask);
1697 DeleteObject (handle);
1703 /*************************************************************************
1704 * ImageList_LoadImage32W [COMCTL32.64]
1706 * Creates an image list from a bitmap, icon or cursor.
1709 * hi [I] instance handle
1710 * lpbmp [I] name or id of the image
1711 * cx [I] width of each image
1712 * cGrow [I] number of images to expand
1713 * clrMask [I] mask color
1714 * uType [I] type of image to load
1715 * uFlags [I] loading flags
1718 * Success: handle to the loaded image list
1726 ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow,
1727 COLORREF clrMask, UINT uType, UINT uFlags)
1729 HIMAGELIST himl = NULL;
1733 handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags);
1735 ERR("Error loading image!\n");
1739 if (uType == IMAGE_BITMAP) {
1741 GetObjectA (handle, sizeof(BITMAP), &bmp);
1742 nImageCount = bmp.bmWidth / cx;
1744 himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1745 nImageCount, cGrow);
1746 ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1748 else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1752 GetIconInfo (handle, &ii);
1753 GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
1754 himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1755 ILC_MASK | ILC_COLOR, 1, cGrow);
1756 ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1757 DeleteObject (ii.hbmColor);
1758 DeleteObject (ii.hbmMask);
1761 DeleteObject (handle);
1767 /*************************************************************************
1768 * ImageList_Merge [COMCTL32.65]
1770 * Creates a new image list that contains a merged image from the specified
1771 * images of both source image lists.
1774 * himl1 [I] handle to first image list
1775 * i1 [I] first image index
1776 * himl2 [I] handle to second image list
1777 * i2 [I] second image index
1778 * dx [I] X offset of the second image relative to the first.
1779 * dy [I] Y offset of the second image relative to the first.
1782 * Success: handle of the merged image list.
1787 ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
1790 HIMAGELIST himlDst = NULL;
1791 HDC hdcSrcImage, hdcDstImage;
1793 INT xOff1, yOff1, xOff2, yOff2;
1796 if ((himl1 == NULL) || (himl2 == NULL))
1800 if ((i1 < 0) || (i1 >= himl1->cCurImage)) {
1801 ERR("Index 1 out of range! %d\n", i1);
1805 if ((i2 < 0) || (i2 >= himl2->cCurImage)) {
1806 ERR("Index 2 out of range! %d\n", i2);
1811 cxDst = _MAX (himl1->cx, dx + himl2->cx);
1816 cxDst = _MAX (himl2->cx, himl1->cx - dx);
1821 cxDst = _MAX (himl1->cx, himl2->cx);
1827 cyDst = _MAX (himl1->cy, dy + himl2->cy);
1832 cyDst = _MAX (himl2->cy, himl1->cy - dy);
1837 cyDst = _MAX (himl1->cy, himl2->cy);
1842 himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
1845 hdcSrcImage = CreateCompatibleDC (0);
1846 hdcDstImage = CreateCompatibleDC (0);
1847 nX1 = i1 * himl1->cx;
1848 nX2 = i2 * himl2->cx;
1851 SelectObject (hdcSrcImage, himl1->hbmImage);
1852 SelectObject (hdcDstImage, himlDst->hbmImage);
1853 BitBlt (hdcDstImage, 0, 0, cxDst, cyDst,
1854 hdcSrcImage, 0, 0, BLACKNESS);
1855 BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy,
1856 hdcSrcImage, nX1, 0, SRCCOPY);
1858 SelectObject (hdcSrcImage, himl2->hbmMask);
1859 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1860 hdcSrcImage, nX2, 0, SRCAND);
1862 SelectObject (hdcSrcImage, himl2->hbmImage);
1863 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1864 hdcSrcImage, nX2, 0, SRCPAINT);
1867 SelectObject (hdcSrcImage, himl1->hbmMask);
1868 SelectObject (hdcDstImage, himlDst->hbmMask);
1869 BitBlt (hdcDstImage, 0, 0, cxDst, cyDst,
1870 hdcSrcImage, 0, 0, WHITENESS);
1871 BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy,
1872 hdcSrcImage, nX1, 0, SRCCOPY);
1874 SelectObject (hdcSrcImage, himl2->hbmMask);
1875 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1876 hdcSrcImage, nX2, 0, SRCAND);
1878 DeleteDC (hdcSrcImage);
1879 DeleteDC (hdcDstImage);
1886 /*************************************************************************
1887 * ImageList_Read [COMCTL32.66]
1889 * Reads an image list from a stream.
1892 * pstm [I] pointer to a stream
1895 * Success: handle to image list
1899 * This function can not be implemented yet, because
1900 * IStream32::Read is not implemented yet.
1906 HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
1914 FIXME("empty stub!\n");
1916 errCode = IStream_Read (pstm, &ilHead, sizeof(ILHEAD), &ulRead);
1917 if (errCode != S_OK)
1920 FIXME("Magic: 0x%x\n", ilHead.usMagic);
1922 himl = ImageList_Create (32, 32, ILD_NORMAL, 2, 2);
1928 /*************************************************************************
1929 * ImageList_Remove [COMCTL32.67] Removes an image from an image list
1932 * himl [I] image list handle
1941 ImageList_Remove (HIMAGELIST himl, INT i)
1943 HBITMAP hbmNewImage, hbmNewMask;
1947 if ((i < -1) || (i >= himl->cCurImage)) {
1948 ERR("index out of range! %d\n", i);
1952 if (himl->cCurImage == 0) {
1953 ERR("image list is already empty!\n");
1959 TRACE("remove all!\n");
1961 himl->cMaxImage = himl->cInitial + himl->cGrow;
1962 himl->cCurImage = 0;
1963 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
1964 himl->nOvlIdx[nCount] = -1;
1966 DeleteObject (himl->hbmImage);
1968 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
1969 1, himl->uBitsPixel, NULL);
1971 if (himl->hbmMask) {
1972 DeleteObject (himl->hbmMask);
1974 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
1979 /* delete one image */
1980 TRACE("Remove single image! %d\n", i);
1982 /* create new bitmap(s) */
1983 cxNew = (himl->cCurImage + himl->cGrow - 1) * himl->cx;
1985 TRACE(" - Number of images: %d / %d (Old/New)\n",
1986 himl->cCurImage, himl->cCurImage - 1);
1987 TRACE(" - Max. number of images: %d / %d (Old/New)\n",
1988 himl->cMaxImage, himl->cCurImage + himl->cGrow - 1);
1991 CreateBitmap (cxNew, himl->cy, 1, himl->uBitsPixel, NULL);
1994 hbmNewMask = CreateBitmap (cxNew, himl->cy, 1, 1, NULL);
1996 hbmNewMask = 0; /* Just to keep compiler happy! */
1998 hdcSrc = CreateCompatibleDC (0);
1999 hdcDst = CreateCompatibleDC (0);
2001 /* copy all images and masks prior to the "removed" image */
2003 TRACE("Pre image copy: Copy %d images\n", i);
2005 SelectObject (hdcSrc, himl->hbmImage);
2006 SelectObject (hdcDst, hbmNewImage);
2007 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2008 hdcSrc, 0, 0, SRCCOPY);
2010 if (himl->hbmMask) {
2011 SelectObject (hdcSrc, himl->hbmMask);
2012 SelectObject (hdcDst, hbmNewMask);
2013 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2014 hdcSrc, 0, 0, SRCCOPY);
2018 /* copy all images and masks behind the removed image */
2019 if (i < himl->cCurImage - 1) {
2020 TRACE("Post image copy!\n");
2021 SelectObject (hdcSrc, himl->hbmImage);
2022 SelectObject (hdcDst, hbmNewImage);
2023 BitBlt (hdcDst, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx,
2024 himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2026 if (himl->hbmMask) {
2027 SelectObject (hdcSrc, himl->hbmMask);
2028 SelectObject (hdcDst, hbmNewMask);
2029 BitBlt (hdcDst, i * himl->cx, 0,
2030 (himl->cCurImage - i - 1) * himl->cx,
2031 himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2038 /* delete old images and insert new ones */
2039 DeleteObject (himl->hbmImage);
2040 himl->hbmImage = hbmNewImage;
2041 if (himl->hbmMask) {
2042 DeleteObject (himl->hbmMask);
2043 himl->hbmMask = hbmNewMask;
2047 himl->cMaxImage = himl->cCurImage + himl->cGrow;
2054 /*************************************************************************
2055 * ImageList_Replace [COMCTL32.68]
2057 * Replaces an image in an image list with a new image.
2060 * himl [I] handle to image list
2062 * hbmImage [I] handle to image bitmap
2063 * hbmMask [I] handle to mask bitmap. Can be NULL.
2071 ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage,
2074 HDC hdcImageList, hdcImage;
2078 ERR("Invalid image list handle!\n");
2082 if ((i >= himl->cCurImage) || (i < 0)) {
2083 ERR("Invalid image index!\n");
2087 hdcImageList = CreateCompatibleDC (0);
2088 hdcImage = CreateCompatibleDC (0);
2089 GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
2092 SelectObject (hdcImageList, himl->hbmImage);
2093 SelectObject (hdcImage, hbmImage);
2095 StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2096 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2101 SelectObject (hdcImageList, himl->hbmMask);
2102 SelectObject (hdcImage, hbmMask);
2104 StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2105 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2108 DeleteDC (hdcImage);
2109 DeleteDC (hdcImageList);
2115 /*************************************************************************
2116 * ImageList_ReplaceIcon [COMCTL32.69]
2118 * Replaces an image in an image list using an icon.
2121 * himl [I] handle to image list
2123 * hIcon [I] handle to icon
2126 * Success: index of the replaced image
2131 ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon)
2133 HDC hdcImageList, hdcImage;
2136 HBITMAP hbmOldSrc, hbmOldDst;
2140 TRACE("(0x%lx 0x%x 0x%x)\n", (DWORD)himl, i, hIcon);
2144 if ((i >= himl->cCurImage) || (i < -1))
2147 hBestFitIcon = CopyImage(
2150 LR_COPYFROMRESOURCE);
2152 GetIconInfo (hBestFitIcon, &ii);
2153 if (ii.hbmMask == 0)
2155 if (ii.hbmColor == 0)
2157 GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
2160 if (himl->cCurImage + 1 >= himl->cMaxImage)
2161 IMAGELIST_InternalExpandBitmaps (himl, 1);
2163 nIndex = himl->cCurImage;
2169 hdcImageList = CreateCompatibleDC (0);
2170 TRACE("hdcImageList=0x%x!\n", hdcImageList);
2171 if (hdcImageList == 0)
2172 ERR("invalid hdcImageList!\n");
2174 hdcImage = CreateCompatibleDC (0);
2175 TRACE("hdcImage=0x%x!\n", hdcImage);
2177 ERR("invalid hdcImage!\n");
2179 hbmOldDst = SelectObject (hdcImageList, himl->hbmImage);
2180 SetTextColor( hdcImageList, RGB(0,0,0));
2181 SetBkColor( hdcImageList, RGB(255,255,255));
2182 hbmOldSrc = SelectObject (hdcImage, ii.hbmColor);
2183 StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2184 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2186 if (himl->hbmMask) {
2187 SelectObject (hdcImageList, himl->hbmMask);
2188 SelectObject (hdcImage, ii.hbmMask);
2189 StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2190 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2193 SelectObject (hdcImage, hbmOldSrc);
2194 SelectObject (hdcImageList, hbmOldDst);
2197 DestroyIcon(hBestFitIcon);
2199 DeleteDC (hdcImageList);
2201 DeleteDC (hdcImage);
2203 DeleteObject (ii.hbmColor);
2205 DeleteObject (ii.hbmMask);
2211 /*************************************************************************
2212 * ImageList_SetBkColor [COMCTL32.70]
2214 * Sets the background color of an image list.
2217 * himl [I] handle to image list
2218 * clrBk [I] background color
2221 * Success: previous background color
2226 ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
2233 clrOldBk = himl->clrBk;
2234 himl->clrBk = clrBk;
2239 /*************************************************************************
2240 * ImageList_SetDragCursorImage [COMCTL32.75]
2242 * Combines the specified image with the current drag image
2245 * himlDrag [I] handle to drag image list
2246 * iDrag [I] drag image index
2247 * dxHotspot [I] X position of the hot spot
2248 * dyHotspot [I] Y position of the hot spot
2259 ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag,
2260 INT dxHotspot, INT dyHotspot)
2262 HIMAGELIST himlTemp;
2264 FIXME("semi-stub!\n");
2266 if (himlInternalDrag == NULL)
2269 TRACE(" dxH=%d dyH=%d nX=%d nY=%d\n",
2270 dxHotspot, dyHotspot, nInternalDragHotspotX, nInternalDragHotspotY);
2272 himlTemp = ImageList_Merge (himlInternalDrag, 0, himlDrag, iDrag,
2273 dxHotspot, dyHotspot);
2275 ImageList_Destroy (himlInternalDrag);
2276 himlInternalDrag = himlTemp;
2278 nInternalDragHotspotX = dxHotspot;
2279 nInternalDragHotspotY = dyHotspot;
2285 /*************************************************************************
2286 * ImageList_SetFilter [COMCTL32.76]
2288 * Sets a filter (or does something completely different)!!???
2291 * himl [I] handle to image list
2297 * Failure: FALSE ???
2300 * This is an UNDOCUMENTED function!!!!
2305 ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter)
2307 FIXME("(%p 0x%x 0x%lx):empty stub!\n",
2314 /*************************************************************************
2315 * ImageList_SetIconSize [COMCTL32.77]
2317 * Sets the image size of the bitmap and deletes all images.
2320 * himl [I] handle to image list
2321 * cx [I] image width
2322 * cy [I] image height
2330 ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy)
2337 /* remove all images*/
2338 himl->cMaxImage = himl->cInitial + himl->cGrow;
2339 himl->cCurImage = 0;
2343 /* initialize overlay mask indices */
2344 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2345 himl->nOvlIdx[nCount] = -1;
2347 DeleteObject (himl->hbmImage);
2349 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2350 1, himl->uBitsPixel, NULL);
2352 if (himl->hbmMask) {
2353 DeleteObject (himl->hbmMask);
2355 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2363 /*************************************************************************
2364 * ImageList_SetImageCount [COMCTL32.78]
2366 * Resizes an image list to the specified number of images.
2369 * himl [I] handle to image list
2370 * iImageCount [I] number of images in the image list
2378 ImageList_SetImageCount (HIMAGELIST himl, INT iImageCount)
2380 HDC hdcImageList, hdcBitmap;
2381 HBITMAP hbmNewBitmap;
2382 INT nNewCount, nCopyCount;
2386 if (himl->cCurImage >= iImageCount)
2388 if (himl->cMaxImage > iImageCount)
2391 nNewCount = iImageCount + himl->cGrow;
2392 nCopyCount = _MIN(himl->cCurImage, iImageCount);
2394 hdcImageList = CreateCompatibleDC (0);
2395 hdcBitmap = CreateCompatibleDC (0);
2397 hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2398 1, himl->uBitsPixel, NULL);
2399 if (hbmNewBitmap != 0)
2401 SelectObject (hdcImageList, himl->hbmImage);
2402 SelectObject (hdcBitmap, hbmNewBitmap);
2405 BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2406 hdcImageList, 0, 0, SRCCOPY);
2408 /* delete 'empty' image space */
2409 SetBkColor (hdcBitmap, RGB(255, 255, 255));
2410 SetTextColor (hdcBitmap, RGB(0, 0, 0));
2411 PatBlt (hdcBitmap, nCopyCount * himl->cx, 0,
2412 (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2414 DeleteObject (himl->hbmImage);
2415 himl->hbmImage = hbmNewBitmap;
2418 ERR("Could not create new image bitmap !\n");
2422 hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2424 if (hbmNewBitmap != 0)
2426 SelectObject (hdcImageList, himl->hbmMask);
2427 SelectObject (hdcBitmap, hbmNewBitmap);
2430 BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2431 hdcImageList, 0, 0, SRCCOPY);
2433 /* delete 'empty' image space */
2434 SetBkColor (hdcBitmap, RGB(255, 255, 255));
2435 SetTextColor (hdcBitmap, RGB(0, 0, 0));
2436 PatBlt (hdcBitmap, nCopyCount * himl->cx, 0,
2437 (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2439 DeleteObject (himl->hbmMask);
2440 himl->hbmMask = hbmNewBitmap;
2443 ERR("Could not create new mask bitmap!\n");
2446 DeleteDC (hdcImageList);
2447 DeleteDC (hdcBitmap);
2449 /* Update max image count and current image count */
2450 himl->cMaxImage = nNewCount;
2451 if (himl->cCurImage > nCopyCount)
2452 himl->cCurImage = nCopyCount;
2458 /*************************************************************************
2459 * ImageList_SetOverlayImage [COMCTL32.79]
2461 * Assigns an overlay mask index to an existing image in an image list.
2464 * himl [I] handle to image list
2465 * iImage [I] image index
2466 * iOverlay [I] overlay mask index
2474 ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay)
2478 if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
2480 if ((iImage < 0) || (iImage > himl->cCurImage))
2483 himl->nOvlIdx[iOverlay - 1] = iImage;
2488 /*************************************************************************
2489 * ImageList_Write [COMCTL32.80]
2491 * Writes an image list to a stream.
2494 * himl [I] handle to image list
2495 * pstm [O] Pointer to a stream.
2502 * This function can not be implemented yet, because
2503 * IStream32::Write is not implemented.
2510 ImageList_Write (HIMAGELIST himl, LPSTREAM pstm)
2515 FIXME("empty stub!\n");