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"
39 DEFAULT_DEBUG_CHANNEL(imagelist)
42 #define _MAX(a,b) (((a)>(b))?(a):(b))
43 #define _MIN(a,b) (((a)>(b))?(b):(a))
45 #define MAX_OVERLAYIMAGE 15
48 /* internal image list data used for Drag & Drop operations */
50 static HIMAGELIST himlInternalDrag = NULL;
51 static INT nInternalDragHotspotX = 0;
52 static INT nInternalDragHotspotY = 0;
54 static HWND hwndInternalDrag = 0;
55 static INT xInternalPos = 0;
56 static INT yInternalPos = 0;
58 static HDC hdcBackBuffer = 0;
59 static HBITMAP hbmBackBuffer = 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)
80 HDC hdcImageList, hdcBitmap;
82 INT nNewWidth, nNewCount;
84 TRACE("Create expanded bitmaps!\n");
86 nNewCount = himl->cCurImage + nImageCount + himl->cGrow;
87 nNewWidth = nNewCount * himl->cx;
89 hdcImageList = CreateCompatibleDC (0);
90 hdcBitmap = CreateCompatibleDC (0);
93 CreateBitmap (nNewWidth, himl->cy, 1, himl->uBitsPixel, NULL);
94 if (hbmNewBitmap == 0)
95 ERR("creating new image bitmap!\n");
97 SelectObject (hdcImageList, himl->hbmImage);
98 SelectObject (hdcBitmap, hbmNewBitmap);
99 BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, himl->cy,
100 hdcImageList, 0, 0, SRCCOPY);
102 DeleteObject (himl->hbmImage);
103 himl->hbmImage = hbmNewBitmap;
107 CreateBitmap (nNewWidth, himl->cy, 1, 1, NULL);
109 if (hbmNewBitmap == 0)
110 ERR("creating new mask bitmap!");
112 SelectObject (hdcImageList, himl->hbmMask);
113 SelectObject (hdcBitmap, hbmNewBitmap);
114 BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, himl->cy,
115 hdcImageList, 0, 0, SRCCOPY);
116 DeleteObject (himl->hbmMask);
117 himl->hbmMask = hbmNewBitmap;
120 himl->cMaxImage = nNewCount;
122 DeleteDC (hdcImageList);
123 DeleteDC (hdcBitmap);
127 /*************************************************************************
128 * IMAGELIST_InternalDraw [Internal]
130 * Draws the image in the ImageList (without the mask)
133 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
134 * cx [I] the width of the image to display
135 * cy............[I] the height of the image to display
141 * This functions is used by ImageList_DrawIndirect, when it is
142 * required to draw only the Image (without the mask) to the screen.
144 * Blending and Overlays styles are accomplised by another function
147 IMAGELIST_InternalDraw(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
151 hImageDC = CreateCompatibleDC(0);
152 hOldBitmap = SelectObject(hImageDC, pimldp->himl->hbmImage);
153 BitBlt(pimldp->hdcDst,
154 pimldp->x, pimldp->y, cx, cy,
156 pimldp->himl->cx * pimldp->i, 0,
159 SelectObject(hImageDC, hOldBitmap);
164 /*************************************************************************
165 * IMAGELIST_InternalDrawMask [Internal]
167 * Draws the image in the ImageList witht the mask
170 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
171 * cx [I] the width of the image to display
172 * cy............[I] the height of the image to display
178 * This functions is used by ImageList_DrawIndirect, when it is
179 * required to draw the Image with the mask to the screen.
181 * Blending and Overlays styles are accomplised by another function.
184 IMAGELIST_InternalDrawMask(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
186 HDC hMaskDC, hImageDC;
187 BOOL bUseCustomBackground, bBlendFlag;
188 HBRUSH hBrush, hOldBrush;
189 HBITMAP hOldBitmapImage, hOldBitmapMask;
190 HIMAGELIST himlLocal = pimldp->himl;
191 COLORREF oldBkColor, oldFgColor;
193 bUseCustomBackground = (himlLocal->clrBk != CLR_NONE);
194 bBlendFlag = (pimldp->fStyle & ILD_BLEND50 )
195 || (pimldp->fStyle & ILD_BLEND25);
197 hImageDC = CreateCompatibleDC(0);
198 hMaskDC = CreateCompatibleDC(0);
200 hOldBitmapImage = SelectObject(hImageDC, himlLocal->hbmImage);
201 hOldBitmapMask = SelectObject(hMaskDC, himlLocal->hbmMask);
202 /* Draw the Background for the appropriate Styles
204 if( bUseCustomBackground && (pimldp->fStyle == ILD_NORMAL
205 || pimldp->fStyle & ILD_IMAGE
208 hBrush = CreateSolidBrush (himlLocal->clrBk);
209 hOldBrush = SelectObject (pimldp->hdcDst, hBrush);
210 PatBlt (pimldp->hdcDst,
211 pimldp->x, pimldp->y, cx, cy,
214 DeleteObject (SelectObject (pimldp->hdcDst, hOldBrush));
217 /* Draw Image Transparently over the current background
219 if(pimldp->fStyle == ILD_NORMAL
220 || pimldp->fStyle & ILD_TRANSPARENT
221 || ((pimldp->fStyle & ILD_IMAGE) && bUseCustomBackground)
224 /* to obtain a transparent look, background color should be set
225 to white and foreground color to black when blting the
227 oldBkColor = SetBkColor(pimldp->hdcDst, RGB(0xff, 0xff, 0xff));
228 oldFgColor = SetTextColor(pimldp->hdcDst, RGB(0, 0, 0));
230 BitBlt(pimldp->hdcDst,
231 pimldp->x, pimldp->y, cx, cy,
233 himlLocal->cx * pimldp->i, 0,
236 BitBlt(pimldp->hdcDst,
237 pimldp->x, pimldp->y, cx, cy,
239 himlLocal->cx * pimldp->i, 0,
242 SetBkColor(pimldp->hdcDst, oldBkColor);
243 SetTextColor(pimldp->hdcDst, oldFgColor);
245 /* Draw the image when no Background is specified
247 else if(pimldp->fStyle & ILD_IMAGE && !bUseCustomBackground)
249 BitBlt(pimldp->hdcDst,
250 pimldp->x, pimldp->y, cx, cy,
252 himlLocal->cx * pimldp->i, 0,
255 /* Draw the mask with or without a background
257 else if(pimldp->fStyle & ILD_MASK)
259 BitBlt(pimldp->hdcDst,
260 pimldp->x, pimldp->y, cx, cy,
262 himlLocal->cx * pimldp->i, 0,
263 bUseCustomBackground ? SRCCOPY : SRCAND);
265 SelectObject(hImageDC, hOldBitmapImage);
266 SelectObject(hMaskDC, hOldBitmapMask);
271 /*************************************************************************
272 * IMAGELIST_InternalDrawBlend [Internal]
274 * Draws the Blend over the current image
277 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
278 * cx [I] the width of the image to display
279 * cy............[I] the height of the image to display
285 * This functions is used by ImageList_DrawIndirect, when it is
286 * required to add the blend to the current image.
290 IMAGELIST_InternalDrawBlend(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
293 HDC hBlendMaskDC,hMaskDC;
294 HBRUSH hBlendColorBrush, hBlendBrush, hOldBrush;
295 HBITMAP hBlendMaskBitmap, hOldBitmap;
296 COLORREF clrBlend, OldTextColor, OldBkColor;
297 HIMAGELIST himlLocal = pimldp->himl;
299 clrBlend = GetSysColor (COLOR_HIGHLIGHT);
300 if (!(pimldp->rgbFg == CLR_DEFAULT))
302 clrBlend = pimldp->rgbFg;
304 /* Create the blend Mask
306 hBlendMaskDC = CreateCompatibleDC(0);
307 hBlendBrush = pimldp->fStyle & ILD_BLEND50 ?
308 himlLocal->hbrBlend50 : himlLocal->hbrBlend25;
310 hBlendMaskBitmap = CreateBitmap(cx, cy, 1, 1, NULL);
311 hOldBitmap = SelectObject(hBlendMaskDC, hBlendMaskBitmap);
313 hOldBrush = (HBRUSH) SelectObject(hBlendMaskDC, hBlendBrush);
314 PatBlt(hBlendMaskDC, 0, 0, cx, cy, PATCOPY);
315 SelectObject(hBlendMaskDC, hOldBrush);
317 /* Modify the blend mask if an Image Mask exist
319 if(pimldp->himl->hbmMask != 0)
321 HBITMAP hOldMaskBitmap;
322 hMaskDC = CreateCompatibleDC(0);
323 hOldMaskBitmap = (HBITMAP) SelectObject(hMaskDC, himlLocal->hbmMask);
328 himlLocal->cx * pimldp->i,0,
329 0x220326); /* NOTSRCAND */
337 SelectObject(hMaskDC, hOldMaskBitmap);
341 /* Apply blend to the current image given the BlendMask
343 OldTextColor = SetTextColor(pimldp->hdcDst, 0);
344 OldBkColor = SetBkColor(pimldp->hdcDst, RGB(255,255,255));
345 hBlendColorBrush = CreateSolidBrush(clrBlend);
346 hOldBrush = (HBRUSH) SelectObject (pimldp->hdcDst, hBlendColorBrush);
348 BitBlt (pimldp->hdcDst,
349 pimldp->x, pimldp->y, cx, cy,
352 0xB8074A); /* PSDPxax */
354 SelectObject(pimldp->hdcDst, hOldBrush);
355 SetTextColor(pimldp->hdcDst, OldTextColor);
356 SetBkColor(pimldp->hdcDst, OldBkColor);
357 SelectObject(hBlendMaskDC, hOldBitmap);
358 DeleteDC(hBlendMaskDC);
359 DeleteObject(hBlendMaskBitmap);
360 DeleteObject(hBlendColorBrush);
363 /*************************************************************************
364 * IMAGELIST_InternalDrawOverlay [Internal]
366 * Draws the overlay image
369 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
370 * cx [I] the width of the image to display
371 * cy............[I] the height of the image to display
377 * This functions is used by ImageList_DrawIndirect, when it is
378 * required to draw the overlay
383 IMAGELIST_InternalDrawOverlay(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
389 nOvlIdx = (pimldp->fStyle & 0x0700) >> 8;
390 if ((nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE))
392 nOvlIdx = pimldp->himl->nOvlIdx[nOvlIdx - 1];
393 if ((nOvlIdx >= 0) && (nOvlIdx <= pimldp->himl->cCurImage))
395 hImageDC = CreateCompatibleDC(0);
396 if (pimldp->himl->hbmMask)
398 hOldBitmap = (HBITMAP) SelectObject (hImageDC,
399 pimldp->himl->hbmMask);
401 BitBlt (pimldp->hdcDst,
402 pimldp->x, pimldp->y, cx, cy,
403 hImageDC, pimldp->himl->cx * nOvlIdx, 0,
406 SelectObject(hImageDC, hOldBitmap);
408 hOldBitmap = (HBITMAP) SelectObject (hImageDC,
409 pimldp->himl->hbmImage);
411 BitBlt (pimldp->hdcDst,
412 pimldp->x, pimldp->y, cx, cy,
414 pimldp->himl->cx * nOvlIdx, 0,
417 SelectObject(hImageDC, hOldBitmap);
427 /*************************************************************************
428 * ImageList_Add [COMCTL32.39]
430 * Add an image or images to an image list.
433 * himl [I] handle to image list
434 * hbmImage [I] handle to image bitmap
435 * hbmMask [I] handle to mask bitmap
438 * Success: Index of the first new image.
443 ImageList_Add (HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
445 HDC hdcImage, hdcBitmap;
446 INT nFirstIndex, nImageCount;
449 HBITMAP hOldBitmapImage, hOldBitmap;
451 if (!himl || !hbmImage)
454 GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
455 nImageCount = bmp.bmWidth / himl->cx;
457 if (himl->cCurImage + nImageCount >= himl->cMaxImage)
458 IMAGELIST_InternalExpandBitmaps (himl, nImageCount);
460 nStartX = himl->cCurImage * himl->cx;
462 hdcImage = CreateCompatibleDC(0);
463 hdcBitmap = CreateCompatibleDC(0);
465 hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
466 hOldBitmap = SelectObject(hdcBitmap, hbmImage);
468 /* Copy result to the imagelist
470 BitBlt (hdcImage, nStartX, 0, bmp.bmWidth, himl->cy,
471 hdcBitmap, 0, 0, SRCCOPY);
475 HDC hdcMask, hdcTemp, hOldBitmapMask, hOldBitmapTemp;
477 hdcMask = CreateCompatibleDC (0);
478 hdcTemp = CreateCompatibleDC(0);
479 hOldBitmapMask = (HBITMAP) SelectObject(hdcMask, himl->hbmMask);
480 hOldBitmapTemp = (HBITMAP) SelectObject(hdcTemp, hbmMask);
483 nStartX, 0, bmp.bmWidth, himl->cy,
488 SelectObject(hdcTemp, hOldBitmapTemp);
491 /* Remove the background from the image
494 nStartX, 0, bmp.bmWidth, himl->cy,
497 0x220326); /* NOTSRCAND */
499 SelectObject(hdcMask, hOldBitmapMask);
503 SelectObject(hdcImage, hOldBitmapImage);
504 SelectObject(hdcBitmap, hOldBitmap);
508 nFirstIndex = himl->cCurImage;
509 himl->cCurImage += nImageCount;
515 /*************************************************************************
516 * ImageList_AddIcon [COMCTL32.40]
518 * Adds an icon to an image list.
521 * himl [I] handle to image list
522 * hIcon [I] handle to icon
525 * Success: index of the new image
530 ImageList_AddIcon (HIMAGELIST himl, HICON hIcon)
532 return ImageList_ReplaceIcon (himl, -1, hIcon);
536 /*************************************************************************
537 * ImageList_AddMasked [COMCTL32.41]
539 * Adds an image or images to an image list and creates a mask from the
540 * specified bitmap using the mask color.
543 * himl [I] handle to image list.
544 * hBitmap [I] handle to bitmap
545 * clrMask [I] mask color.
548 * Success: Index of the first new image.
553 ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
555 HDC hdcImage, hdcMask, hdcBitmap;
556 INT nIndex, nImageCount, nMaskXOffset=0;
558 HBITMAP hOldBitmap, hOldBitmapMask, hOldBitmapImage;
559 HBITMAP hMaskBitmap=0;
565 if (!GetObjectA (hBitmap, sizeof(BITMAP), &bmp))
568 nImageCount = bmp.bmWidth / himl->cx;
570 if (himl->cCurImage + nImageCount >= himl->cMaxImage)
572 IMAGELIST_InternalExpandBitmaps (himl, nImageCount);
575 nIndex = himl->cCurImage;
576 himl->cCurImage += nImageCount;
578 hdcMask = CreateCompatibleDC (0);
579 hdcImage = CreateCompatibleDC(0);
580 hdcBitmap = CreateCompatibleDC(0);
583 hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
584 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
587 hOldBitmapMask = SelectObject(hdcMask, himl->hbmMask);
588 nMaskXOffset = nIndex * himl->cx;
593 Create a temp Mask so we can remove the background of
594 the Image (Windows does this even if there is no mask)
596 hMaskBitmap = CreateBitmap(bmp.bmWidth, himl->cy, 1, 1, NULL);
597 hOldBitmapMask = SelectObject(hdcMask, hMaskBitmap);
600 /* create monochrome image to the mask bitmap */
601 bkColor = (clrMask != CLR_DEFAULT) ? clrMask :
602 GetPixel (hdcBitmap, 0, 0);
603 SetBkColor (hdcBitmap, bkColor);
605 nMaskXOffset, 0, bmp.bmWidth, himl->cy,
609 SetBkColor(hdcBitmap, RGB(255,255,255));
610 /*Remove the background from the image
613 WINDOWS BUG ALERT!!!!!!
614 The statement below should not be done in common practice
615 but this is how ImageList_AddMasked works in Windows.
616 It overwrites the original bitmap passed, this was discovered
617 by using the same bitmap to itterated the different styles
618 on windows where it failed (BUT ImageList_Add is OK)
619 This is here in case some apps really on this bug
622 0, 0, bmp.bmWidth, himl->cy,
625 0x220326); /* NOTSRCAND */
626 /* Copy result to the imagelist
629 nIndex * himl->cx, 0, bmp.bmWidth, himl->cy,
635 SelectObject(hdcMask,hOldBitmapMask);
636 SelectObject(hdcImage, hOldBitmapImage);
637 SelectObject(hdcBitmap, hOldBitmap);
643 DeleteObject(hMaskBitmap);
650 /*************************************************************************
651 * ImageList_BeginDrag [COMCTL32.42]
653 * Creates a temporary image list that contains one image. It will be used
657 * himlTrack [I] handle to the source image list
658 * iTrack [I] index of the drag image in the source image list
659 * dxHotspot [I] X position of the hot spot of the drag image
660 * dyHotspot [I] Y position of the hot spot of the drag image
668 ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
669 INT dxHotspot, INT dyHotspot)
673 FIXME("partially implemented!\n");
675 if (himlTrack == NULL)
678 if (himlInternalDrag)
679 ImageList_EndDrag ();
682 ImageList_Create (himlTrack->cx, himlTrack->cy,
683 himlTrack->flags, 1, 1);
684 if (himlInternalDrag == NULL) {
685 ERR("Error creating drag image list!\n");
689 nInternalDragHotspotX = dxHotspot;
690 nInternalDragHotspotY = dyHotspot;
692 hdcSrc = CreateCompatibleDC (0);
693 hdcDst = CreateCompatibleDC (0);
696 SelectObject (hdcSrc, himlTrack->hbmImage);
697 SelectObject (hdcDst, himlInternalDrag->hbmImage);
698 StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
699 iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
702 SelectObject (hdcSrc, himlTrack->hbmMask);
703 SelectObject (hdcDst, himlInternalDrag->hbmMask);
704 StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
705 iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
710 himlInternalDrag->cCurImage = 1;
716 /*************************************************************************
717 * ImageList_Copy [COMCTL32.43]
719 * Copies an image of the source image list to an image of the
720 * destination image list. Images can be copied or swapped.
723 * himlDst [I] handle to the destination image list
724 * iDst [I] destination image index.
725 * himlSrc [I] handle to the source image list
726 * iSrc [I] source image index
727 * uFlags [I] flags for the copy operation
734 * Copying from one image list to another is possible. The original
735 * implementation just copies or swapps within one image list.
736 * Could this feature become a bug??? ;-)
740 ImageList_Copy (HIMAGELIST himlDst, INT iDst, HIMAGELIST himlSrc,
741 INT iSrc, INT uFlags)
745 TRACE("iDst=%d iSrc=%d\n", iDst, iSrc);
747 if ((himlSrc == NULL) || (himlDst == NULL))
749 if ((iDst < 0) || (iDst >= himlDst->cCurImage))
751 if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage))
754 hdcSrc = CreateCompatibleDC (0);
755 if (himlDst == himlSrc)
758 hdcDst = CreateCompatibleDC (0);
760 if (uFlags & ILCF_SWAP) {
762 HBITMAP hbmTempImage, hbmTempMask;
764 /* create temporary bitmaps */
765 hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
766 himlSrc->uBitsPixel, NULL);
767 hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
770 /* copy (and stretch) destination to temporary bitmaps.(save) */
772 SelectObject (hdcSrc, himlDst->hbmImage);
773 SelectObject (hdcDst, hbmTempImage);
774 StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
775 hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
778 SelectObject (hdcSrc, himlDst->hbmMask);
779 SelectObject (hdcDst, hbmTempMask);
780 StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
781 hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
784 /* copy (and stretch) source to destination */
786 SelectObject (hdcSrc, himlSrc->hbmImage);
787 SelectObject (hdcDst, himlDst->hbmImage);
788 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
789 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
792 SelectObject (hdcSrc, himlSrc->hbmMask);
793 SelectObject (hdcDst, himlDst->hbmMask);
794 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
795 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
798 /* copy (without stretching) temporary bitmaps to source (restore) */
800 SelectObject (hdcSrc, hbmTempImage);
801 SelectObject (hdcDst, himlSrc->hbmImage);
802 BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
803 hdcSrc, 0, 0, SRCCOPY);
805 SelectObject (hdcSrc, hbmTempMask);
806 SelectObject (hdcDst, himlSrc->hbmMask);
807 BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
808 hdcSrc, 0, 0, SRCCOPY);
810 /* delete temporary bitmaps */
811 DeleteObject (hbmTempMask);
812 DeleteObject (hbmTempImage);
816 SelectObject (hdcSrc, himlSrc->hbmImage);
817 if (himlSrc == himlDst)
820 SelectObject (hdcDst, himlDst->hbmImage);
821 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
822 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
826 SelectObject (hdcSrc, himlSrc->hbmMask);
827 if (himlSrc == himlDst)
830 SelectObject (hdcDst, himlDst->hbmMask);
831 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
832 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
837 if (himlSrc != himlDst)
844 /*************************************************************************
845 * ImageList_Create [COMCTL32.44] Creates a new image list.
848 * cx [I] image height
850 * flags [I] creation flags
851 * cInitial [I] initial number of images in the image list
852 * cGrow [I] number of images by which image list grows
855 * Success: Handle to the created image list
860 ImageList_Create (INT cx, INT cy, UINT flags,
861 INT cInitial, INT cGrow)
867 static WORD aBitBlend25[] =
868 {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00};
870 static WORD aBitBlend50[] =
871 {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
873 TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow);
875 himl = (HIMAGELIST)COMCTL32_Alloc (sizeof(struct _IMAGELIST));
882 himl->cMaxImage = cInitial + cGrow;
883 himl->cInitial = cInitial;
886 himl->clrFg = CLR_DEFAULT;
887 himl->clrBk = CLR_NONE;
889 /* initialize overlay mask indices */
890 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
891 himl->nOvlIdx[nCount] = -1;
893 hdc = CreateCompatibleDC (0);
894 himl->uBitsPixel = (UINT)GetDeviceCaps (hdc, BITSPIXEL);
897 TRACE("Image: %d Bits per Pixel\n", himl->uBitsPixel);
899 if (himl->cMaxImage > 0) {
901 CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
902 1, himl->uBitsPixel, NULL);
903 if (himl->hbmImage == 0) {
904 ERR("Error creating image bitmap!\n");
911 if ( (himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) {
912 himl->hbmMask = CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
914 if (himl->hbmMask == 0) {
915 ERR("Error creating mask bitmap!\n");
917 DeleteObject (himl->hbmImage);
924 /* create blending brushes */
925 hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend25);
926 himl->hbrBlend25 = CreatePatternBrush (hbmTemp);
927 DeleteObject (hbmTemp);
929 hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend50);
930 himl->hbrBlend50 = CreatePatternBrush (hbmTemp);
931 DeleteObject (hbmTemp);
937 /*************************************************************************
938 * ImageList_Destroy [COMCTL32.45]
940 * Destroys an image list.
943 * himl [I] handle to image list
951 ImageList_Destroy (HIMAGELIST himl)
956 /* delete image bitmaps */
958 DeleteObject (himl->hbmImage);
960 DeleteObject (himl->hbmMask);
962 /* delete blending brushes */
963 if (himl->hbrBlend25)
964 DeleteObject (himl->hbrBlend25);
965 if (himl->hbrBlend50)
966 DeleteObject (himl->hbrBlend50);
968 COMCTL32_Free (himl);
974 /*************************************************************************
975 * ImageList_DragEnter [COMCTL32.46]
977 * Locks window update and displays the drag image at the given position.
980 * hwndLock [I] handle of the window that owns the drag image.
981 * x [I] X position of the drag image.
982 * y [I] Y position of the drag image.
989 * The position of the drag image is relative to the window, not
994 ImageList_DragEnter (HWND hwndLock, INT x, INT y)
996 if (himlInternalDrag == NULL)
1000 hwndInternalDrag = hwndLock;
1002 hwndInternalDrag = GetDesktopWindow ();
1007 hdcBackBuffer = CreateCompatibleDC (0);
1008 hbmBackBuffer = CreateCompatibleBitmap (hdcBackBuffer,
1009 himlInternalDrag->cx, himlInternalDrag->cy);
1011 ImageList_DragShowNolock (TRUE);
1017 /*************************************************************************
1018 * ImageList_DragLeave [COMCTL32.47]
1020 * Unlocks window update and hides the drag image.
1023 * hwndLock [I] handle of the window that owns the drag image.
1031 ImageList_DragLeave (HWND hwndLock)
1034 hwndInternalDrag = hwndLock;
1036 hwndInternalDrag = GetDesktopWindow ();
1038 ImageList_DragShowNolock (FALSE);
1040 DeleteDC (hdcBackBuffer);
1041 DeleteObject (hbmBackBuffer);
1047 /*************************************************************************
1048 * ImageList_DragMove [COMCTL32.48]
1050 * Moves the drag image.
1053 * x [I] X position of the drag image.
1054 * y [I] Y position of the drag image.
1061 * The position of the drag image is relative to the window, not
1066 ImageList_DragMove (INT x, INT y)
1068 ImageList_DragShowNolock (FALSE);
1073 ImageList_DragShowNolock (TRUE);
1079 /*************************************************************************
1080 * ImageList_DragShowNolock [COMCTL32.49]
1082 * Shows or hides the drag image.
1085 * bShow [I] TRUE shows the drag image, FALSE hides it.
1096 ImageList_DragShowNolock (BOOL bShow)
1100 FIXME("semi-stub!\n");
1101 TRACE("bShow=0x%X!\n", bShow);
1103 hdcDrag = GetDCEx (hwndInternalDrag, 0,
1104 DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
1107 /* show drag image */
1109 /* save background */
1111 /* draw drag image */
1115 /* hide drag image */
1117 /* restore background */
1121 ReleaseDC (hwndInternalDrag, hdcDrag);
1127 /*************************************************************************
1128 * ImageList_Draw [COMCTL32.50] Draws an image.
1131 * himl [I] handle to image list
1133 * hdc [I] handle to device context
1136 * fStyle [I] drawing flags
1143 * Calls ImageList_DrawIndirect.
1146 * ImageList_DrawIndirect.
1150 ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc,
1151 INT x, INT y, UINT fStyle)
1153 IMAGELISTDRAWPARAMS imldp;
1155 imldp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
1165 imldp.rgbBk = CLR_DEFAULT;
1166 imldp.rgbFg = CLR_DEFAULT;
1167 imldp.fStyle = fStyle;
1170 return ImageList_DrawIndirect (&imldp);
1174 /*************************************************************************
1175 * ImageList_DrawEx [COMCTL32.51]
1177 * Draws an image and allows to use extended drawing features.
1180 * himl [I] handle to image list
1182 * hdc [I] handle to device context
1185 * xOffs [I] X offset
1186 * yOffs [I] Y offset
1187 * rgbBk [I] background color
1188 * rgbFg [I] foreground color
1189 * fStyle [I] drawing flags
1196 * Calls ImageList_DrawIndirect.
1199 * ImageList_DrawIndirect.
1203 ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y,
1204 INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg,
1207 IMAGELISTDRAWPARAMS imldp;
1209 imldp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
1219 imldp.rgbBk = rgbBk;
1220 imldp.rgbFg = rgbFg;
1221 imldp.fStyle = fStyle;
1224 return ImageList_DrawIndirect (&imldp);
1228 /*************************************************************************
1229 * ImageList_DrawIndirect [COMCTL32.52]
1231 * Draws an image using ...
1234 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
1242 ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
1246 Do some Error Checking
1250 if (pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS))
1252 if (pimldp->himl == NULL)
1254 if ((pimldp->i < 0) || (pimldp->i > pimldp->himl->cCurImage))
1257 Get the Height and Width to display
1259 cx = (pimldp->cx == 0) ? pimldp->himl->cx : pimldp->cx;
1260 cy = (pimldp->cy == 0) ? pimldp->himl->cy : pimldp->cy;
1264 if(pimldp->himl->hbmMask != 0)
1266 IMAGELIST_InternalDrawMask(pimldp, cx, cy);
1270 IMAGELIST_InternalDraw(pimldp, cx, cy);
1273 Apply the blend if needed to the Image
1275 if((pimldp->fStyle & ILD_BLEND50)
1276 || (pimldp->fStyle & ILD_BLEND25))
1278 IMAGELIST_InternalDrawBlend(pimldp, cx, cy);
1281 Apply the Overlay if needed
1283 if (pimldp->fStyle & 0x0700)
1285 IMAGELIST_InternalDrawOverlay(pimldp, cx, cy);
1292 /*************************************************************************
1293 * ImageList_Duplicate [COMCTL32.53] Duplicates an image list.
1296 * himlSrc [I] source image list handle
1299 * Success: Handle of duplicated image list.
1304 ImageList_Duplicate (HIMAGELIST himlSrc)
1309 if (himlSrc == NULL) {
1310 ERR("Invalid image list handle!\n");
1314 himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
1315 himlSrc->cInitial, himlSrc->cGrow);
1319 hdcSrc = CreateCompatibleDC (0);
1320 hdcDst = CreateCompatibleDC (0);
1321 SelectObject (hdcSrc, himlSrc->hbmImage);
1322 SelectObject (hdcDst, himlDst->hbmImage);
1323 BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy,
1324 hdcSrc, 0, 0, SRCCOPY);
1326 if (himlDst->hbmMask)
1328 SelectObject (hdcSrc, himlSrc->hbmMask);
1329 SelectObject (hdcDst, himlDst->hbmMask);
1330 BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx,
1331 himlSrc->cy, hdcSrc, 0, 0, SRCCOPY);
1342 /*************************************************************************
1343 * ImageList_EndDrag [COMCTL32.54] Finishes a drag operation.
1345 * Finishes a drag operation.
1359 ImageList_EndDrag (void)
1361 FIXME("semi-stub!\n");
1363 if (himlInternalDrag)
1366 ImageList_Destroy (himlInternalDrag);
1367 himlInternalDrag = NULL;
1369 nInternalDragHotspotX = 0;
1370 nInternalDragHotspotY = 0;
1378 /*************************************************************************
1379 * ImageList_GetBkColor [COMCTL32.55]
1381 * Returns the background color of an image list.
1384 * himl [I] Image list handle.
1387 * Success: background color
1392 ImageList_GetBkColor (HIMAGELIST himl)
1401 /*************************************************************************
1402 * ImageList_GetDragImage [COMCTL32.56]
1404 * Returns the handle to the internal drag image list.
1407 * ppt [O] Pointer to the drag position. Can be NULL.
1408 * pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
1411 * Success: Handle of the drag image list.
1419 ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot)
1421 FIXME("semi-stub!\n");
1423 if (himlInternalDrag)
1424 return (himlInternalDrag);
1430 /*************************************************************************
1431 * ImageList_GetIcon [COMCTL32.57]
1433 * Creates an icon from a masked image of an image list.
1436 * himl [I] handle to image list
1438 * flags [I] drawing style flags
1441 * Success: icon handle
1446 ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle)
1450 HBITMAP hOldSrcBitmap,hOldDstBitmap;
1453 if ((himl == NULL) || (i < 0) || (i >= himl->cCurImage))
1456 hdcSrc = CreateCompatibleDC(0);
1457 hdcDst = CreateCompatibleDC(0);
1460 ii.hbmMask = CreateCompatibleBitmap (hdcDst, himl->cx, himl->cy);
1463 hOldDstBitmap = (HBITMAP)SelectObject (hdcDst, ii.hbmMask);
1464 if (himl->hbmMask) {
1465 SelectObject (hdcSrc, himl->hbmMask);
1466 BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1467 hdcSrc, i * himl->cx, 0, SRCCOPY);
1470 PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS);
1473 hOldSrcBitmap = (HBITMAP)SelectObject (hdcSrc, himl->hbmImage);
1474 ii.hbmColor = CreateCompatibleBitmap (hdcSrc, himl->cx, himl->cy);
1475 SelectObject (hdcDst, ii.hbmColor);
1476 BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1477 hdcSrc, i * himl->cx, 0, SRCCOPY);
1480 * CreateIconIndirect requires us to deselect the bitmaps from
1481 * the DCs before calling
1483 SelectObject(hdcSrc, hOldSrcBitmap);
1484 SelectObject(hdcDst, hOldDstBitmap);
1486 hIcon = CreateIconIndirect (&ii);
1490 DeleteObject (ii.hbmMask);
1491 DeleteObject (ii.hbmColor);
1497 /*************************************************************************
1498 * ImageList_GetIconSize [COMCTL32.58]
1500 * Retrieves the size of an image in an image list.
1503 * himl [I] handle to image list
1504 * cx [O] pointer to the image width.
1505 * cy [O] pointer to the image height.
1512 * All images in an image list have the same size.
1516 ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy)
1520 if ((himl->cx <= 0) || (himl->cy <= 0))
1532 /*************************************************************************
1533 * ImageList_GetImageCount [COMCTL32.59]
1535 * Returns the number of images in an image list.
1538 * himl [I] handle to image list
1541 * Success: Number of images.
1546 ImageList_GetImageCount (HIMAGELIST himl)
1551 return himl->cCurImage;
1555 /*************************************************************************
1556 * ImageList_GetImageInfo [COMCTL32.60]
1558 * Returns information about an image in an image list.
1561 * himl [I] handle to image list
1563 * pImageInfo [O] pointer to the image information
1571 ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
1573 if ((himl == NULL) || (pImageInfo == NULL))
1575 if ((i < 0) || (i >= himl->cCurImage))
1578 pImageInfo->hbmImage = himl->hbmImage;
1579 pImageInfo->hbmMask = himl->hbmMask;
1581 pImageInfo->rcImage.top = 0;
1582 pImageInfo->rcImage.bottom = himl->cy;
1583 pImageInfo->rcImage.left = i * himl->cx;
1584 pImageInfo->rcImage.right = (i+1) * himl->cx;
1590 /*************************************************************************
1591 * ImageList_GetImageRect [COMCTL32.61]
1593 * Retrieves the rectangle of the specified image in an image list.
1596 * himl [I] handle to image list
1598 * lpRect [O] pointer to the image rectangle
1605 * This is an UNDOCUMENTED function!!!
1609 ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect)
1611 if ((himl == NULL) || (lpRect == NULL))
1613 if ((i < 0) || (i >= himl->cCurImage))
1616 lpRect->left = i * himl->cx;
1618 lpRect->right = lpRect->left + himl->cx;
1619 lpRect->bottom = himl->cy;
1625 /*************************************************************************
1626 * ImageList_LoadImage32A [COMCTL32.63][COMCTL32.62]
1628 * Creates an image list from a bitmap, icon or cursor.
1631 * hi [I] instance handle
1632 * lpbmp [I] name or id of the image
1633 * cx [I] width of each image
1634 * cGrow [I] number of images to expand
1635 * clrMask [I] mask color
1636 * uType [I] type of image to load
1637 * uFlags [I] loading flags
1640 * Success: handle to the loaded image list
1648 ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx, INT cGrow,
1649 COLORREF clrMask, UINT uType, UINT uFlags)
1651 HIMAGELIST himl = NULL;
1655 handle = LoadImageA (hi, lpbmp, uType, 0, 0, uFlags);
1657 ERR("Error loading image!\n");
1661 if (uType == IMAGE_BITMAP) {
1663 GetObjectA (handle, sizeof(BITMAP), &bmp);
1665 /* To match windows behavior, if cx is set to zero and
1666 the flag DI_DEFAULTSIZE is specified, cx becomes the
1667 system metric value for icons. If the flag is not specified
1668 the function sets the size to the height of the bitmap */
1671 if (uFlags & DI_DEFAULTSIZE)
1672 cx = GetSystemMetrics (SM_CXICON);
1677 nImageCount = bmp.bmWidth / cx;
1679 himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1680 nImageCount, cGrow);
1681 ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1683 else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1687 GetIconInfo (handle, &ii);
1688 GetObjectA (ii.hbmColor, sizeof(BITMAP), (LPVOID)&bmp);
1689 himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1690 ILC_MASK | ILC_COLOR, 1, cGrow);
1691 ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1692 DeleteObject (ii.hbmColor);
1693 DeleteObject (ii.hbmMask);
1696 DeleteObject (handle);
1702 /*************************************************************************
1703 * ImageList_LoadImage32W [COMCTL32.64]
1705 * Creates an image list from a bitmap, icon or cursor.
1708 * hi [I] instance handle
1709 * lpbmp [I] name or id of the image
1710 * cx [I] width of each image
1711 * cGrow [I] number of images to expand
1712 * clrMask [I] mask color
1713 * uType [I] type of image to load
1714 * uFlags [I] loading flags
1717 * Success: handle to the loaded image list
1725 ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow,
1726 COLORREF clrMask, UINT uType, UINT uFlags)
1728 HIMAGELIST himl = NULL;
1732 handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags);
1734 ERR("Error loading image!\n");
1738 if (uType == IMAGE_BITMAP) {
1740 GetObjectA (handle, sizeof(BITMAP), &bmp);
1741 nImageCount = bmp.bmWidth / cx;
1743 himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1744 nImageCount, cGrow);
1745 ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1747 else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1751 GetIconInfo (handle, &ii);
1752 GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
1753 himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1754 ILC_MASK | ILC_COLOR, 1, cGrow);
1755 ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1756 DeleteObject (ii.hbmColor);
1757 DeleteObject (ii.hbmMask);
1760 DeleteObject (handle);
1766 /*************************************************************************
1767 * ImageList_Merge [COMCTL32.65]
1769 * Creates a new image list that contains a merged image from the specified
1770 * images of both source image lists.
1773 * himl1 [I] handle to first image list
1774 * i1 [I] first image index
1775 * himl2 [I] handle to second image list
1776 * i2 [I] second image index
1777 * dx [I] X offset of the second image relative to the first.
1778 * dy [I] Y offset of the second image relative to the first.
1781 * Success: handle of the merged image list.
1786 ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
1789 HIMAGELIST himlDst = NULL;
1790 HDC hdcSrcImage, hdcDstImage;
1792 INT xOff1, yOff1, xOff2, yOff2;
1795 if ((himl1 == NULL) || (himl2 == NULL))
1799 if ((i1 < 0) || (i1 >= himl1->cCurImage)) {
1800 ERR("Index 1 out of range! %d\n", i1);
1804 if ((i2 < 0) || (i2 >= himl2->cCurImage)) {
1805 ERR("Index 2 out of range! %d\n", i2);
1810 cxDst = _MAX (himl1->cx, dx + himl2->cx);
1815 cxDst = _MAX (himl2->cx, himl1->cx - dx);
1820 cxDst = _MAX (himl1->cx, himl2->cx);
1826 cyDst = _MAX (himl1->cy, dy + himl2->cy);
1831 cyDst = _MAX (himl2->cy, himl1->cy - dy);
1836 cyDst = _MAX (himl1->cy, himl2->cy);
1841 himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
1844 hdcSrcImage = CreateCompatibleDC (0);
1845 hdcDstImage = CreateCompatibleDC (0);
1846 nX1 = i1 * himl1->cx;
1847 nX2 = i2 * himl2->cx;
1850 SelectObject (hdcSrcImage, himl1->hbmImage);
1851 SelectObject (hdcDstImage, himlDst->hbmImage);
1852 BitBlt (hdcDstImage, 0, 0, cxDst, cyDst,
1853 hdcSrcImage, 0, 0, BLACKNESS);
1854 BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy,
1855 hdcSrcImage, nX1, 0, SRCCOPY);
1857 SelectObject (hdcSrcImage, himl2->hbmMask);
1858 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1859 hdcSrcImage, nX2, 0, SRCAND);
1861 SelectObject (hdcSrcImage, himl2->hbmImage);
1862 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1863 hdcSrcImage, nX2, 0, SRCPAINT);
1866 SelectObject (hdcSrcImage, himl1->hbmMask);
1867 SelectObject (hdcDstImage, himlDst->hbmMask);
1868 BitBlt (hdcDstImage, 0, 0, cxDst, cyDst,
1869 hdcSrcImage, 0, 0, WHITENESS);
1870 BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy,
1871 hdcSrcImage, nX1, 0, SRCCOPY);
1873 SelectObject (hdcSrcImage, himl2->hbmMask);
1874 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1875 hdcSrcImage, nX2, 0, SRCAND);
1877 DeleteDC (hdcSrcImage);
1878 DeleteDC (hdcDstImage);
1885 /*************************************************************************
1886 * ImageList_Read [COMCTL32.66]
1888 * Reads an image list from a stream.
1891 * pstm [I] pointer to a stream
1894 * Success: handle to image list
1898 * This function can not be implemented yet, because
1899 * IStream32::Read is not implemented yet.
1905 HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
1907 FIXME("empty stub!\n");
1914 /*************************************************************************
1915 * ImageList_Remove [COMCTL32.67] Removes an image from an image list
1918 * himl [I] image list handle
1927 ImageList_Remove (HIMAGELIST himl, INT i)
1929 HBITMAP hbmNewImage, hbmNewMask;
1933 if ((i < -1) || (i >= himl->cCurImage)) {
1934 ERR("index out of range! %d\n", i);
1938 if (himl->cCurImage == 0) {
1939 ERR("image list is already empty!\n");
1945 TRACE("remove all!\n");
1947 himl->cMaxImage = himl->cInitial + himl->cGrow;
1948 himl->cCurImage = 0;
1949 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
1950 himl->nOvlIdx[nCount] = -1;
1952 DeleteObject (himl->hbmImage);
1954 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
1955 1, himl->uBitsPixel, NULL);
1957 if (himl->hbmMask) {
1958 DeleteObject (himl->hbmMask);
1960 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
1965 /* delete one image */
1966 TRACE("Remove single image! %d\n", i);
1968 /* create new bitmap(s) */
1969 cxNew = (himl->cCurImage + himl->cGrow - 1) * himl->cx;
1971 TRACE(" - Number of images: %d / %d (Old/New)\n",
1972 himl->cCurImage, himl->cCurImage - 1);
1973 TRACE(" - Max. number of images: %d / %d (Old/New)\n",
1974 himl->cMaxImage, himl->cCurImage + himl->cGrow - 1);
1977 CreateBitmap (cxNew, himl->cy, 1, himl->uBitsPixel, NULL);
1980 hbmNewMask = CreateBitmap (cxNew, himl->cy, 1, 1, NULL);
1982 hbmNewMask = 0; /* Just to keep compiler happy! */
1984 hdcSrc = CreateCompatibleDC (0);
1985 hdcDst = CreateCompatibleDC (0);
1987 /* copy all images and masks prior to the "removed" image */
1989 TRACE("Pre image copy: Copy %d images\n", i);
1991 SelectObject (hdcSrc, himl->hbmImage);
1992 SelectObject (hdcDst, hbmNewImage);
1993 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
1994 hdcSrc, 0, 0, SRCCOPY);
1996 if (himl->hbmMask) {
1997 SelectObject (hdcSrc, himl->hbmMask);
1998 SelectObject (hdcDst, hbmNewMask);
1999 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2000 hdcSrc, 0, 0, SRCCOPY);
2004 /* copy all images and masks behind the removed image */
2005 if (i < himl->cCurImage - 1) {
2006 TRACE("Post image copy!\n");
2007 SelectObject (hdcSrc, himl->hbmImage);
2008 SelectObject (hdcDst, hbmNewImage);
2009 BitBlt (hdcDst, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx,
2010 himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2012 if (himl->hbmMask) {
2013 SelectObject (hdcSrc, himl->hbmMask);
2014 SelectObject (hdcDst, hbmNewMask);
2015 BitBlt (hdcDst, i * himl->cx, 0,
2016 (himl->cCurImage - i - 1) * himl->cx,
2017 himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2024 /* delete old images and insert new ones */
2025 DeleteObject (himl->hbmImage);
2026 himl->hbmImage = hbmNewImage;
2027 if (himl->hbmMask) {
2028 DeleteObject (himl->hbmMask);
2029 himl->hbmMask = hbmNewMask;
2033 himl->cMaxImage = himl->cCurImage + himl->cGrow;
2040 /*************************************************************************
2041 * ImageList_Replace [COMCTL32.68]
2043 * Replaces an image in an image list with a new image.
2046 * himl [I] handle to image list
2048 * hbmImage [I] handle to image bitmap
2049 * hbmMask [I] handle to mask bitmap. Can be NULL.
2057 ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage,
2060 HDC hdcImageList, hdcImage;
2064 ERR("Invalid image list handle!\n");
2068 if ((i >= himl->cCurImage) || (i < 0)) {
2069 ERR("Invalid image index!\n");
2073 hdcImageList = CreateCompatibleDC (0);
2074 hdcImage = CreateCompatibleDC (0);
2075 GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
2078 SelectObject (hdcImageList, himl->hbmImage);
2079 SelectObject (hdcImage, hbmImage);
2081 StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2082 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2087 SelectObject (hdcImageList, himl->hbmMask);
2088 SelectObject (hdcImage, hbmMask);
2090 StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2091 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2094 DeleteDC (hdcImage);
2095 DeleteDC (hdcImageList);
2101 /*************************************************************************
2102 * ImageList_ReplaceIcon [COMCTL32.69]
2104 * Replaces an image in an image list using an icon.
2107 * himl [I] handle to image list
2109 * hIcon [I] handle to icon
2112 * Success: index of the replaced image
2117 ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon)
2119 HDC hdcImageList, hdcImage;
2122 HBITMAP hbmOldSrc, hbmOldDst;
2126 TRACE("(0x%lx 0x%x 0x%x)\n", (DWORD)himl, i, hIcon);
2130 if ((i >= himl->cCurImage) || (i < -1))
2133 hBestFitIcon = CopyImage(
2136 LR_COPYFROMRESOURCE);
2138 GetIconInfo (hBestFitIcon, &ii);
2139 if (ii.hbmMask == 0)
2141 if (ii.hbmColor == 0)
2143 GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
2146 if (himl->cCurImage + 1 >= himl->cMaxImage)
2147 IMAGELIST_InternalExpandBitmaps (himl, 1);
2149 nIndex = himl->cCurImage;
2155 hdcImageList = CreateCompatibleDC (0);
2156 TRACE("hdcImageList=0x%x!\n", hdcImageList);
2157 if (hdcImageList == 0)
2158 ERR("invalid hdcImageList!\n");
2160 hdcImage = CreateCompatibleDC (0);
2161 TRACE("hdcImage=0x%x!\n", hdcImage);
2163 ERR("invalid hdcImage!\n");
2165 hbmOldDst = SelectObject (hdcImageList, himl->hbmImage);
2166 SetTextColor( hdcImageList, RGB(0,0,0));
2167 SetBkColor( hdcImageList, RGB(255,255,255));
2168 hbmOldSrc = SelectObject (hdcImage, ii.hbmColor);
2169 StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2170 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2172 if (himl->hbmMask) {
2173 SelectObject (hdcImageList, himl->hbmMask);
2174 SelectObject (hdcImage, ii.hbmMask);
2175 StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2176 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2179 SelectObject (hdcImage, hbmOldSrc);
2180 SelectObject (hdcImageList, hbmOldDst);
2183 DestroyIcon(hBestFitIcon);
2185 DeleteDC (hdcImageList);
2187 DeleteDC (hdcImage);
2189 DeleteObject (ii.hbmColor);
2191 DeleteObject (ii.hbmMask);
2197 /*************************************************************************
2198 * ImageList_SetBkColor [COMCTL32.70]
2200 * Sets the background color of an image list.
2203 * himl [I] handle to image list
2204 * clrBk [I] background color
2207 * Success: previous background color
2212 ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
2219 clrOldBk = himl->clrBk;
2220 himl->clrBk = clrBk;
2225 /*************************************************************************
2226 * ImageList_SetDragCursorImage [COMCTL32.75]
2228 * Combines the specified image with the current drag image
2231 * himlDrag [I] handle to drag image list
2232 * iDrag [I] drag image index
2233 * dxHotspot [I] X position of the hot spot
2234 * dyHotspot [I] Y position of the hot spot
2245 ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag,
2246 INT dxHotspot, INT dyHotspot)
2248 HIMAGELIST himlTemp;
2250 FIXME("semi-stub!\n");
2252 if (himlInternalDrag == NULL)
2255 TRACE(" dxH=%d dyH=%d nX=%d nY=%d\n",
2256 dxHotspot, dyHotspot, nInternalDragHotspotX, nInternalDragHotspotY);
2258 himlTemp = ImageList_Merge (himlInternalDrag, 0, himlDrag, iDrag,
2259 dxHotspot, dyHotspot);
2261 ImageList_Destroy (himlInternalDrag);
2262 himlInternalDrag = himlTemp;
2264 nInternalDragHotspotX = dxHotspot;
2265 nInternalDragHotspotY = dyHotspot;
2271 /*************************************************************************
2272 * ImageList_SetFilter [COMCTL32.76]
2274 * Sets a filter (or does something completely different)!!???
2277 * himl [I] handle to image list
2283 * Failure: FALSE ???
2286 * This is an UNDOCUMENTED function!!!!
2291 ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter)
2293 FIXME("(%p 0x%x 0x%lx):empty stub!\n",
2300 /*************************************************************************
2301 * ImageList_SetIconSize [COMCTL32.77]
2303 * Sets the image size of the bitmap and deletes all images.
2306 * himl [I] handle to image list
2307 * cx [I] image width
2308 * cy [I] image height
2316 ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy)
2323 /* remove all images*/
2324 himl->cMaxImage = himl->cInitial + himl->cGrow;
2325 himl->cCurImage = 0;
2329 /* initialize overlay mask indices */
2330 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2331 himl->nOvlIdx[nCount] = -1;
2333 DeleteObject (himl->hbmImage);
2335 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2336 1, himl->uBitsPixel, NULL);
2338 if (himl->hbmMask) {
2339 DeleteObject (himl->hbmMask);
2341 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2349 /*************************************************************************
2350 * ImageList_SetImageCount [COMCTL32.78]
2352 * Resizes an image list to the specified number of images.
2355 * himl [I] handle to image list
2356 * iImageCount [I] number of images in the image list
2364 ImageList_SetImageCount (HIMAGELIST himl, INT iImageCount)
2366 HDC hdcImageList, hdcBitmap;
2367 HBITMAP hbmNewBitmap;
2368 INT nNewCount, nCopyCount;
2372 if (himl->cCurImage >= iImageCount)
2374 if (himl->cMaxImage > iImageCount)
2377 nNewCount = iImageCount + himl->cGrow;
2378 nCopyCount = _MIN(himl->cCurImage, iImageCount);
2380 hdcImageList = CreateCompatibleDC (0);
2381 hdcBitmap = CreateCompatibleDC (0);
2383 hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2384 1, himl->uBitsPixel, NULL);
2385 if (hbmNewBitmap != 0)
2387 SelectObject (hdcImageList, himl->hbmImage);
2388 SelectObject (hdcBitmap, hbmNewBitmap);
2391 BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2392 hdcImageList, 0, 0, SRCCOPY);
2394 /* delete 'empty' image space */
2395 SetBkColor (hdcBitmap, RGB(255, 255, 255));
2396 SetTextColor (hdcBitmap, RGB(0, 0, 0));
2397 PatBlt (hdcBitmap, nCopyCount * himl->cx, 0,
2398 (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2400 DeleteObject (himl->hbmImage);
2401 himl->hbmImage = hbmNewBitmap;
2404 ERR("Could not create new image bitmap !\n");
2408 hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2410 if (hbmNewBitmap != 0)
2412 SelectObject (hdcImageList, himl->hbmMask);
2413 SelectObject (hdcBitmap, hbmNewBitmap);
2416 BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2417 hdcImageList, 0, 0, SRCCOPY);
2419 /* delete 'empty' image space */
2420 SetBkColor (hdcBitmap, RGB(255, 255, 255));
2421 SetTextColor (hdcBitmap, RGB(0, 0, 0));
2422 PatBlt (hdcBitmap, nCopyCount * himl->cx, 0,
2423 (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2425 DeleteObject (himl->hbmMask);
2426 himl->hbmMask = hbmNewBitmap;
2429 ERR("Could not create new mask bitmap!\n");
2432 DeleteDC (hdcImageList);
2433 DeleteDC (hdcBitmap);
2435 /* Update max image count and current image count */
2436 himl->cMaxImage = nNewCount;
2437 if (himl->cCurImage > nCopyCount)
2438 himl->cCurImage = nCopyCount;
2444 /*************************************************************************
2445 * ImageList_SetOverlayImage [COMCTL32.79]
2447 * Assigns an overlay mask index to an existing image in an image list.
2450 * himl [I] handle to image list
2451 * iImage [I] image index
2452 * iOverlay [I] overlay mask index
2460 ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay)
2464 if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
2466 if ((iImage < 0) || (iImage > himl->cCurImage))
2469 himl->nOvlIdx[iOverlay - 1] = iImage;
2474 /*************************************************************************
2475 * ImageList_Write [COMCTL32.80]
2477 * Writes an image list to a stream.
2480 * himl [I] handle to image list
2481 * pstm [O] Pointer to a stream.
2488 * This function can not be implemented yet, because
2489 * IStream32::Write is not implemented.
2496 ImageList_Write (HIMAGELIST himl, LPSTREAM pstm)
2501 FIXME("empty stub!\n");