Height calculation was 1 off in ImageList_Read.
[wine/hacks.git] / dlls / comctl32 / imagelist.c
blob6e2cd7a649714c6b6d6e905878a55f921b009452
1 /*
2 * ImageList implementation
4 * Copyright 1998 Eric Kohl
6 * TODO:
7 * - Fix ImageList_DrawIndirect (xBitmap, yBitmap, rgbFg, rgbBk, dwRop).
8 * - Fix ImageList_GetIcon.
9 * - Fix drag functions.
10 * - Fix 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.... ?????????????????????
18 * Comments:
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"
36 #include "commctrl.h"
37 #include "debugtools.h"
38 #include "winerror.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.
68 * PARAMS
69 * himl [I] handle to image list
70 * nImageCount [I] number of images to add
72 * RETURNS
73 * nothing
75 * NOTES
76 * This function can NOT be used to reduce the number of images.
78 static VOID
79 IMAGELIST_InternalExpandBitmaps (HIMAGELIST himl, INT nImageCount)
81 HDC hdcImageList, hdcBitmap;
82 HBITMAP hbmNewBitmap;
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);
93 hbmNewBitmap =
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;
106 if (himl->hbmMask) {
107 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)
133 * PARAMS
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
138 * RETURNS
139 * nothing
141 * NOTES
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
147 static VOID
148 IMAGELIST_InternalDraw(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
150 HDC hImageDC;
151 HBITMAP hOldBitmap;
153 hImageDC = CreateCompatibleDC(0);
154 hOldBitmap = SelectObject(hImageDC, pimldp->himl->hbmImage);
155 BitBlt(pimldp->hdcDst,
156 pimldp->x, pimldp->y, cx, cy,
157 hImageDC,
158 pimldp->himl->cx * pimldp->i, 0,
159 SRCCOPY);
161 SelectObject(hImageDC, hOldBitmap);
162 DeleteDC(hImageDC);
166 /*************************************************************************
167 * IMAGELIST_InternalDrawMask [Internal]
169 * Draws the image in the ImageList witht the mask
171 * PARAMS
172 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
173 * cx [I] the width of the image to display
174 * cy............[I] the height of the image to display
176 * RETURNS
177 * nothing
179 * NOTES
180 * This functions is used by ImageList_DrawIndirect, when it is
181 * required to draw the Image with the mask to the screen.
183 * Blending and Overlays styles are accomplised by another function.
185 static VOID
186 IMAGELIST_InternalDrawMask(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
188 HDC hMaskDC, hImageDC;
189 BOOL bUseCustomBackground, bBlendFlag;
190 HBRUSH hBrush, hOldBrush;
191 HBITMAP hOldBitmapImage, hOldBitmapMask;
192 HIMAGELIST himlLocal = pimldp->himl;
193 COLORREF oldBkColor, oldFgColor;
195 bUseCustomBackground = (himlLocal->clrBk != CLR_NONE);
196 bBlendFlag = (pimldp->fStyle & ILD_BLEND50 )
197 || (pimldp->fStyle & ILD_BLEND25);
199 hImageDC = CreateCompatibleDC(0);
200 hMaskDC = CreateCompatibleDC(0);
202 hOldBitmapImage = SelectObject(hImageDC, himlLocal->hbmImage);
203 hOldBitmapMask = SelectObject(hMaskDC, himlLocal->hbmMask);
204 /* Draw the Background for the appropriate Styles
206 if( bUseCustomBackground && (pimldp->fStyle == ILD_NORMAL
207 || (pimldp->fStyle & ILD_IMAGE)
208 || bBlendFlag))
210 hBrush = CreateSolidBrush (himlLocal->clrBk);
211 hOldBrush = SelectObject (pimldp->hdcDst, hBrush);
212 PatBlt (pimldp->hdcDst,
213 pimldp->x, pimldp->y, cx, cy,
214 PATCOPY);
216 DeleteObject (SelectObject (pimldp->hdcDst, hOldBrush));
219 /* Draw Image Transparently over the current background
221 if(pimldp->fStyle == ILD_NORMAL
222 || (pimldp->fStyle & ILD_TRANSPARENT)
223 || ((pimldp->fStyle & ILD_IMAGE) && bUseCustomBackground)
224 || bBlendFlag)
226 /* to obtain a transparent look, background color should be set
227 to white and foreground color to black when blting the
228 monochrome mask. */
229 oldBkColor = SetBkColor(pimldp->hdcDst, RGB(0xff, 0xff, 0xff));
230 oldFgColor = SetTextColor(pimldp->hdcDst, RGB(0, 0, 0));
232 BitBlt(pimldp->hdcDst,
233 pimldp->x, pimldp->y, cx, cy,
234 hMaskDC,
235 himlLocal->cx * pimldp->i, 0,
236 SRCAND);
238 BitBlt(pimldp->hdcDst,
239 pimldp->x, pimldp->y, cx, cy,
240 hImageDC,
241 himlLocal->cx * pimldp->i, 0,
242 SRCPAINT);
244 SetBkColor(pimldp->hdcDst, oldBkColor);
245 SetTextColor(pimldp->hdcDst, oldFgColor);
247 /* Draw the image when no Background is specified
249 else if((pimldp->fStyle & ILD_IMAGE) && !bUseCustomBackground)
251 BitBlt(pimldp->hdcDst,
252 pimldp->x, pimldp->y, cx, cy,
253 hImageDC,
254 himlLocal->cx * pimldp->i, 0,
255 SRCCOPY);
257 /* Draw the mask with or without a background
259 else if(pimldp->fStyle & ILD_MASK)
261 BitBlt(pimldp->hdcDst,
262 pimldp->x, pimldp->y, cx, cy,
263 hMaskDC,
264 himlLocal->cx * pimldp->i, 0,
265 bUseCustomBackground ? SRCCOPY : SRCAND);
267 SelectObject(hImageDC, hOldBitmapImage);
268 SelectObject(hMaskDC, hOldBitmapMask);
269 DeleteDC(hImageDC);
270 DeleteDC(hMaskDC);
273 /*************************************************************************
274 * IMAGELIST_InternalDrawBlend [Internal]
276 * Draws the Blend over the current image
278 * PARAMS
279 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
280 * cx [I] the width of the image to display
281 * cy............[I] the height of the image to display
283 * RETURNS
284 * nothing
286 * NOTES
287 * This functions is used by ImageList_DrawIndirect, when it is
288 * required to add the blend to the current image.
291 static VOID
292 IMAGELIST_InternalDrawBlend(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
295 HDC hBlendMaskDC,hMaskDC;
296 HBRUSH hBlendColorBrush, hBlendBrush, hOldBrush;
297 HBITMAP hBlendMaskBitmap, hOldBitmap;
298 COLORREF clrBlend, OldTextColor, OldBkColor;
299 HIMAGELIST himlLocal = pimldp->himl;
301 clrBlend = GetSysColor (COLOR_HIGHLIGHT);
302 if (!(pimldp->rgbFg == CLR_DEFAULT))
304 clrBlend = pimldp->rgbFg;
306 /* Create the blend Mask
308 hBlendMaskDC = CreateCompatibleDC(0);
309 hBlendBrush = pimldp->fStyle & ILD_BLEND50 ?
310 himlLocal->hbrBlend50 : himlLocal->hbrBlend25;
312 hBlendMaskBitmap = CreateBitmap(cx, cy, 1, 1, NULL);
313 hOldBitmap = SelectObject(hBlendMaskDC, hBlendMaskBitmap);
315 hOldBrush = (HBRUSH) SelectObject(hBlendMaskDC, hBlendBrush);
316 PatBlt(hBlendMaskDC, 0, 0, cx, cy, PATCOPY);
317 SelectObject(hBlendMaskDC, hOldBrush);
319 /* Modify the blend mask if an Image Mask exist
321 if(pimldp->himl->hbmMask != 0)
323 HBITMAP hOldMaskBitmap;
324 hMaskDC = CreateCompatibleDC(0);
325 hOldMaskBitmap = (HBITMAP) SelectObject(hMaskDC, himlLocal->hbmMask);
327 BitBlt(hBlendMaskDC,
328 0,0, cx, cy,
329 hMaskDC,
330 himlLocal->cx * pimldp->i,0,
331 0x220326); /* NOTSRCAND */
333 BitBlt(hBlendMaskDC,
334 0,0, cx, cy,
335 hBlendMaskDC,
336 0,0,
337 NOTSRCCOPY);
339 SelectObject(hMaskDC, hOldMaskBitmap);
340 DeleteDC(hMaskDC);
343 /* Apply blend to the current image given the BlendMask
345 OldTextColor = SetTextColor(pimldp->hdcDst, 0);
346 OldBkColor = SetBkColor(pimldp->hdcDst, RGB(255,255,255));
347 hBlendColorBrush = CreateSolidBrush(clrBlend);
348 hOldBrush = (HBRUSH) SelectObject (pimldp->hdcDst, hBlendColorBrush);
350 BitBlt (pimldp->hdcDst,
351 pimldp->x, pimldp->y, cx, cy,
352 hBlendMaskDC,
353 0, 0,
354 0xB8074A); /* PSDPxax */
356 SelectObject(pimldp->hdcDst, hOldBrush);
357 SetTextColor(pimldp->hdcDst, OldTextColor);
358 SetBkColor(pimldp->hdcDst, OldBkColor);
359 SelectObject(hBlendMaskDC, hOldBitmap);
360 DeleteDC(hBlendMaskDC);
361 DeleteObject(hBlendMaskBitmap);
362 DeleteObject(hBlendColorBrush);
365 /*************************************************************************
366 * IMAGELIST_InternalDrawOverlay [Internal]
368 * Draws the overlay image
370 * PARAMS
371 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
372 * cx [I] the width of the image to display
373 * cy............[I] the height of the image to display
375 * RETURNS
376 * nothing
378 * NOTES
379 * This functions is used by ImageList_DrawIndirect, when it is
380 * required to draw the overlay
384 static VOID
385 IMAGELIST_InternalDrawOverlay(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
387 INT nOvlIdx;
388 HDC hImageDC;
389 HBITMAP hOldBitmap;
391 nOvlIdx = (pimldp->fStyle & 0x0700) >> 8;
392 if ((nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE))
394 nOvlIdx = pimldp->himl->nOvlIdx[nOvlIdx - 1];
395 if ((nOvlIdx >= 0) && (nOvlIdx <= pimldp->himl->cCurImage))
397 hImageDC = CreateCompatibleDC(0);
398 if (pimldp->himl->hbmMask)
400 hOldBitmap = (HBITMAP) SelectObject (hImageDC,
401 pimldp->himl->hbmMask);
403 BitBlt (pimldp->hdcDst,
404 pimldp->x, pimldp->y, cx, cy,
405 hImageDC, pimldp->himl->cx * nOvlIdx, 0,
406 SRCAND);
408 SelectObject(hImageDC, hOldBitmap);
410 hOldBitmap = (HBITMAP) SelectObject (hImageDC,
411 pimldp->himl->hbmImage);
413 BitBlt (pimldp->hdcDst,
414 pimldp->x, pimldp->y, cx, cy,
415 hImageDC,
416 pimldp->himl->cx * nOvlIdx, 0,
417 SRCPAINT);
419 SelectObject(hImageDC, hOldBitmap);
420 DeleteDC(hImageDC);
429 /*************************************************************************
430 * ImageList_Add [COMCTL32.39]
432 * Add an image or images to an image list.
434 * PARAMS
435 * himl [I] handle to image list
436 * hbmImage [I] handle to image bitmap
437 * hbmMask [I] handle to mask bitmap
439 * RETURNS
440 * Success: Index of the first new image.
441 * Failure: -1
444 INT WINAPI
445 ImageList_Add (HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
447 HDC hdcImage, hdcBitmap;
448 INT nFirstIndex, nImageCount;
449 INT nStartX;
450 BITMAP bmp;
451 HBITMAP hOldBitmapImage, hOldBitmap;
453 if (!himl || !hbmImage)
454 return -1;
456 GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
457 nImageCount = bmp.bmWidth / himl->cx;
459 if (himl->cCurImage + nImageCount >= himl->cMaxImage)
460 IMAGELIST_InternalExpandBitmaps (himl, nImageCount);
462 nStartX = himl->cCurImage * himl->cx;
464 hdcImage = CreateCompatibleDC(0);
465 hdcBitmap = CreateCompatibleDC(0);
467 hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
468 hOldBitmap = SelectObject(hdcBitmap, hbmImage);
470 /* Copy result to the imagelist
472 BitBlt (hdcImage, nStartX, 0, bmp.bmWidth, himl->cy,
473 hdcBitmap, 0, 0, SRCCOPY);
475 if(himl->hbmMask)
477 HDC hdcMask, hdcTemp, hOldBitmapMask, hOldBitmapTemp;
479 hdcMask = CreateCompatibleDC (0);
480 hdcTemp = CreateCompatibleDC(0);
481 hOldBitmapMask = (HBITMAP) SelectObject(hdcMask, himl->hbmMask);
482 hOldBitmapTemp = (HBITMAP) SelectObject(hdcTemp, hbmMask);
484 BitBlt (hdcMask,
485 nStartX, 0, bmp.bmWidth, himl->cy,
486 hdcTemp,
487 0, 0,
488 SRCCOPY);
490 SelectObject(hdcTemp, hOldBitmapTemp);
491 DeleteDC(hdcTemp);
493 /* Remove the background from the image
495 BitBlt (hdcImage,
496 nStartX, 0, bmp.bmWidth, himl->cy,
497 hdcMask,
498 nStartX, 0,
499 0x220326); /* NOTSRCAND */
501 SelectObject(hdcMask, hOldBitmapMask);
502 DeleteDC(hdcMask);
505 SelectObject(hdcImage, hOldBitmapImage);
506 SelectObject(hdcBitmap, hOldBitmap);
507 DeleteDC(hdcImage);
508 DeleteDC(hdcBitmap);
510 nFirstIndex = himl->cCurImage;
511 himl->cCurImage += nImageCount;
513 return nFirstIndex;
517 /*************************************************************************
518 * ImageList_AddIcon [COMCTL32.40]
520 * Adds an icon to an image list.
522 * PARAMS
523 * himl [I] handle to image list
524 * hIcon [I] handle to icon
526 * RETURNS
527 * Success: index of the new image
528 * Failure: -1
531 INT WINAPI
532 ImageList_AddIcon (HIMAGELIST himl, HICON hIcon)
534 return ImageList_ReplaceIcon (himl, -1, hIcon);
538 /*************************************************************************
539 * ImageList_AddMasked [COMCTL32.41]
541 * Adds an image or images to an image list and creates a mask from the
542 * specified bitmap using the mask color.
544 * PARAMS
545 * himl [I] handle to image list.
546 * hBitmap [I] handle to bitmap
547 * clrMask [I] mask color.
549 * RETURNS
550 * Success: Index of the first new image.
551 * Failure: -1
554 INT WINAPI
555 ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
557 HDC hdcImage, hdcMask, hdcBitmap;
558 INT nIndex, nImageCount, nMaskXOffset=0;
559 BITMAP bmp;
560 HBITMAP hOldBitmap, hOldBitmapMask, hOldBitmapImage;
561 HBITMAP hMaskBitmap=0;
562 COLORREF bkColor;
564 if (himl == NULL)
565 return -1;
567 if (!GetObjectA (hBitmap, sizeof(BITMAP), &bmp))
568 return -1;
570 nImageCount = bmp.bmWidth / himl->cx;
572 if (himl->cCurImage + nImageCount >= himl->cMaxImage)
574 IMAGELIST_InternalExpandBitmaps (himl, nImageCount);
577 nIndex = himl->cCurImage;
578 himl->cCurImage += nImageCount;
580 hdcMask = CreateCompatibleDC (0);
581 hdcImage = CreateCompatibleDC(0);
582 hdcBitmap = CreateCompatibleDC(0);
585 hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
586 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
587 if(himl->hbmMask)
589 hOldBitmapMask = SelectObject(hdcMask, himl->hbmMask);
590 nMaskXOffset = nIndex * himl->cx;
592 else
595 Create a temp Mask so we can remove the background of
596 the Image (Windows does this even if there is no mask)
598 hMaskBitmap = CreateBitmap(bmp.bmWidth, himl->cy, 1, 1, NULL);
599 hOldBitmapMask = SelectObject(hdcMask, hMaskBitmap);
600 nMaskXOffset = 0;
602 /* create monochrome image to the mask bitmap */
603 bkColor = (clrMask != CLR_DEFAULT) ? clrMask :
604 GetPixel (hdcBitmap, 0, 0);
605 SetBkColor (hdcBitmap, bkColor);
606 BitBlt (hdcMask,
607 nMaskXOffset, 0, bmp.bmWidth, himl->cy,
608 hdcBitmap, 0, 0,
609 SRCCOPY);
611 SetBkColor(hdcBitmap, RGB(255,255,255));
612 /*Remove the background from the image
615 WINDOWS BUG ALERT!!!!!!
616 The statement below should not be done in common practice
617 but this is how ImageList_AddMasked works in Windows.
618 It overwrites the original bitmap passed, this was discovered
619 by using the same bitmap to itterated the different styles
620 on windows where it failed (BUT ImageList_Add is OK)
621 This is here in case some apps really on this bug
623 BitBlt(hdcBitmap,
624 0, 0, bmp.bmWidth, himl->cy,
625 hdcMask,
626 nMaskXOffset, 0,
627 0x220326); /* NOTSRCAND */
628 /* Copy result to the imagelist
630 BitBlt (hdcImage,
631 nIndex * himl->cx, 0, bmp.bmWidth, himl->cy,
632 hdcBitmap,
633 0, 0,
634 SRCCOPY);
635 /* Clean up
637 SelectObject(hdcMask,hOldBitmapMask);
638 SelectObject(hdcImage, hOldBitmapImage);
639 SelectObject(hdcBitmap, hOldBitmap);
640 DeleteDC(hdcMask);
641 DeleteDC(hdcImage);
642 DeleteDC(hdcBitmap);
643 if(!himl->hbmMask)
645 DeleteObject(hMaskBitmap);
648 return nIndex;
652 /*************************************************************************
653 * ImageList_BeginDrag [COMCTL32.42]
655 * Creates a temporary image list that contains one image. It will be used
656 * as a drag image.
658 * PARAMS
659 * himlTrack [I] handle to the source image list
660 * iTrack [I] index of the drag image in the source image list
661 * dxHotspot [I] X position of the hot spot of the drag image
662 * dyHotspot [I] Y position of the hot spot of the drag image
664 * RETURNS
665 * Success: TRUE
666 * Failure: FALSE
669 BOOL WINAPI
670 ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
671 INT dxHotspot, INT dyHotspot)
673 HDC hdcSrc, hdcDst;
675 FIXME("partially implemented!\n");
677 if (himlTrack == NULL)
678 return FALSE;
680 if (himlInternalDrag)
681 ImageList_EndDrag ();
683 himlInternalDrag =
684 ImageList_Create (himlTrack->cx, himlTrack->cy,
685 himlTrack->flags, 1, 1);
686 if (himlInternalDrag == NULL) {
687 ERR("Error creating drag image list!\n");
688 return FALSE;
691 nInternalDragHotspotX = dxHotspot;
692 nInternalDragHotspotY = dyHotspot;
694 hdcSrc = CreateCompatibleDC (0);
695 hdcDst = CreateCompatibleDC (0);
697 /* copy image */
698 SelectObject (hdcSrc, himlTrack->hbmImage);
699 SelectObject (hdcDst, himlInternalDrag->hbmImage);
700 StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
701 iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
703 /* copy mask */
704 SelectObject (hdcSrc, himlTrack->hbmMask);
705 SelectObject (hdcDst, himlInternalDrag->hbmMask);
706 StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
707 iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
709 DeleteDC (hdcSrc);
710 DeleteDC (hdcDst);
712 himlInternalDrag->cCurImage = 1;
714 return TRUE;
718 /*************************************************************************
719 * ImageList_Copy [COMCTL32.43]
721 * Copies an image of the source image list to an image of the
722 * destination image list. Images can be copied or swapped.
724 * PARAMS
725 * himlDst [I] handle to the destination image list
726 * iDst [I] destination image index.
727 * himlSrc [I] handle to the source image list
728 * iSrc [I] source image index
729 * uFlags [I] flags for the copy operation
731 * RETURNS
732 * Success: TRUE
733 * Failure: FALSE
735 * NOTES
736 * Copying from one image list to another is possible. The original
737 * implementation just copies or swapps within one image list.
738 * Could this feature become a bug??? ;-)
741 BOOL WINAPI
742 ImageList_Copy (HIMAGELIST himlDst, INT iDst, HIMAGELIST himlSrc,
743 INT iSrc, INT uFlags)
745 HDC hdcSrc, hdcDst;
747 TRACE("iDst=%d iSrc=%d\n", iDst, iSrc);
749 if ((himlSrc == NULL) || (himlDst == NULL))
750 return FALSE;
751 if ((iDst < 0) || (iDst >= himlDst->cCurImage))
752 return FALSE;
753 if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage))
754 return FALSE;
756 hdcSrc = CreateCompatibleDC (0);
757 if (himlDst == himlSrc)
758 hdcDst = hdcSrc;
759 else
760 hdcDst = CreateCompatibleDC (0);
762 if (uFlags & ILCF_SWAP) {
763 /* swap */
764 HBITMAP hbmTempImage, hbmTempMask;
766 /* create temporary bitmaps */
767 hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
768 himlSrc->uBitsPixel, NULL);
769 hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
770 1, NULL);
772 /* copy (and stretch) destination to temporary bitmaps.(save) */
773 /* image */
774 SelectObject (hdcSrc, himlDst->hbmImage);
775 SelectObject (hdcDst, hbmTempImage);
776 StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
777 hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
778 SRCCOPY);
779 /* mask */
780 SelectObject (hdcSrc, himlDst->hbmMask);
781 SelectObject (hdcDst, hbmTempMask);
782 StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
783 hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
784 SRCCOPY);
786 /* copy (and stretch) source to destination */
787 /* image */
788 SelectObject (hdcSrc, himlSrc->hbmImage);
789 SelectObject (hdcDst, himlDst->hbmImage);
790 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
791 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
792 SRCCOPY);
793 /* mask */
794 SelectObject (hdcSrc, himlSrc->hbmMask);
795 SelectObject (hdcDst, himlDst->hbmMask);
796 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
797 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
798 SRCCOPY);
800 /* copy (without stretching) temporary bitmaps to source (restore) */
801 /* image */
802 SelectObject (hdcSrc, hbmTempImage);
803 SelectObject (hdcDst, himlSrc->hbmImage);
804 BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
805 hdcSrc, 0, 0, SRCCOPY);
806 /* mask */
807 SelectObject (hdcSrc, hbmTempMask);
808 SelectObject (hdcDst, himlSrc->hbmMask);
809 BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
810 hdcSrc, 0, 0, SRCCOPY);
812 /* delete temporary bitmaps */
813 DeleteObject (hbmTempMask);
814 DeleteObject (hbmTempImage);
816 else {
817 /* copy image */
818 SelectObject (hdcSrc, himlSrc->hbmImage);
819 if (himlSrc == himlDst)
820 hdcDst = hdcSrc;
821 else
822 SelectObject (hdcDst, himlDst->hbmImage);
823 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
824 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
825 SRCCOPY);
827 /* copy mask */
828 SelectObject (hdcSrc, himlSrc->hbmMask);
829 if (himlSrc == himlDst)
830 hdcDst = hdcSrc;
831 else
832 SelectObject (hdcDst, himlDst->hbmMask);
833 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
834 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
835 SRCCOPY);
838 DeleteDC (hdcSrc);
839 if (himlSrc != himlDst)
840 DeleteDC (hdcDst);
842 return TRUE;
846 /*************************************************************************
847 * ImageList_Create [COMCTL32.44] Creates a new image list.
849 * PARAMS
850 * cx [I] image height
851 * cy [I] image width
852 * flags [I] creation flags
853 * cInitial [I] initial number of images in the image list
854 * cGrow [I] number of images by which image list grows
856 * RETURNS
857 * Success: Handle to the created image list
858 * Failure: NULL
861 HIMAGELIST WINAPI
862 ImageList_Create (INT cx, INT cy, UINT flags,
863 INT cInitial, INT cGrow)
865 HIMAGELIST himl;
866 HDC hdc;
867 INT nCount;
868 HBITMAP hbmTemp;
869 static WORD aBitBlend25[] =
870 {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00};
872 static WORD aBitBlend50[] =
873 {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
875 TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow);
877 himl = (HIMAGELIST)COMCTL32_Alloc (sizeof(struct _IMAGELIST));
878 if (!himl)
879 return NULL;
881 himl->cx = cx;
882 himl->cy = cy;
883 himl->flags = flags;
884 himl->cMaxImage = cInitial + cGrow;
885 himl->cInitial = cInitial;
886 himl->cGrow = cGrow;
887 himl->cCurImage = 0;
888 himl->clrFg = CLR_DEFAULT;
889 himl->clrBk = CLR_NONE;
891 /* initialize overlay mask indices */
892 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
893 himl->nOvlIdx[nCount] = -1;
895 hdc = CreateCompatibleDC (0);
896 himl->uBitsPixel = (UINT)GetDeviceCaps (hdc, BITSPIXEL);
897 DeleteDC (hdc);
899 TRACE("Image: %d Bits per Pixel\n", himl->uBitsPixel);
901 if (himl->cMaxImage > 0) {
902 himl->hbmImage =
903 CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
904 1, himl->uBitsPixel, NULL);
905 if (himl->hbmImage == 0) {
906 ERR("Error creating image bitmap!\n");
907 return NULL;
910 else
911 himl->hbmImage = 0;
913 if ( (himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) {
914 himl->hbmMask = CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
915 1, 1, NULL);
916 if (himl->hbmMask == 0) {
917 ERR("Error creating mask bitmap!\n");
918 if (himl->hbmImage)
919 DeleteObject (himl->hbmImage);
920 return NULL;
923 else
924 himl->hbmMask = 0;
926 /* create blending brushes */
927 hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend25);
928 himl->hbrBlend25 = CreatePatternBrush (hbmTemp);
929 DeleteObject (hbmTemp);
931 hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend50);
932 himl->hbrBlend50 = CreatePatternBrush (hbmTemp);
933 DeleteObject (hbmTemp);
935 return himl;
939 /*************************************************************************
940 * ImageList_Destroy [COMCTL32.45]
942 * Destroys an image list.
944 * PARAMS
945 * himl [I] handle to image list
947 * RETURNS
948 * Success: TRUE
949 * Failure: FALSE
952 BOOL WINAPI
953 ImageList_Destroy (HIMAGELIST himl)
955 if (!himl)
956 return FALSE;
958 /* delete image bitmaps */
959 if (himl->hbmImage)
960 DeleteObject (himl->hbmImage);
961 if (himl->hbmMask)
962 DeleteObject (himl->hbmMask);
964 /* delete blending brushes */
965 if (himl->hbrBlend25)
966 DeleteObject (himl->hbrBlend25);
967 if (himl->hbrBlend50)
968 DeleteObject (himl->hbrBlend50);
970 COMCTL32_Free (himl);
972 return TRUE;
976 /*************************************************************************
977 * ImageList_DragEnter [COMCTL32.46]
979 * Locks window update and displays the drag image at the given position.
981 * PARAMS
982 * hwndLock [I] handle of the window that owns the drag image.
983 * x [I] X position of the drag image.
984 * y [I] Y position of the drag image.
986 * RETURNS
987 * Success: TRUE
988 * Failure: FALSE
990 * NOTES
991 * The position of the drag image is relative to the window, not
992 * the client area.
995 BOOL WINAPI
996 ImageList_DragEnter (HWND hwndLock, INT x, INT y)
998 if (himlInternalDrag == NULL)
999 return FALSE;
1001 if (hwndLock)
1002 hwndInternalDrag = hwndLock;
1003 else
1004 hwndInternalDrag = GetDesktopWindow ();
1006 xInternalPos = x;
1007 yInternalPos = y;
1009 hdcBackBuffer = CreateCompatibleDC (0);
1010 hbmBackBuffer = CreateCompatibleBitmap (hdcBackBuffer,
1011 himlInternalDrag->cx, himlInternalDrag->cy);
1013 ImageList_DragShowNolock (TRUE);
1015 return FALSE;
1019 /*************************************************************************
1020 * ImageList_DragLeave [COMCTL32.47]
1022 * Unlocks window update and hides the drag image.
1024 * PARAMS
1025 * hwndLock [I] handle of the window that owns the drag image.
1027 * RETURNS
1028 * Success: TRUE
1029 * Failure: FALSE
1032 BOOL WINAPI
1033 ImageList_DragLeave (HWND hwndLock)
1035 if (hwndLock)
1036 hwndInternalDrag = hwndLock;
1037 else
1038 hwndInternalDrag = GetDesktopWindow ();
1040 ImageList_DragShowNolock (FALSE);
1042 DeleteDC (hdcBackBuffer);
1043 DeleteObject (hbmBackBuffer);
1045 return TRUE;
1049 /*************************************************************************
1050 * ImageList_DragMove [COMCTL32.48]
1052 * Moves the drag image.
1054 * PARAMS
1055 * x [I] X position of the drag image.
1056 * y [I] Y position of the drag image.
1058 * RETURNS
1059 * Success: TRUE
1060 * Failure: FALSE
1062 * NOTES
1063 * The position of the drag image is relative to the window, not
1064 * the client area.
1067 BOOL WINAPI
1068 ImageList_DragMove (INT x, INT y)
1070 ImageList_DragShowNolock (FALSE);
1072 xInternalPos = x;
1073 yInternalPos = y;
1075 ImageList_DragShowNolock (TRUE);
1077 return FALSE;
1081 /*************************************************************************
1082 * ImageList_DragShowNolock [COMCTL32.49]
1084 * Shows or hides the drag image.
1086 * PARAMS
1087 * bShow [I] TRUE shows the drag image, FALSE hides it.
1089 * RETURNS
1090 * Success: TRUE
1091 * Failure: FALSE
1093 * FIXME
1094 * semi-stub.
1097 BOOL WINAPI
1098 ImageList_DragShowNolock (BOOL bShow)
1100 HDC hdcDrag;
1102 FIXME("semi-stub!\n");
1103 TRACE("bShow=0x%X!\n", bShow);
1105 hdcDrag = GetDCEx (hwndInternalDrag, 0,
1106 DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
1108 if (bShow) {
1109 /* show drag image */
1111 /* save background */
1113 /* draw drag image */
1116 else {
1117 /* hide drag image */
1119 /* restore background */
1123 ReleaseDC (hwndInternalDrag, hdcDrag);
1125 return FALSE;
1129 /*************************************************************************
1130 * ImageList_Draw [COMCTL32.50] Draws an image.
1132 * PARAMS
1133 * himl [I] handle to image list
1134 * i [I] image index
1135 * hdc [I] handle to device context
1136 * x [I] x position
1137 * y [I] y position
1138 * fStyle [I] drawing flags
1140 * RETURNS
1141 * Success: TRUE
1142 * Failure: FALSE
1144 * NOTES
1145 * Calls ImageList_DrawIndirect.
1147 * SEE
1148 * ImageList_DrawIndirect.
1151 BOOL WINAPI
1152 ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc,
1153 INT x, INT y, UINT fStyle)
1155 IMAGELISTDRAWPARAMS imldp;
1157 imldp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
1158 imldp.himl = himl;
1159 imldp.i = i;
1160 imldp.hdcDst = hdc,
1161 imldp.x = x;
1162 imldp.y = y;
1163 imldp.cx = 0;
1164 imldp.cy = 0;
1165 imldp.xBitmap = 0;
1166 imldp.yBitmap = 0;
1167 imldp.rgbBk = CLR_DEFAULT;
1168 imldp.rgbFg = CLR_DEFAULT;
1169 imldp.fStyle = fStyle;
1170 imldp.dwRop = 0;
1172 return ImageList_DrawIndirect (&imldp);
1176 /*************************************************************************
1177 * ImageList_DrawEx [COMCTL32.51]
1179 * Draws an image and allows to use extended drawing features.
1181 * PARAMS
1182 * himl [I] handle to image list
1183 * i [I] image index
1184 * hdc [I] handle to device context
1185 * x [I] X position
1186 * y [I] Y position
1187 * xOffs [I] X offset
1188 * yOffs [I] Y offset
1189 * rgbBk [I] background color
1190 * rgbFg [I] foreground color
1191 * fStyle [I] drawing flags
1193 * RETURNS
1194 * Success: TRUE
1195 * Failure: FALSE
1197 * NOTES
1198 * Calls ImageList_DrawIndirect.
1200 * SEE
1201 * ImageList_DrawIndirect.
1204 BOOL WINAPI
1205 ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y,
1206 INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg,
1207 UINT fStyle)
1209 IMAGELISTDRAWPARAMS imldp;
1211 imldp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
1212 imldp.himl = himl;
1213 imldp.i = i;
1214 imldp.hdcDst = hdc,
1215 imldp.x = x;
1216 imldp.y = y;
1217 imldp.cx = dx;
1218 imldp.cy = dy;
1219 imldp.xBitmap = 0;
1220 imldp.yBitmap = 0;
1221 imldp.rgbBk = rgbBk;
1222 imldp.rgbFg = rgbFg;
1223 imldp.fStyle = fStyle;
1224 imldp.dwRop = 0;
1226 return ImageList_DrawIndirect (&imldp);
1230 /*************************************************************************
1231 * ImageList_DrawIndirect [COMCTL32.52]
1233 * Draws an image using ...
1235 * PARAMS
1236 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
1238 * RETURNS
1239 * Success: TRUE
1240 * Failure: FALSE
1243 BOOL WINAPI
1244 ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
1246 INT cx, cy;
1248 Do some Error Checking
1250 if (pimldp == NULL)
1251 return FALSE;
1252 if (pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS))
1253 return FALSE;
1254 if (pimldp->himl == NULL)
1255 return FALSE;
1256 if ((pimldp->i < 0) || (pimldp->i > pimldp->himl->cCurImage)) {
1257 ERR("%d not within range (max %d)\n",pimldp->i,pimldp->himl->cCurImage);
1258 return FALSE;
1261 Get the Height and Width to display
1263 cx = (pimldp->cx == 0) ? pimldp->himl->cx : pimldp->cx;
1264 cy = (pimldp->cy == 0) ? pimldp->himl->cy : pimldp->cy;
1266 Draw the image
1268 if(pimldp->himl->hbmMask != 0)
1270 IMAGELIST_InternalDrawMask(pimldp, cx, cy);
1272 else
1274 IMAGELIST_InternalDraw(pimldp, cx, cy);
1277 Apply the blend if needed to the Image
1279 if((pimldp->fStyle & ILD_BLEND50)
1280 || (pimldp->fStyle & ILD_BLEND25))
1282 IMAGELIST_InternalDrawBlend(pimldp, cx, cy);
1285 Apply the Overlay if needed
1287 if (pimldp->fStyle & 0x0700)
1289 IMAGELIST_InternalDrawOverlay(pimldp, cx, cy);
1292 return TRUE;
1296 /*************************************************************************
1297 * ImageList_Duplicate [COMCTL32.53] Duplicates an image list.
1299 * PARAMS
1300 * himlSrc [I] source image list handle
1302 * RETURNS
1303 * Success: Handle of duplicated image list.
1304 * Failure: NULL
1307 HIMAGELIST WINAPI
1308 ImageList_Duplicate (HIMAGELIST himlSrc)
1310 HIMAGELIST himlDst;
1311 HDC hdcSrc, hdcDst;
1313 if (himlSrc == NULL) {
1314 ERR("Invalid image list handle!\n");
1315 return NULL;
1318 himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
1319 himlSrc->cInitial, himlSrc->cGrow);
1321 if (himlDst)
1323 hdcSrc = CreateCompatibleDC (0);
1324 hdcDst = CreateCompatibleDC (0);
1325 SelectObject (hdcSrc, himlSrc->hbmImage);
1326 SelectObject (hdcDst, himlDst->hbmImage);
1327 BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy,
1328 hdcSrc, 0, 0, SRCCOPY);
1330 if (himlDst->hbmMask)
1332 SelectObject (hdcSrc, himlSrc->hbmMask);
1333 SelectObject (hdcDst, himlDst->hbmMask);
1334 BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx,
1335 himlSrc->cy, hdcSrc, 0, 0, SRCCOPY);
1338 DeleteDC (hdcDst);
1339 DeleteDC (hdcSrc);
1341 himlDst->cCurImage = himlSrc->cCurImage;
1342 himlDst->cMaxImage = himlSrc->cMaxImage;
1344 return himlDst;
1348 /*************************************************************************
1349 * ImageList_EndDrag [COMCTL32.54] Finishes a drag operation.
1351 * Finishes a drag operation.
1353 * PARAMS
1354 * no Parameters
1356 * RETURNS
1357 * Success: TRUE
1358 * Failure: FALSE
1360 * BUGS
1361 * semi-stub.
1364 BOOL WINAPI
1365 ImageList_EndDrag (void)
1367 FIXME("semi-stub!\n");
1369 if (himlInternalDrag)
1372 ImageList_Destroy (himlInternalDrag);
1373 himlInternalDrag = NULL;
1375 nInternalDragHotspotX = 0;
1376 nInternalDragHotspotY = 0;
1380 return TRUE;
1384 /*************************************************************************
1385 * ImageList_GetBkColor [COMCTL32.55]
1387 * Returns the background color of an image list.
1389 * PARAMS
1390 * himl [I] Image list handle.
1392 * RETURNS
1393 * Success: background color
1394 * Failure: CLR_NONE
1397 COLORREF WINAPI
1398 ImageList_GetBkColor (HIMAGELIST himl)
1400 if (himl == NULL)
1401 return CLR_NONE;
1403 return himl->clrBk;
1407 /*************************************************************************
1408 * ImageList_GetDragImage [COMCTL32.56]
1410 * Returns the handle to the internal drag image list.
1412 * PARAMS
1413 * ppt [O] Pointer to the drag position. Can be NULL.
1414 * pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
1416 * RETURNS
1417 * Success: Handle of the drag image list.
1418 * Failure: NULL.
1420 * BUGS
1421 * semi-stub.
1424 HIMAGELIST WINAPI
1425 ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot)
1427 FIXME("semi-stub!\n");
1429 if (himlInternalDrag)
1430 return (himlInternalDrag);
1432 return NULL;
1436 /*************************************************************************
1437 * ImageList_GetIcon [COMCTL32.57]
1439 * Creates an icon from a masked image of an image list.
1441 * PARAMS
1442 * himl [I] handle to image list
1443 * i [I] image index
1444 * flags [I] drawing style flags
1446 * RETURNS
1447 * Success: icon handle
1448 * Failure: NULL
1451 HICON WINAPI
1452 ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle)
1454 ICONINFO ii;
1455 HICON hIcon;
1456 HBITMAP hOldSrcBitmap,hOldDstBitmap;
1457 HDC hdcSrc, hdcDst;
1459 if ((himl == NULL) || (i < 0) || (i >= himl->cCurImage)) {
1460 FIXME("(%p,%d,%x), params out of range!\n",himl,i,fStyle);
1461 return 0;
1464 hdcSrc = CreateCompatibleDC(0);
1465 hdcDst = CreateCompatibleDC(0);
1467 ii.fIcon = TRUE;
1468 ii.hbmMask = CreateCompatibleBitmap (hdcDst, himl->cx, himl->cy);
1470 /* draw mask*/
1471 hOldDstBitmap = (HBITMAP)SelectObject (hdcDst, ii.hbmMask);
1472 if (himl->hbmMask) {
1473 SelectObject (hdcSrc, himl->hbmMask);
1474 BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1475 hdcSrc, i * himl->cx, 0, SRCCOPY);
1477 else
1478 PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS);
1480 /* draw image*/
1481 hOldSrcBitmap = (HBITMAP)SelectObject (hdcSrc, himl->hbmImage);
1482 ii.hbmColor = CreateCompatibleBitmap (hdcSrc, himl->cx, himl->cy);
1483 SelectObject (hdcDst, ii.hbmColor);
1484 BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1485 hdcSrc, i * himl->cx, 0, SRCCOPY);
1488 * CreateIconIndirect requires us to deselect the bitmaps from
1489 * the DCs before calling
1491 SelectObject(hdcSrc, hOldSrcBitmap);
1492 SelectObject(hdcDst, hOldDstBitmap);
1494 hIcon = CreateIconIndirect (&ii);
1496 DeleteDC (hdcSrc);
1497 DeleteDC (hdcDst);
1498 DeleteObject (ii.hbmMask);
1499 DeleteObject (ii.hbmColor);
1501 return hIcon;
1505 /*************************************************************************
1506 * ImageList_GetIconSize [COMCTL32.58]
1508 * Retrieves the size of an image in an image list.
1510 * PARAMS
1511 * himl [I] handle to image list
1512 * cx [O] pointer to the image width.
1513 * cy [O] pointer to the image height.
1515 * RETURNS
1516 * Success: TRUE
1517 * Failure: FALSE
1519 * NOTES
1520 * All images in an image list have the same size.
1523 BOOL WINAPI
1524 ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy)
1526 if (himl == NULL)
1527 return FALSE;
1528 if ((himl->cx <= 0) || (himl->cy <= 0))
1529 return FALSE;
1531 if (cx)
1532 *cx = himl->cx;
1533 if (cy)
1534 *cy = himl->cy;
1536 return TRUE;
1540 /*************************************************************************
1541 * ImageList_GetImageCount [COMCTL32.59]
1543 * Returns the number of images in an image list.
1545 * PARAMS
1546 * himl [I] handle to image list
1548 * RETURNS
1549 * Success: Number of images.
1550 * Failure: 0
1553 INT WINAPI
1554 ImageList_GetImageCount (HIMAGELIST himl)
1556 if (himl == NULL)
1557 return 0;
1559 return himl->cCurImage;
1563 /*************************************************************************
1564 * ImageList_GetImageInfo [COMCTL32.60]
1566 * Returns information about an image in an image list.
1568 * PARAMS
1569 * himl [I] handle to image list
1570 * i [I] image index
1571 * pImageInfo [O] pointer to the image information
1573 * RETURNS
1574 * Success: TRUE
1575 * Failure: FALSE
1578 BOOL WINAPI
1579 ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
1581 if ((himl == NULL) || (pImageInfo == NULL))
1582 return FALSE;
1583 if ((i < 0) || (i >= himl->cCurImage))
1584 return FALSE;
1586 pImageInfo->hbmImage = himl->hbmImage;
1587 pImageInfo->hbmMask = himl->hbmMask;
1589 pImageInfo->rcImage.top = 0;
1590 pImageInfo->rcImage.bottom = himl->cy;
1591 pImageInfo->rcImage.left = i * himl->cx;
1592 pImageInfo->rcImage.right = (i+1) * himl->cx;
1594 return TRUE;
1598 /*************************************************************************
1599 * ImageList_GetImageRect [COMCTL32.61]
1601 * Retrieves the rectangle of the specified image in an image list.
1603 * PARAMS
1604 * himl [I] handle to image list
1605 * i [I] image index
1606 * lpRect [O] pointer to the image rectangle
1608 * RETURNS
1609 * Success: TRUE
1610 * Failure: FALSE
1612 * NOTES
1613 * This is an UNDOCUMENTED function!!!
1616 BOOL WINAPI
1617 ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect)
1619 if ((himl == NULL) || (lpRect == NULL))
1620 return FALSE;
1621 if ((i < 0) || (i >= himl->cCurImage))
1622 return FALSE;
1624 lpRect->left = i * himl->cx;
1625 lpRect->top = 0;
1626 lpRect->right = lpRect->left + himl->cx;
1627 lpRect->bottom = himl->cy;
1629 return TRUE;
1633 /*************************************************************************
1634 * ImageList_LoadImage32A [COMCTL32.63][COMCTL32.62]
1636 * Creates an image list from a bitmap, icon or cursor.
1638 * PARAMS
1639 * hi [I] instance handle
1640 * lpbmp [I] name or id of the image
1641 * cx [I] width of each image
1642 * cGrow [I] number of images to expand
1643 * clrMask [I] mask color
1644 * uType [I] type of image to load
1645 * uFlags [I] loading flags
1647 * RETURNS
1648 * Success: handle to the loaded image list
1649 * Failure: NULL
1651 * SEE
1652 * LoadImage ()
1655 HIMAGELIST WINAPI
1656 ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx, INT cGrow,
1657 COLORREF clrMask, UINT uType, UINT uFlags)
1659 HIMAGELIST himl = NULL;
1660 HANDLE handle;
1661 INT nImageCount;
1663 handle = LoadImageA (hi, lpbmp, uType, 0, 0, uFlags);
1664 if (!handle) {
1665 ERR("Error loading image!\n");
1666 return NULL;
1669 if (uType == IMAGE_BITMAP) {
1670 BITMAP bmp;
1671 GetObjectA (handle, sizeof(BITMAP), &bmp);
1673 /* To match windows behavior, if cx is set to zero and
1674 the flag DI_DEFAULTSIZE is specified, cx becomes the
1675 system metric value for icons. If the flag is not specified
1676 the function sets the size to the height of the bitmap */
1677 if (cx == 0)
1679 if (uFlags & DI_DEFAULTSIZE)
1680 cx = GetSystemMetrics (SM_CXICON);
1681 else
1682 cx = bmp.bmHeight;
1685 nImageCount = bmp.bmWidth / cx;
1687 himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1688 nImageCount, cGrow);
1689 ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1691 else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1692 ICONINFO ii;
1693 BITMAP bmp;
1695 GetIconInfo (handle, &ii);
1696 GetObjectA (ii.hbmColor, sizeof(BITMAP), (LPVOID)&bmp);
1697 himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1698 ILC_MASK | ILC_COLOR, 1, cGrow);
1699 ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1700 DeleteObject (ii.hbmColor);
1701 DeleteObject (ii.hbmMask);
1704 DeleteObject (handle);
1706 return himl;
1710 /*************************************************************************
1711 * ImageList_LoadImage32W [COMCTL32.64]
1713 * Creates an image list from a bitmap, icon or cursor.
1715 * PARAMS
1716 * hi [I] instance handle
1717 * lpbmp [I] name or id of the image
1718 * cx [I] width of each image
1719 * cGrow [I] number of images to expand
1720 * clrMask [I] mask color
1721 * uType [I] type of image to load
1722 * uFlags [I] loading flags
1724 * RETURNS
1725 * Success: handle to the loaded image list
1726 * Failure: NULL
1728 * SEE
1729 * LoadImage ()
1732 HIMAGELIST WINAPI
1733 ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow,
1734 COLORREF clrMask, UINT uType, UINT uFlags)
1736 HIMAGELIST himl = NULL;
1737 HANDLE handle;
1738 INT nImageCount;
1740 handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags);
1741 if (!handle) {
1742 ERR("Error loading image!\n");
1743 return NULL;
1746 if (uType == IMAGE_BITMAP) {
1747 BITMAP bmp;
1748 GetObjectA (handle, sizeof(BITMAP), &bmp);
1749 nImageCount = bmp.bmWidth / cx;
1751 himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1752 nImageCount, cGrow);
1753 ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1755 else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1756 ICONINFO ii;
1757 BITMAP bmp;
1759 GetIconInfo (handle, &ii);
1760 GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
1761 himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1762 ILC_MASK | ILC_COLOR, 1, cGrow);
1763 ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1764 DeleteObject (ii.hbmColor);
1765 DeleteObject (ii.hbmMask);
1768 DeleteObject (handle);
1770 return himl;
1774 /*************************************************************************
1775 * ImageList_Merge [COMCTL32.65]
1777 * Creates a new image list that contains a merged image from the specified
1778 * images of both source image lists.
1780 * PARAMS
1781 * himl1 [I] handle to first image list
1782 * i1 [I] first image index
1783 * himl2 [I] handle to second image list
1784 * i2 [I] second image index
1785 * dx [I] X offset of the second image relative to the first.
1786 * dy [I] Y offset of the second image relative to the first.
1788 * RETURNS
1789 * Success: handle of the merged image list.
1790 * Failure: NULL
1793 HIMAGELIST WINAPI
1794 ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
1795 INT dx, INT dy)
1797 HIMAGELIST himlDst = NULL;
1798 HDC hdcSrcImage, hdcDstImage;
1799 INT cxDst, cyDst;
1800 INT xOff1, yOff1, xOff2, yOff2;
1801 INT nX1, nX2;
1803 if ((himl1 == NULL) || (himl2 == NULL))
1804 return NULL;
1806 /* check indices */
1807 if ((i1 < 0) || (i1 >= himl1->cCurImage)) {
1808 ERR("Index 1 out of range! %d\n", i1);
1809 return NULL;
1812 if ((i2 < 0) || (i2 >= himl2->cCurImage)) {
1813 ERR("Index 2 out of range! %d\n", i2);
1814 return NULL;
1817 if (dx > 0) {
1818 cxDst = _MAX (himl1->cx, dx + himl2->cx);
1819 xOff1 = 0;
1820 xOff2 = dx;
1822 else if (dx < 0) {
1823 cxDst = _MAX (himl2->cx, himl1->cx - dx);
1824 xOff1 = -dx;
1825 xOff2 = 0;
1827 else {
1828 cxDst = _MAX (himl1->cx, himl2->cx);
1829 xOff1 = 0;
1830 xOff2 = 0;
1833 if (dy > 0) {
1834 cyDst = _MAX (himl1->cy, dy + himl2->cy);
1835 yOff1 = 0;
1836 yOff2 = dy;
1838 else if (dy < 0) {
1839 cyDst = _MAX (himl2->cy, himl1->cy - dy);
1840 yOff1 = -dy;
1841 yOff2 = 0;
1843 else {
1844 cyDst = _MAX (himl1->cy, himl2->cy);
1845 yOff1 = 0;
1846 yOff2 = 0;
1849 himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
1851 if (himlDst) {
1852 hdcSrcImage = CreateCompatibleDC (0);
1853 hdcDstImage = CreateCompatibleDC (0);
1854 nX1 = i1 * himl1->cx;
1855 nX2 = i2 * himl2->cx;
1857 /* copy image */
1858 SelectObject (hdcSrcImage, himl1->hbmImage);
1859 SelectObject (hdcDstImage, himlDst->hbmImage);
1860 BitBlt (hdcDstImage, 0, 0, cxDst, cyDst,
1861 hdcSrcImage, 0, 0, BLACKNESS);
1862 BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy,
1863 hdcSrcImage, nX1, 0, SRCCOPY);
1865 SelectObject (hdcSrcImage, himl2->hbmMask);
1866 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1867 hdcSrcImage, nX2, 0, SRCAND);
1869 SelectObject (hdcSrcImage, himl2->hbmImage);
1870 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1871 hdcSrcImage, nX2, 0, SRCPAINT);
1873 /* copy mask */
1874 SelectObject (hdcSrcImage, himl1->hbmMask);
1875 SelectObject (hdcDstImage, himlDst->hbmMask);
1876 BitBlt (hdcDstImage, 0, 0, cxDst, cyDst,
1877 hdcSrcImage, 0, 0, WHITENESS);
1878 BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy,
1879 hdcSrcImage, nX1, 0, SRCCOPY);
1881 SelectObject (hdcSrcImage, himl2->hbmMask);
1882 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1883 hdcSrcImage, nX2, 0, SRCAND);
1885 DeleteDC (hdcSrcImage);
1886 DeleteDC (hdcDstImage);
1889 return himlDst;
1893 /* helper for _read_bitmap currently unused */
1894 static int may_use_dibsection(HDC hdc) {
1895 int bitspixel = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES);
1896 if (bitspixel>8)
1897 return TRUE;
1898 if (bitspixel<=4)
1899 return FALSE;
1900 return GetDeviceCaps(hdc,94) & 0x10;
1903 /* helper for ImageList_Read, see comments below */
1904 static HBITMAP _read_bitmap(LPSTREAM pstm,int ilcFlag,int cx,int cy) {
1905 HDC xdc = 0;
1906 BITMAPFILEHEADER bmfh;
1907 BITMAPINFOHEADER bmih;
1908 int bitsperpixel,palspace,longsperline,width,height;
1909 LPBITMAPINFOHEADER bmihc = NULL;
1910 int result = 0;
1911 HBITMAP hbitmap = 0;
1912 LPBYTE bits = NULL,nbits = NULL;
1913 int nbytesperline,bytesperline;
1915 if (!SUCCEEDED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL)) ||
1916 (bmfh.bfType != (('M'<<8)|'B')) ||
1917 !SUCCEEDED(IStream_Read ( pstm, &bmih, sizeof(bmih), NULL)) ||
1918 (bmih.biSize != sizeof(bmih))
1920 return 0;
1922 bitsperpixel = bmih.biPlanes * bmih.biBitCount;
1923 if (bitsperpixel<=8)
1924 palspace = (1<<bitsperpixel)*sizeof(RGBQUAD);
1925 else
1926 palspace = 0;
1927 width = bmih.biWidth;
1928 height = bmih.biHeight;
1929 bmihc = (LPBITMAPINFOHEADER)LocalAlloc(LMEM_ZEROINIT,sizeof(bmih)+palspace);
1930 memcpy(bmihc,&bmih,sizeof(bmih));
1931 longsperline = ((width*bitsperpixel+31)&~0x1f)>>5;
1932 bmihc->biSizeImage = (longsperline*height)<<2;
1934 /* read the palette right after the end of the bitmapinfoheader */
1935 if (palspace)
1936 if (!SUCCEEDED(IStream_Read ( pstm, bmihc+1, palspace, NULL)))
1937 goto ret1;
1939 xdc = GetDC(0);
1940 #if 0 /* Magic for NxM -> 1x(N*M) not implemented for DIB Sections */
1941 if ((bitsperpixel>1) &&
1942 ((ilcFlag!=ILC_COLORDDB) && (!ilcFlag || may_use_dibsection(xdc)))
1944 hbitmap = CreateDIBSection(xdc,(BITMAPINFO*)bmihc,0,(LPVOID*)&bits,0,0);
1945 if (!hbitmap)
1946 goto ret1;
1947 if (!SUCCEEDED(IStream_Read( pstm, bits, bmihc->biSizeImage, NULL)))
1948 goto ret1;
1949 result = 1;
1950 } else
1951 #endif
1953 int i,nwidth,nheight;
1955 nwidth = width*(height/cy);
1956 nheight = cy;
1958 if (bitsperpixel==1)
1959 hbitmap = CreateBitmap(nwidth,nheight,1,1,NULL);
1960 else
1961 hbitmap = CreateCompatibleBitmap(xdc,nwidth,nheight);
1963 /* Might be a bit excessive memory use here */
1964 bits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage);
1965 nbits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage);
1966 if (!SUCCEEDED(IStream_Read ( pstm, bits, bmihc->biSizeImage, NULL)))
1967 goto ret1;
1969 /* Copy the NxM bitmap into a 1x(N*M) bitmap we need, linewise */
1970 /* Do not forget that windows bitmaps are bottom->top */
1971 bytesperline = longsperline*4;
1972 nbytesperline = (height/cy)*bytesperline;
1973 for (i=0;i<height;i++) {
1974 memcpy(
1975 nbits+((height-1-i)%cy)*nbytesperline+(i/cy)*bytesperline,
1976 bits+bytesperline*(height-1-i),
1977 bytesperline
1980 bmihc->biWidth = nwidth;
1981 bmihc->biHeight = nheight;
1982 if (!SetDIBits(xdc,hbitmap,0,nheight,nbits,(BITMAPINFO*)bmihc,0))
1983 goto ret1;
1984 LocalFree((HLOCAL)nbits);
1985 LocalFree((HLOCAL)bits);
1986 result = 1;
1988 ret1:
1989 if (xdc) ReleaseDC(0,xdc);
1990 if (bmihc) LocalFree((HLOCAL)bmihc);
1991 if (!result) {
1992 if (hbitmap) {
1993 DeleteObject(hbitmap);
1994 hbitmap = 0;
1997 return hbitmap;
2000 /*************************************************************************
2001 * ImageList_Read [COMCTL32.66]
2003 * Reads an image list from a stream.
2005 * PARAMS
2006 * pstm [I] pointer to a stream
2008 * RETURNS
2009 * Success: handle to image list
2010 * Failure: NULL
2012 * The format is like this:
2013 * ILHEAD ilheadstruct;
2015 * for the color image part:
2016 * BITMAPFILEHEADER bmfh;
2017 * BITMAPINFOHEADER bmih;
2018 * only if it has a palette:
2019 * RGBQUAD rgbs[nr_of_paletted_colors];
2021 * BYTE colorbits[imagesize];
2023 * the following only if the ILC_MASK bit is set in ILHEAD.ilFlags:
2024 * BITMAPFILEHEADER bmfh_mask;
2025 * BITMAPINFOHEADER bmih_mask;
2026 * only if it has a palette (it usually does not):
2027 * RGBQUAD rgbs[nr_of_paletted_colors];
2029 * BYTE maskbits[imagesize];
2031 * CAVEAT: Those images are within a NxM bitmap, not the 1xN we expect.
2032 * _read_bitmap needs to convert them.
2034 HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
2036 ILHEAD ilHead;
2037 HIMAGELIST himl;
2038 HBITMAP hbmColor=0,hbmMask=0;
2039 int i;
2041 if (!SUCCEEDED(IStream_Read (pstm, &ilHead, sizeof(ILHEAD), NULL)))
2042 return NULL;
2043 if (ilHead.usMagic != (('L' << 8) | 'I'))
2044 return NULL;
2045 if (ilHead.usVersion != 0x101) /* probably version? */
2046 return NULL;
2048 #if 0
2049 FIXME(" ilHead.cCurImage = %d\n",ilHead.cCurImage);
2050 FIXME(" ilHead.cMaxImage = %d\n",ilHead.cMaxImage);
2051 FIXME(" ilHead.cGrow = %d\n",ilHead.cGrow);
2052 FIXME(" ilHead.cx = %d\n",ilHead.cx);
2053 FIXME(" ilHead.cy = %d\n",ilHead.cy);
2054 FIXME(" ilHead.flags = %x\n",ilHead.flags);
2055 FIXME(" ilHead.ovls[0] = %d\n",ilHead.ovls[0]);
2056 FIXME(" ilHead.ovls[1] = %d\n",ilHead.ovls[1]);
2057 FIXME(" ilHead.ovls[2] = %d\n",ilHead.ovls[2]);
2058 FIXME(" ilHead.ovls[3] = %d\n",ilHead.ovls[3]);
2059 #endif
2061 hbmColor = _read_bitmap(pstm,ilHead.flags & ~ILC_MASK,ilHead.cx,ilHead.cy);
2062 if (!hbmColor)
2063 return NULL;
2064 if (ilHead.flags & ILC_MASK) {
2065 hbmMask = _read_bitmap(pstm,0,ilHead.cx,ilHead.cy);
2066 if (!hbmMask) {
2067 DeleteObject(hbmColor);
2068 return NULL;
2072 himl = ImageList_Create (
2073 ilHead.cx,
2074 ilHead.cy,
2075 ilHead.flags,
2076 1, /* initial */
2077 ilHead.cGrow
2079 if (!himl) {
2080 DeleteObject(hbmColor);
2081 DeleteObject(hbmMask);
2082 return NULL;
2084 himl->hbmImage = hbmColor;
2085 himl->hbmMask = hbmMask;
2086 himl->cCurImage = ilHead.cCurImage;
2087 himl->cMaxImage = ilHead.cMaxImage;
2089 ImageList_SetBkColor(himl,ilHead.bkcolor);
2090 for (i=0;i<4;i++)
2091 ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1);
2092 return himl;
2096 /*************************************************************************
2097 * ImageList_Remove [COMCTL32.67] Removes an image from an image list
2099 * PARAMS
2100 * himl [I] image list handle
2101 * i [I] image index
2103 * RETURNS
2104 * Success: TRUE
2105 * Failure: FALSE
2108 BOOL WINAPI
2109 ImageList_Remove (HIMAGELIST himl, INT i)
2111 HBITMAP hbmNewImage, hbmNewMask;
2112 HDC hdcSrc, hdcDst;
2113 INT cxNew, nCount;
2115 if ((i < -1) || (i >= himl->cCurImage)) {
2116 ERR("index out of range! %d\n", i);
2117 return FALSE;
2120 if (himl->cCurImage == 0) {
2121 ERR("image list is already empty!\n");
2122 return FALSE;
2125 if (i == -1) {
2126 /* remove all */
2127 TRACE("remove all!\n");
2129 himl->cMaxImage = himl->cInitial + himl->cGrow;
2130 himl->cCurImage = 0;
2131 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2132 himl->nOvlIdx[nCount] = -1;
2134 DeleteObject (himl->hbmImage);
2135 himl->hbmImage =
2136 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2137 1, himl->uBitsPixel, NULL);
2139 if (himl->hbmMask) {
2140 DeleteObject (himl->hbmMask);
2141 himl->hbmMask =
2142 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2143 1, 1, NULL);
2146 else {
2147 /* delete one image */
2148 TRACE("Remove single image! %d\n", i);
2150 /* create new bitmap(s) */
2151 cxNew = (himl->cCurImage + himl->cGrow - 1) * himl->cx;
2153 TRACE(" - Number of images: %d / %d (Old/New)\n",
2154 himl->cCurImage, himl->cCurImage - 1);
2155 TRACE(" - Max. number of images: %d / %d (Old/New)\n",
2156 himl->cMaxImage, himl->cCurImage + himl->cGrow - 1);
2158 hbmNewImage =
2159 CreateBitmap (cxNew, himl->cy, 1, himl->uBitsPixel, NULL);
2161 if (himl->hbmMask)
2162 hbmNewMask = CreateBitmap (cxNew, himl->cy, 1, 1, NULL);
2163 else
2164 hbmNewMask = 0; /* Just to keep compiler happy! */
2166 hdcSrc = CreateCompatibleDC (0);
2167 hdcDst = CreateCompatibleDC (0);
2169 /* copy all images and masks prior to the "removed" image */
2170 if (i > 0) {
2171 TRACE("Pre image copy: Copy %d images\n", i);
2173 SelectObject (hdcSrc, himl->hbmImage);
2174 SelectObject (hdcDst, hbmNewImage);
2175 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2176 hdcSrc, 0, 0, SRCCOPY);
2178 if (himl->hbmMask) {
2179 SelectObject (hdcSrc, himl->hbmMask);
2180 SelectObject (hdcDst, hbmNewMask);
2181 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2182 hdcSrc, 0, 0, SRCCOPY);
2186 /* copy all images and masks behind the removed image */
2187 if (i < himl->cCurImage - 1) {
2188 TRACE("Post image copy!\n");
2189 SelectObject (hdcSrc, himl->hbmImage);
2190 SelectObject (hdcDst, hbmNewImage);
2191 BitBlt (hdcDst, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx,
2192 himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2194 if (himl->hbmMask) {
2195 SelectObject (hdcSrc, himl->hbmMask);
2196 SelectObject (hdcDst, hbmNewMask);
2197 BitBlt (hdcDst, i * himl->cx, 0,
2198 (himl->cCurImage - i - 1) * himl->cx,
2199 himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2203 DeleteDC (hdcSrc);
2204 DeleteDC (hdcDst);
2206 /* delete old images and insert new ones */
2207 DeleteObject (himl->hbmImage);
2208 himl->hbmImage = hbmNewImage;
2209 if (himl->hbmMask) {
2210 DeleteObject (himl->hbmMask);
2211 himl->hbmMask = hbmNewMask;
2214 himl->cCurImage--;
2215 himl->cMaxImage = himl->cCurImage + himl->cGrow;
2218 return TRUE;
2222 /*************************************************************************
2223 * ImageList_Replace [COMCTL32.68]
2225 * Replaces an image in an image list with a new image.
2227 * PARAMS
2228 * himl [I] handle to image list
2229 * i [I] image index
2230 * hbmImage [I] handle to image bitmap
2231 * hbmMask [I] handle to mask bitmap. Can be NULL.
2233 * RETURNS
2234 * Success: TRUE
2235 * Failure: FALSE
2238 BOOL WINAPI
2239 ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage,
2240 HBITMAP hbmMask)
2242 HDC hdcImageList, hdcImage;
2243 BITMAP bmp;
2245 if (himl == NULL) {
2246 ERR("Invalid image list handle!\n");
2247 return FALSE;
2250 if ((i >= himl->cCurImage) || (i < 0)) {
2251 ERR("Invalid image index!\n");
2252 return FALSE;
2255 hdcImageList = CreateCompatibleDC (0);
2256 hdcImage = CreateCompatibleDC (0);
2257 GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
2259 /* Replace Image */
2260 SelectObject (hdcImageList, himl->hbmImage);
2261 SelectObject (hdcImage, hbmImage);
2263 StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2264 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2266 if (himl->hbmMask)
2268 /* Replace Mask */
2269 SelectObject (hdcImageList, himl->hbmMask);
2270 SelectObject (hdcImage, hbmMask);
2272 StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2273 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2276 DeleteDC (hdcImage);
2277 DeleteDC (hdcImageList);
2279 return TRUE;
2283 /*************************************************************************
2284 * ImageList_ReplaceIcon [COMCTL32.69]
2286 * Replaces an image in an image list using an icon.
2288 * PARAMS
2289 * himl [I] handle to image list
2290 * i [I] image index
2291 * hIcon [I] handle to icon
2293 * RETURNS
2294 * Success: index of the replaced image
2295 * Failure: -1
2298 INT WINAPI
2299 ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon)
2301 HDC hdcImageList, hdcImage;
2302 INT nIndex;
2303 HICON hBestFitIcon;
2304 HBITMAP hbmOldSrc, hbmOldDst;
2305 ICONINFO ii;
2306 BITMAP bmp;
2308 TRACE("(0x%lx 0x%x 0x%x)\n", (DWORD)himl, i, hIcon);
2310 if (himl == NULL)
2311 return -1;
2312 if ((i >= himl->cCurImage) || (i < -1))
2313 return -1;
2315 hBestFitIcon = CopyImage(
2316 hIcon, IMAGE_ICON,
2317 himl->cx, himl->cy,
2318 LR_COPYFROMRESOURCE);
2320 GetIconInfo (hBestFitIcon, &ii);
2321 if (ii.hbmMask == 0)
2322 ERR("no mask!\n");
2323 if (ii.hbmColor == 0)
2324 ERR("no color!\n");
2325 GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
2327 if (i == -1) {
2328 if (himl->cCurImage + 1 >= himl->cMaxImage)
2329 IMAGELIST_InternalExpandBitmaps (himl, 1);
2331 nIndex = himl->cCurImage;
2332 himl->cCurImage++;
2334 else
2335 nIndex = i;
2337 hdcImageList = CreateCompatibleDC (0);
2338 TRACE("hdcImageList=0x%x!\n", hdcImageList);
2339 if (hdcImageList == 0)
2340 ERR("invalid hdcImageList!\n");
2342 hdcImage = CreateCompatibleDC (0);
2343 TRACE("hdcImage=0x%x!\n", hdcImage);
2344 if (hdcImage == 0)
2345 ERR("invalid hdcImage!\n");
2347 hbmOldDst = SelectObject (hdcImageList, himl->hbmImage);
2348 SetTextColor( hdcImageList, RGB(0,0,0));
2349 SetBkColor( hdcImageList, RGB(255,255,255));
2350 hbmOldSrc = SelectObject (hdcImage, ii.hbmColor);
2351 StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2352 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2354 if (himl->hbmMask) {
2355 SelectObject (hdcImageList, himl->hbmMask);
2356 SelectObject (hdcImage, ii.hbmMask);
2357 StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2358 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2361 SelectObject (hdcImage, hbmOldSrc);
2362 SelectObject (hdcImageList, hbmOldDst);
2364 if(hBestFitIcon)
2365 DestroyIcon(hBestFitIcon);
2366 if (hdcImageList)
2367 DeleteDC (hdcImageList);
2368 if (hdcImage)
2369 DeleteDC (hdcImage);
2370 if (ii.hbmColor)
2371 DeleteObject (ii.hbmColor);
2372 if (ii.hbmMask)
2373 DeleteObject (ii.hbmMask);
2375 return nIndex;
2379 /*************************************************************************
2380 * ImageList_SetBkColor [COMCTL32.70]
2382 * Sets the background color of an image list.
2384 * PARAMS
2385 * himl [I] handle to image list
2386 * clrBk [I] background color
2388 * RETURNS
2389 * Success: previous background color
2390 * Failure: CLR_NONE
2393 COLORREF WINAPI
2394 ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
2396 COLORREF clrOldBk;
2398 if (himl == NULL)
2399 return CLR_NONE;
2401 clrOldBk = himl->clrBk;
2402 himl->clrBk = clrBk;
2403 return clrOldBk;
2407 /*************************************************************************
2408 * ImageList_SetDragCursorImage [COMCTL32.75]
2410 * Combines the specified image with the current drag image
2412 * PARAMS
2413 * himlDrag [I] handle to drag image list
2414 * iDrag [I] drag image index
2415 * dxHotspot [I] X position of the hot spot
2416 * dyHotspot [I] Y position of the hot spot
2418 * RETURNS
2419 * Success: TRUE
2420 * Failure: FALSE
2422 * BUGS
2423 * semi-stub.
2426 BOOL WINAPI
2427 ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag,
2428 INT dxHotspot, INT dyHotspot)
2430 HIMAGELIST himlTemp;
2432 FIXME("semi-stub!\n");
2434 if (himlInternalDrag == NULL)
2435 return FALSE;
2437 TRACE(" dxH=%d dyH=%d nX=%d nY=%d\n",
2438 dxHotspot, dyHotspot, nInternalDragHotspotX, nInternalDragHotspotY);
2440 himlTemp = ImageList_Merge (himlInternalDrag, 0, himlDrag, iDrag,
2441 dxHotspot, dyHotspot);
2443 ImageList_Destroy (himlInternalDrag);
2444 himlInternalDrag = himlTemp;
2446 nInternalDragHotspotX = dxHotspot;
2447 nInternalDragHotspotY = dyHotspot;
2449 return FALSE;
2453 /*************************************************************************
2454 * ImageList_SetFilter [COMCTL32.76]
2456 * Sets a filter (or does something completely different)!!???
2458 * PARAMS
2459 * himl [I] handle to image list
2460 * i [I] ???
2461 * dwFilter [I] ???
2463 * RETURNS
2464 * Success: TRUE ???
2465 * Failure: FALSE ???
2467 * BUGS
2468 * This is an UNDOCUMENTED function!!!!
2469 * empty stub.
2472 BOOL WINAPI
2473 ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter)
2475 FIXME("(%p 0x%x 0x%lx):empty stub!\n",
2476 himl, i, dwFilter);
2478 return FALSE;
2482 /*************************************************************************
2483 * ImageList_SetIconSize [COMCTL32.77]
2485 * Sets the image size of the bitmap and deletes all images.
2487 * PARAMS
2488 * himl [I] handle to image list
2489 * cx [I] image width
2490 * cy [I] image height
2492 * RETURNS
2493 * Success: TRUE
2494 * Failure: FALSE
2497 BOOL WINAPI
2498 ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy)
2500 INT nCount;
2502 if (!himl)
2503 return FALSE;
2505 /* remove all images*/
2506 himl->cMaxImage = himl->cInitial + himl->cGrow;
2507 himl->cCurImage = 0;
2508 himl->cx = cx;
2509 himl->cy = cy;
2511 /* initialize overlay mask indices */
2512 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2513 himl->nOvlIdx[nCount] = -1;
2515 DeleteObject (himl->hbmImage);
2516 himl->hbmImage =
2517 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2518 1, himl->uBitsPixel, NULL);
2520 if (himl->hbmMask) {
2521 DeleteObject (himl->hbmMask);
2522 himl->hbmMask =
2523 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2524 1, 1, NULL);
2527 return TRUE;
2531 /*************************************************************************
2532 * ImageList_SetImageCount [COMCTL32.78]
2534 * Resizes an image list to the specified number of images.
2536 * PARAMS
2537 * himl [I] handle to image list
2538 * iImageCount [I] number of images in the image list
2540 * RETURNS
2541 * Success: TRUE
2542 * Failure: FALSE
2545 BOOL WINAPI
2546 ImageList_SetImageCount (HIMAGELIST himl, INT iImageCount)
2548 HDC hdcImageList, hdcBitmap;
2549 HBITMAP hbmNewBitmap;
2550 INT nNewCount, nCopyCount;
2552 if (!himl)
2553 return FALSE;
2554 if (himl->cCurImage >= iImageCount)
2555 return FALSE;
2556 if (himl->cMaxImage > iImageCount)
2557 return TRUE;
2559 nNewCount = iImageCount + himl->cGrow;
2560 nCopyCount = _MIN(himl->cCurImage, iImageCount);
2562 hdcImageList = CreateCompatibleDC (0);
2563 hdcBitmap = CreateCompatibleDC (0);
2565 hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2566 1, himl->uBitsPixel, NULL);
2567 if (hbmNewBitmap != 0)
2569 SelectObject (hdcImageList, himl->hbmImage);
2570 SelectObject (hdcBitmap, hbmNewBitmap);
2572 /* copy images */
2573 BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2574 hdcImageList, 0, 0, SRCCOPY);
2575 #if 0
2576 /* delete 'empty' image space */
2577 SetBkColor (hdcBitmap, RGB(255, 255, 255));
2578 SetTextColor (hdcBitmap, RGB(0, 0, 0));
2579 PatBlt (hdcBitmap, nCopyCount * himl->cx, 0,
2580 (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2581 #endif
2582 DeleteObject (himl->hbmImage);
2583 himl->hbmImage = hbmNewBitmap;
2585 else
2586 ERR("Could not create new image bitmap !\n");
2588 if (himl->hbmMask)
2590 hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2591 1, 1, NULL);
2592 if (hbmNewBitmap != 0)
2594 SelectObject (hdcImageList, himl->hbmMask);
2595 SelectObject (hdcBitmap, hbmNewBitmap);
2597 /* copy images */
2598 BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2599 hdcImageList, 0, 0, SRCCOPY);
2600 #if 0
2601 /* delete 'empty' image space */
2602 SetBkColor (hdcBitmap, RGB(255, 255, 255));
2603 SetTextColor (hdcBitmap, RGB(0, 0, 0));
2604 PatBlt (hdcBitmap, nCopyCount * himl->cx, 0,
2605 (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2606 #endif
2607 DeleteObject (himl->hbmMask);
2608 himl->hbmMask = hbmNewBitmap;
2610 else
2611 ERR("Could not create new mask bitmap!\n");
2614 DeleteDC (hdcImageList);
2615 DeleteDC (hdcBitmap);
2617 /* Update max image count and current image count */
2618 himl->cMaxImage = nNewCount;
2619 if (himl->cCurImage > nCopyCount)
2620 himl->cCurImage = nCopyCount;
2622 return TRUE;
2626 /*************************************************************************
2627 * ImageList_SetOverlayImage [COMCTL32.79]
2629 * Assigns an overlay mask index to an existing image in an image list.
2631 * PARAMS
2632 * himl [I] handle to image list
2633 * iImage [I] image index
2634 * iOverlay [I] overlay mask index
2636 * RETURNS
2637 * Success: TRUE
2638 * Failure: FALSE
2641 BOOL WINAPI
2642 ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay)
2644 if (!himl)
2645 return FALSE;
2646 if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
2647 return FALSE;
2648 if ((iImage!=-1) && ((iImage < 0) || (iImage > himl->cCurImage)))
2649 return FALSE;
2650 himl->nOvlIdx[iOverlay - 1] = iImage;
2651 return TRUE;
2655 /*************************************************************************
2656 * ImageList_Write [COMCTL32.80]
2658 * Writes an image list to a stream.
2660 * PARAMS
2661 * himl [I] handle to image list
2662 * pstm [O] Pointer to a stream.
2664 * RETURNS
2665 * Success: TRUE
2666 * Failure: FALSE
2668 * NOTES
2669 * This function can not be implemented yet, because
2670 * IStream32::Write is not implemented.
2672 * BUGS
2673 * empty stub.
2676 BOOL WINAPI
2677 ImageList_Write (HIMAGELIST himl, LPSTREAM pstm)
2679 if (!himl)
2680 return FALSE;
2682 FIXME("empty stub!\n");
2684 return FALSE;