Allow the size of bitmaps to be changed after toolbar buttons have
[wine.git] / dlls / comctl32 / imagelist.c
blob368684a98254ea5bdefe80221d0d68e26c43de27
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, INT cx, INT cy)
81 HDC hdcImageList, hdcBitmap;
82 HBITMAP hbmNewBitmap;
83 INT nNewWidth, nNewCount;
85 if ((himl->cCurImage + nImageCount < himl->cMaxImage)
86 && (himl->cy >= cy))
87 return;
89 if (cy == 0) cy = himl->cy;
90 nNewCount = himl->cCurImage + nImageCount + himl->cGrow;
91 nNewWidth = nNewCount * himl->cx;
93 TRACE("Create expanded bitmaps : himl=%p x=%d y=%d count=%d\n", himl, nNewWidth, cy, nNewCount);
94 hdcImageList = CreateCompatibleDC (0);
95 hdcBitmap = CreateCompatibleDC (0);
97 hbmNewBitmap =
98 CreateBitmap (nNewWidth, cy, 1, himl->uBitsPixel, NULL);
99 if (hbmNewBitmap == 0)
100 ERR("creating new image bitmap (x=%d y=%d)!\n", nNewWidth, cy);
102 SelectObject (hdcImageList, himl->hbmImage);
103 SelectObject (hdcBitmap, hbmNewBitmap);
104 BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy,
105 hdcImageList, 0, 0, SRCCOPY);
107 DeleteObject (himl->hbmImage);
108 himl->hbmImage = hbmNewBitmap;
110 if (himl->hbmMask) {
111 hbmNewBitmap =
112 CreateBitmap (nNewWidth, cy, 1, 1, NULL);
114 if (hbmNewBitmap == 0)
115 ERR("creating new mask bitmap!\n");
117 SelectObject (hdcImageList, himl->hbmMask);
118 SelectObject (hdcBitmap, hbmNewBitmap);
119 BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy,
120 hdcImageList, 0, 0, SRCCOPY);
121 DeleteObject (himl->hbmMask);
122 himl->hbmMask = hbmNewBitmap;
125 himl->cMaxImage = nNewCount;
127 DeleteDC (hdcImageList);
128 DeleteDC (hdcBitmap);
132 /*************************************************************************
133 * IMAGELIST_InternalDraw [Internal]
135 * Draws the image in the ImageList (without the mask)
137 * PARAMS
138 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
139 * cx [I] the width of the image to display
140 * cy............[I] the height of the image to display
142 * RETURNS
143 * nothing
145 * NOTES
146 * This functions is used by ImageList_DrawIndirect, when it is
147 * required to draw only the Image (without the mask) to the screen.
149 * Blending and Overlays styles are accomplised by another function
151 static VOID
152 IMAGELIST_InternalDraw(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
154 HDC hImageDC;
155 HBITMAP hOldBitmap;
157 hImageDC = CreateCompatibleDC(0);
158 hOldBitmap = SelectObject(hImageDC, pimldp->himl->hbmImage);
159 BitBlt(pimldp->hdcDst,
160 pimldp->x, pimldp->y, cx, cy,
161 hImageDC,
162 pimldp->himl->cx * pimldp->i, 0,
163 SRCCOPY);
165 SelectObject(hImageDC, hOldBitmap);
166 DeleteDC(hImageDC);
170 /*************************************************************************
171 * IMAGELIST_InternalDrawMask [Internal]
173 * Draws the image in the ImageList witht the mask
175 * PARAMS
176 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
177 * cx [I] the width of the image to display
178 * cy............[I] the height of the image to display
180 * RETURNS
181 * nothing
183 * NOTES
184 * This functions is used by ImageList_DrawIndirect, when it is
185 * required to draw the Image with the mask to the screen.
187 * Blending and Overlays styles are accomplised by another function.
189 static VOID
190 IMAGELIST_InternalDrawMask(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
192 HDC hMaskDC, hImageDC;
193 BOOL bUseCustomBackground, bBlendFlag;
194 HBRUSH hBrush, hOldBrush;
195 HBITMAP hOldBitmapImage, hOldBitmapMask;
196 HIMAGELIST himlLocal = pimldp->himl;
197 COLORREF oldBkColor, oldFgColor;
198 UINT fStyle = pimldp->fStyle & (~ILD_OVERLAYMASK);
200 bUseCustomBackground = (himlLocal->clrBk != CLR_NONE);
201 bBlendFlag = (fStyle & ILD_BLEND50 ) || (fStyle & ILD_BLEND25);
203 hImageDC = CreateCompatibleDC(0);
204 hMaskDC = CreateCompatibleDC(0);
206 hOldBitmapImage = SelectObject(hImageDC, himlLocal->hbmImage);
207 hOldBitmapMask = SelectObject(hMaskDC, himlLocal->hbmMask);
208 /* Draw the Background for the appropriate Styles
210 if( bUseCustomBackground &&
211 (fStyle == ILD_NORMAL || fStyle & ILD_IMAGE || bBlendFlag))
213 hBrush = CreateSolidBrush (himlLocal->clrBk);
214 hOldBrush = SelectObject (pimldp->hdcDst, hBrush);
215 PatBlt (pimldp->hdcDst,
216 pimldp->x, pimldp->y, cx, cy,
217 PATCOPY);
219 DeleteObject (SelectObject (pimldp->hdcDst, hOldBrush));
222 /* Draw Image Transparently over the current background
224 if(fStyle == ILD_NORMAL
225 || (fStyle & ILD_TRANSPARENT)
226 || ((fStyle & ILD_IMAGE) && bUseCustomBackground)
227 || bBlendFlag)
229 /* to obtain a transparent look, background color should be set
230 to white and foreground color to black when blting the
231 monochrome mask. */
232 oldBkColor = SetBkColor(pimldp->hdcDst, RGB(0xff, 0xff, 0xff));
233 oldFgColor = SetTextColor(pimldp->hdcDst, RGB(0, 0, 0));
235 BitBlt(pimldp->hdcDst,
236 pimldp->x, pimldp->y, cx, cy,
237 hMaskDC,
238 himlLocal->cx * pimldp->i, 0,
239 SRCAND);
241 BitBlt(pimldp->hdcDst,
242 pimldp->x, pimldp->y, cx, cy,
243 hImageDC,
244 himlLocal->cx * pimldp->i, 0,
245 SRCPAINT);
247 SetBkColor(pimldp->hdcDst, oldBkColor);
248 SetTextColor(pimldp->hdcDst, oldFgColor);
250 /* Draw the image when no Background is specified
252 else if((fStyle & ILD_IMAGE) && !bUseCustomBackground)
254 BitBlt(pimldp->hdcDst,
255 pimldp->x, pimldp->y, cx, cy,
256 hImageDC,
257 himlLocal->cx * pimldp->i, 0,
258 SRCCOPY);
260 /* Draw the mask with or without a background
262 else if(fStyle & ILD_MASK)
264 BitBlt(pimldp->hdcDst,
265 pimldp->x, pimldp->y, cx, cy,
266 hMaskDC,
267 himlLocal->cx * pimldp->i, 0,
268 bUseCustomBackground ? SRCCOPY : SRCAND);
270 SelectObject(hImageDC, hOldBitmapImage);
271 SelectObject(hMaskDC, hOldBitmapMask);
272 DeleteDC(hImageDC);
273 DeleteDC(hMaskDC);
276 /*************************************************************************
277 * IMAGELIST_InternalDrawBlend [Internal]
279 * Draws the Blend over the current image
281 * PARAMS
282 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
283 * cx [I] the width of the image to display
284 * cy............[I] the height of the image to display
286 * RETURNS
287 * nothing
289 * NOTES
290 * This functions is used by ImageList_DrawIndirect, when it is
291 * required to add the blend to the current image.
294 static VOID
295 IMAGELIST_InternalDrawBlend(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
298 HDC hBlendMaskDC,hMaskDC;
299 HBRUSH hBlendColorBrush, hBlendBrush, hOldBrush;
300 HBITMAP hBlendMaskBitmap, hOldBitmap;
301 COLORREF clrBlend, OldTextColor, OldBkColor;
302 HIMAGELIST himlLocal = pimldp->himl;
304 clrBlend = GetSysColor (COLOR_HIGHLIGHT);
305 if (!(pimldp->rgbFg == CLR_DEFAULT))
307 clrBlend = pimldp->rgbFg;
309 /* Create the blend Mask
311 hBlendMaskDC = CreateCompatibleDC(0);
312 hBlendBrush = pimldp->fStyle & ILD_BLEND50 ?
313 himlLocal->hbrBlend50 : himlLocal->hbrBlend25;
315 hBlendMaskBitmap = CreateBitmap(cx, cy, 1, 1, NULL);
316 hOldBitmap = SelectObject(hBlendMaskDC, hBlendMaskBitmap);
318 hOldBrush = (HBRUSH) SelectObject(hBlendMaskDC, hBlendBrush);
319 PatBlt(hBlendMaskDC, 0, 0, cx, cy, PATCOPY);
320 SelectObject(hBlendMaskDC, hOldBrush);
322 /* Modify the blend mask if an Image Mask exist
324 if(pimldp->himl->hbmMask != 0)
326 HBITMAP hOldMaskBitmap;
327 hMaskDC = CreateCompatibleDC(0);
328 hOldMaskBitmap = (HBITMAP) SelectObject(hMaskDC, himlLocal->hbmMask);
330 BitBlt(hBlendMaskDC,
331 0,0, cx, cy,
332 hMaskDC,
333 himlLocal->cx * pimldp->i,0,
334 0x220326); /* NOTSRCAND */
336 BitBlt(hBlendMaskDC,
337 0,0, cx, cy,
338 hBlendMaskDC,
339 0,0,
340 NOTSRCCOPY);
342 SelectObject(hMaskDC, hOldMaskBitmap);
343 DeleteDC(hMaskDC);
346 /* Apply blend to the current image given the BlendMask
348 OldTextColor = SetTextColor(pimldp->hdcDst, 0);
349 OldBkColor = SetBkColor(pimldp->hdcDst, RGB(255,255,255));
350 hBlendColorBrush = CreateSolidBrush(clrBlend);
351 hOldBrush = (HBRUSH) SelectObject (pimldp->hdcDst, hBlendColorBrush);
353 BitBlt (pimldp->hdcDst,
354 pimldp->x, pimldp->y, cx, cy,
355 hBlendMaskDC,
356 0, 0,
357 0xB8074A); /* PSDPxax */
359 SelectObject(pimldp->hdcDst, hOldBrush);
360 SetTextColor(pimldp->hdcDst, OldTextColor);
361 SetBkColor(pimldp->hdcDst, OldBkColor);
362 SelectObject(hBlendMaskDC, hOldBitmap);
363 DeleteDC(hBlendMaskDC);
364 DeleteObject(hBlendMaskBitmap);
365 DeleteObject(hBlendColorBrush);
368 /*************************************************************************
369 * IMAGELIST_InternalDrawOverlay [Internal]
371 * Draws the overlay image
373 * PARAMS
374 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
375 * cx [I] the width of the image to display
376 * cy............[I] the height of the image to display
378 * RETURNS
379 * nothing
381 * NOTES
382 * This functions is used by ImageList_DrawIndirect, when it is
383 * required to draw the overlay
387 static VOID
388 IMAGELIST_InternalDrawOverlay(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
390 INT nOvlIdx;
391 HDC hImageDC;
392 HBITMAP hOldBitmap;
394 nOvlIdx = (pimldp->fStyle & ILD_OVERLAYMASK) >> 8;
395 if ((nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE))
397 nOvlIdx = pimldp->himl->nOvlIdx[nOvlIdx - 1];
398 if ((nOvlIdx >= 0) && (nOvlIdx <= pimldp->himl->cCurImage))
400 hImageDC = CreateCompatibleDC(0);
401 if (pimldp->himl->hbmMask)
403 hOldBitmap = (HBITMAP) SelectObject (hImageDC,
404 pimldp->himl->hbmMask);
406 BitBlt (pimldp->hdcDst,
407 pimldp->x, pimldp->y, cx, cy,
408 hImageDC, pimldp->himl->cx * nOvlIdx, 0,
409 SRCAND);
411 SelectObject(hImageDC, hOldBitmap);
413 hOldBitmap = (HBITMAP) SelectObject (hImageDC,
414 pimldp->himl->hbmImage);
416 BitBlt (pimldp->hdcDst,
417 pimldp->x, pimldp->y, cx, cy,
418 hImageDC,
419 pimldp->himl->cx * nOvlIdx, 0,
420 SRCPAINT);
422 SelectObject(hImageDC, hOldBitmap);
423 DeleteDC(hImageDC);
432 /*************************************************************************
433 * ImageList_Add [COMCTL32.39]
435 * Add an image or images to an image list.
437 * PARAMS
438 * himl [I] handle to image list
439 * hbmImage [I] handle to image bitmap
440 * hbmMask [I] handle to mask bitmap
442 * RETURNS
443 * Success: Index of the first new image.
444 * Failure: -1
447 INT WINAPI
448 ImageList_Add (HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
450 HDC hdcImage, hdcBitmap;
451 INT nFirstIndex, nImageCount;
452 INT nStartX;
453 BITMAP bmp;
454 HBITMAP hOldBitmapImage, hOldBitmap;
456 TRACE("himl=%p hbmimage=%x hbmmask=%x\n", himl, hbmImage, hbmMask);
457 if (!himl || !hbmImage)
458 return -1;
460 GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
461 nImageCount = bmp.bmWidth / himl->cx;
463 IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight);
465 nStartX = himl->cCurImage * himl->cx;
467 hdcImage = CreateCompatibleDC(0);
468 hdcBitmap = CreateCompatibleDC(0);
470 hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
471 hOldBitmap = SelectObject(hdcBitmap, hbmImage);
473 /* Copy result to the imagelist
475 BitBlt (hdcImage, nStartX, 0, bmp.bmWidth, bmp.bmHeight,
476 hdcBitmap, 0, 0, SRCCOPY);
478 if(himl->hbmMask)
480 HDC hdcMask, hdcTemp, hOldBitmapMask, hOldBitmapTemp;
482 hdcMask = CreateCompatibleDC (0);
483 hdcTemp = CreateCompatibleDC(0);
484 hOldBitmapMask = (HBITMAP) SelectObject(hdcMask, himl->hbmMask);
485 hOldBitmapTemp = (HBITMAP) SelectObject(hdcTemp, hbmMask);
487 BitBlt (hdcMask,
488 nStartX, 0, bmp.bmWidth, bmp.bmHeight,
489 hdcTemp,
490 0, 0,
491 SRCCOPY);
493 SelectObject(hdcTemp, hOldBitmapTemp);
494 DeleteDC(hdcTemp);
496 /* Remove the background from the image
498 BitBlt (hdcImage,
499 nStartX, 0, bmp.bmWidth, bmp.bmHeight,
500 hdcMask,
501 nStartX, 0,
502 0x220326); /* NOTSRCAND */
504 SelectObject(hdcMask, hOldBitmapMask);
505 DeleteDC(hdcMask);
508 SelectObject(hdcImage, hOldBitmapImage);
509 SelectObject(hdcBitmap, hOldBitmap);
510 DeleteDC(hdcImage);
511 DeleteDC(hdcBitmap);
513 nFirstIndex = himl->cCurImage;
514 himl->cCurImage += nImageCount;
516 return nFirstIndex;
520 /*************************************************************************
521 * ImageList_AddIcon [COMCTL32.40]
523 * Adds an icon to an image list.
525 * PARAMS
526 * himl [I] handle to image list
527 * hIcon [I] handle to icon
529 * RETURNS
530 * Success: index of the new image
531 * Failure: -1
534 INT WINAPI
535 ImageList_AddIcon (HIMAGELIST himl, HICON hIcon)
537 return ImageList_ReplaceIcon (himl, -1, hIcon);
541 /*************************************************************************
542 * ImageList_AddMasked [COMCTL32.41]
544 * Adds an image or images to an image list and creates a mask from the
545 * specified bitmap using the mask color.
547 * PARAMS
548 * himl [I] handle to image list.
549 * hBitmap [I] handle to bitmap
550 * clrMask [I] mask color.
552 * RETURNS
553 * Success: Index of the first new image.
554 * Failure: -1
557 INT WINAPI
558 ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
560 HDC hdcImage, hdcMask, hdcBitmap;
561 INT nIndex, nImageCount, nMaskXOffset=0;
562 BITMAP bmp;
563 HBITMAP hOldBitmap, hOldBitmapMask, hOldBitmapImage;
564 HBITMAP hMaskBitmap=0;
565 COLORREF bkColor;
567 TRACE("himl=%p hbitmap=%x clrmask=%lx\n", himl, hBitmap, clrMask);
568 if (himl == NULL)
569 return -1;
571 if (!GetObjectA (hBitmap, sizeof(BITMAP), &bmp))
572 return -1;
574 nImageCount = bmp.bmWidth / himl->cx;
576 IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight);
578 nIndex = himl->cCurImage;
579 himl->cCurImage += nImageCount;
581 hdcMask = CreateCompatibleDC (0);
582 hdcImage = CreateCompatibleDC(0);
583 hdcBitmap = CreateCompatibleDC(0);
586 hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
587 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
588 if(himl->hbmMask)
590 hOldBitmapMask = SelectObject(hdcMask, himl->hbmMask);
591 nMaskXOffset = nIndex * himl->cx;
593 else
596 Create a temp Mask so we can remove the background of
597 the Image (Windows does this even if there is no mask)
599 hMaskBitmap = CreateBitmap(bmp.bmWidth, bmp.bmHeight, 1, 1, NULL);
600 hOldBitmapMask = SelectObject(hdcMask, hMaskBitmap);
601 nMaskXOffset = 0;
603 /* create monochrome image to the mask bitmap */
604 bkColor = (clrMask != CLR_DEFAULT) ? clrMask :
605 GetPixel (hdcBitmap, 0, 0);
606 SetBkColor (hdcBitmap, bkColor);
607 BitBlt (hdcMask,
608 nMaskXOffset, 0, bmp.bmWidth, bmp.bmHeight,
609 hdcBitmap, 0, 0,
610 SRCCOPY);
612 SetBkColor(hdcBitmap, RGB(255,255,255));
613 /*Remove the background from the image
616 WINDOWS BUG ALERT!!!!!!
617 The statement below should not be done in common practice
618 but this is how ImageList_AddMasked works in Windows.
619 It overwrites the original bitmap passed, this was discovered
620 by using the same bitmap to itterated the different styles
621 on windows where it failed (BUT ImageList_Add is OK)
622 This is here in case some apps really on this bug
624 BitBlt(hdcBitmap,
625 0, 0, bmp.bmWidth, bmp.bmHeight,
626 hdcMask,
627 nMaskXOffset, 0,
628 0x220326); /* NOTSRCAND */
629 /* Copy result to the imagelist
631 BitBlt (hdcImage,
632 nIndex * himl->cx, 0, bmp.bmWidth, bmp.bmHeight,
633 hdcBitmap,
634 0, 0,
635 SRCCOPY);
636 /* Clean up
638 SelectObject(hdcMask,hOldBitmapMask);
639 SelectObject(hdcImage, hOldBitmapImage);
640 SelectObject(hdcBitmap, hOldBitmap);
641 DeleteDC(hdcMask);
642 DeleteDC(hdcImage);
643 DeleteDC(hdcBitmap);
644 if(!himl->hbmMask)
646 DeleteObject(hMaskBitmap);
649 return nIndex;
653 /*************************************************************************
654 * ImageList_BeginDrag [COMCTL32.42]
656 * Creates a temporary image list that contains one image. It will be used
657 * as a drag image.
659 * PARAMS
660 * himlTrack [I] handle to the source image list
661 * iTrack [I] index of the drag image in the source image list
662 * dxHotspot [I] X position of the hot spot of the drag image
663 * dyHotspot [I] Y position of the hot spot of the drag image
665 * RETURNS
666 * Success: TRUE
667 * Failure: FALSE
670 BOOL WINAPI
671 ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
672 INT dxHotspot, INT dyHotspot)
674 HDC hdcSrc, hdcDst;
676 FIXME("partially implemented!\n");
678 if (himlTrack == NULL)
679 return FALSE;
681 if (himlInternalDrag)
682 ImageList_EndDrag ();
684 himlInternalDrag =
685 ImageList_Create (himlTrack->cx, himlTrack->cy,
686 himlTrack->flags, 1, 1);
687 if (himlInternalDrag == NULL) {
688 ERR("Error creating drag image list!\n");
689 return FALSE;
692 nInternalDragHotspotX = dxHotspot;
693 nInternalDragHotspotY = dyHotspot;
695 hdcSrc = CreateCompatibleDC (0);
696 hdcDst = CreateCompatibleDC (0);
698 /* copy image */
699 SelectObject (hdcSrc, himlTrack->hbmImage);
700 SelectObject (hdcDst, himlInternalDrag->hbmImage);
701 StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
702 iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
704 /* copy mask */
705 SelectObject (hdcSrc, himlTrack->hbmMask);
706 SelectObject (hdcDst, himlInternalDrag->hbmMask);
707 StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
708 iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
710 DeleteDC (hdcSrc);
711 DeleteDC (hdcDst);
713 himlInternalDrag->cCurImage = 1;
715 return TRUE;
719 /*************************************************************************
720 * ImageList_Copy [COMCTL32.43]
722 * Copies an image of the source image list to an image of the
723 * destination image list. Images can be copied or swapped.
725 * PARAMS
726 * himlDst [I] handle to the destination image list
727 * iDst [I] destination image index.
728 * himlSrc [I] handle to the source image list
729 * iSrc [I] source image index
730 * uFlags [I] flags for the copy operation
732 * RETURNS
733 * Success: TRUE
734 * Failure: FALSE
736 * NOTES
737 * Copying from one image list to another is possible. The original
738 * implementation just copies or swapps within one image list.
739 * Could this feature become a bug??? ;-)
742 BOOL WINAPI
743 ImageList_Copy (HIMAGELIST himlDst, INT iDst, HIMAGELIST himlSrc,
744 INT iSrc, INT uFlags)
746 HDC hdcSrc, hdcDst;
748 TRACE("iDst=%d iSrc=%d\n", iDst, iSrc);
750 if ((himlSrc == NULL) || (himlDst == NULL))
751 return FALSE;
752 if ((iDst < 0) || (iDst >= himlDst->cCurImage))
753 return FALSE;
754 if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage))
755 return FALSE;
757 hdcSrc = CreateCompatibleDC (0);
758 if (himlDst == himlSrc)
759 hdcDst = hdcSrc;
760 else
761 hdcDst = CreateCompatibleDC (0);
763 if (uFlags & ILCF_SWAP) {
764 /* swap */
765 HBITMAP hbmTempImage, hbmTempMask;
767 /* create temporary bitmaps */
768 hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
769 himlSrc->uBitsPixel, NULL);
770 hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
771 1, NULL);
773 /* copy (and stretch) destination to temporary bitmaps.(save) */
774 /* image */
775 SelectObject (hdcSrc, himlDst->hbmImage);
776 SelectObject (hdcDst, hbmTempImage);
777 StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
778 hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
779 SRCCOPY);
780 /* mask */
781 SelectObject (hdcSrc, himlDst->hbmMask);
782 SelectObject (hdcDst, hbmTempMask);
783 StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
784 hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
785 SRCCOPY);
787 /* copy (and stretch) source to destination */
788 /* image */
789 SelectObject (hdcSrc, himlSrc->hbmImage);
790 SelectObject (hdcDst, himlDst->hbmImage);
791 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
792 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
793 SRCCOPY);
794 /* mask */
795 SelectObject (hdcSrc, himlSrc->hbmMask);
796 SelectObject (hdcDst, himlDst->hbmMask);
797 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
798 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
799 SRCCOPY);
801 /* copy (without stretching) temporary bitmaps to source (restore) */
802 /* image */
803 SelectObject (hdcSrc, hbmTempImage);
804 SelectObject (hdcDst, himlSrc->hbmImage);
805 BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
806 hdcSrc, 0, 0, SRCCOPY);
807 /* mask */
808 SelectObject (hdcSrc, hbmTempMask);
809 SelectObject (hdcDst, himlSrc->hbmMask);
810 BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
811 hdcSrc, 0, 0, SRCCOPY);
813 /* delete temporary bitmaps */
814 DeleteObject (hbmTempMask);
815 DeleteObject (hbmTempImage);
817 else {
818 /* copy image */
819 SelectObject (hdcSrc, himlSrc->hbmImage);
820 if (himlSrc == himlDst)
821 hdcDst = hdcSrc;
822 else
823 SelectObject (hdcDst, himlDst->hbmImage);
824 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
825 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
826 SRCCOPY);
828 /* copy mask */
829 SelectObject (hdcSrc, himlSrc->hbmMask);
830 if (himlSrc == himlDst)
831 hdcDst = hdcSrc;
832 else
833 SelectObject (hdcDst, himlDst->hbmMask);
834 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
835 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
836 SRCCOPY);
839 DeleteDC (hdcSrc);
840 if (himlSrc != himlDst)
841 DeleteDC (hdcDst);
843 return TRUE;
847 /*************************************************************************
848 * ImageList_Create [COMCTL32.44] Creates a new image list.
850 * PARAMS
851 * cx [I] image height
852 * cy [I] image width
853 * flags [I] creation flags
854 * cInitial [I] initial number of images in the image list
855 * cGrow [I] number of images by which image list grows
857 * RETURNS
858 * Success: Handle to the created image list
859 * Failure: NULL
862 HIMAGELIST WINAPI
863 ImageList_Create (INT cx, INT cy, UINT flags,
864 INT cInitial, INT cGrow)
866 HIMAGELIST himl;
867 HDC hdc;
868 INT nCount;
869 HBITMAP hbmTemp;
870 static WORD aBitBlend25[] =
871 {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00};
873 static WORD aBitBlend50[] =
874 {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
876 TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow);
878 himl = (HIMAGELIST)COMCTL32_Alloc (sizeof(struct _IMAGELIST));
879 if (!himl)
880 return NULL;
882 himl->cx = cx;
883 himl->cy = cy;
884 himl->flags = flags;
885 himl->cMaxImage = cInitial + cGrow;
886 himl->cInitial = cInitial;
887 himl->cGrow = cGrow;
888 himl->cCurImage = 0;
889 himl->clrFg = CLR_DEFAULT;
890 himl->clrBk = CLR_NONE;
892 /* initialize overlay mask indices */
893 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
894 himl->nOvlIdx[nCount] = -1;
896 hdc = CreateCompatibleDC (0);
897 himl->uBitsPixel = (UINT)GetDeviceCaps (hdc, BITSPIXEL);
898 DeleteDC (hdc);
900 TRACE("Image: %d Bits per Pixel\n", himl->uBitsPixel);
902 if (himl->cMaxImage > 0) {
903 himl->hbmImage =
904 CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
905 1, himl->uBitsPixel, NULL);
906 if (himl->hbmImage == 0) {
907 ERR("Error creating image bitmap!\n");
908 return NULL;
911 else
912 himl->hbmImage = 0;
914 if ( (himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) {
915 himl->hbmMask = CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
916 1, 1, NULL);
917 if (himl->hbmMask == 0) {
918 ERR("Error creating mask bitmap!\n");
919 if (himl->hbmImage)
920 DeleteObject (himl->hbmImage);
921 return NULL;
924 else
925 himl->hbmMask = 0;
927 /* create blending brushes */
928 hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend25);
929 himl->hbrBlend25 = CreatePatternBrush (hbmTemp);
930 DeleteObject (hbmTemp);
932 hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend50);
933 himl->hbrBlend50 = CreatePatternBrush (hbmTemp);
934 DeleteObject (hbmTemp);
936 TRACE("created imagelist %p\n", himl);
937 return himl;
941 /*************************************************************************
942 * ImageList_Destroy [COMCTL32.45]
944 * Destroys an image list.
946 * PARAMS
947 * himl [I] handle to image list
949 * RETURNS
950 * Success: TRUE
951 * Failure: FALSE
954 BOOL WINAPI
955 ImageList_Destroy (HIMAGELIST himl)
957 if (!himl)
958 return FALSE;
960 /* delete image bitmaps */
961 if (himl->hbmImage)
962 DeleteObject (himl->hbmImage);
963 if (himl->hbmMask)
964 DeleteObject (himl->hbmMask);
966 /* delete blending brushes */
967 if (himl->hbrBlend25)
968 DeleteObject (himl->hbrBlend25);
969 if (himl->hbrBlend50)
970 DeleteObject (himl->hbrBlend50);
972 COMCTL32_Free (himl);
974 return TRUE;
978 /*************************************************************************
979 * ImageList_DragEnter [COMCTL32.46]
981 * Locks window update and displays the drag image at the given position.
983 * PARAMS
984 * hwndLock [I] handle of the window that owns the drag image.
985 * x [I] X position of the drag image.
986 * y [I] Y position of the drag image.
988 * RETURNS
989 * Success: TRUE
990 * Failure: FALSE
992 * NOTES
993 * The position of the drag image is relative to the window, not
994 * the client area.
997 BOOL WINAPI
998 ImageList_DragEnter (HWND hwndLock, INT x, INT y)
1000 if (himlInternalDrag == NULL)
1001 return FALSE;
1003 if (hwndLock)
1004 hwndInternalDrag = hwndLock;
1005 else
1006 hwndInternalDrag = GetDesktopWindow ();
1008 xInternalPos = x;
1009 yInternalPos = y;
1011 hdcBackBuffer = CreateCompatibleDC (0);
1012 hbmBackBuffer = CreateCompatibleBitmap (hdcBackBuffer,
1013 himlInternalDrag->cx, himlInternalDrag->cy);
1015 ImageList_DragShowNolock (TRUE);
1017 return FALSE;
1021 /*************************************************************************
1022 * ImageList_DragLeave [COMCTL32.47]
1024 * Unlocks window update and hides the drag image.
1026 * PARAMS
1027 * hwndLock [I] handle of the window that owns the drag image.
1029 * RETURNS
1030 * Success: TRUE
1031 * Failure: FALSE
1034 BOOL WINAPI
1035 ImageList_DragLeave (HWND hwndLock)
1037 if (hwndLock)
1038 hwndInternalDrag = hwndLock;
1039 else
1040 hwndInternalDrag = GetDesktopWindow ();
1042 ImageList_DragShowNolock (FALSE);
1044 DeleteDC (hdcBackBuffer);
1045 DeleteObject (hbmBackBuffer);
1047 return TRUE;
1051 /*************************************************************************
1052 * ImageList_DragMove [COMCTL32.48]
1054 * Moves the drag image.
1056 * PARAMS
1057 * x [I] X position of the drag image.
1058 * y [I] Y position of the drag image.
1060 * RETURNS
1061 * Success: TRUE
1062 * Failure: FALSE
1064 * NOTES
1065 * The position of the drag image is relative to the window, not
1066 * the client area.
1069 BOOL WINAPI
1070 ImageList_DragMove (INT x, INT y)
1072 ImageList_DragShowNolock (FALSE);
1074 xInternalPos = x;
1075 yInternalPos = y;
1077 ImageList_DragShowNolock (TRUE);
1079 return FALSE;
1083 /*************************************************************************
1084 * ImageList_DragShowNolock [COMCTL32.49]
1086 * Shows or hides the drag image.
1088 * PARAMS
1089 * bShow [I] TRUE shows the drag image, FALSE hides it.
1091 * RETURNS
1092 * Success: TRUE
1093 * Failure: FALSE
1095 * FIXME
1096 * semi-stub.
1099 BOOL WINAPI
1100 ImageList_DragShowNolock (BOOL bShow)
1102 HDC hdcDrag;
1104 FIXME("semi-stub!\n");
1105 TRACE("bShow=0x%X!\n", bShow);
1107 hdcDrag = GetDCEx (hwndInternalDrag, 0,
1108 DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
1110 if (bShow) {
1111 /* show drag image */
1113 /* save background */
1115 /* draw drag image */
1118 else {
1119 /* hide drag image */
1121 /* restore background */
1125 ReleaseDC (hwndInternalDrag, hdcDrag);
1127 return FALSE;
1131 /*************************************************************************
1132 * ImageList_Draw [COMCTL32.50] Draws an image.
1134 * PARAMS
1135 * himl [I] handle to image list
1136 * i [I] image index
1137 * hdc [I] handle to device context
1138 * x [I] x position
1139 * y [I] y position
1140 * fStyle [I] drawing flags
1142 * RETURNS
1143 * Success: TRUE
1144 * Failure: FALSE
1146 * NOTES
1147 * Calls ImageList_DrawIndirect.
1149 * SEE
1150 * ImageList_DrawIndirect.
1153 BOOL WINAPI
1154 ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc,
1155 INT x, INT y, UINT fStyle)
1157 IMAGELISTDRAWPARAMS imldp;
1159 imldp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
1160 imldp.himl = himl;
1161 imldp.i = i;
1162 imldp.hdcDst = hdc,
1163 imldp.x = x;
1164 imldp.y = y;
1165 imldp.cx = 0;
1166 imldp.cy = 0;
1167 imldp.xBitmap = 0;
1168 imldp.yBitmap = 0;
1169 imldp.rgbBk = CLR_DEFAULT;
1170 imldp.rgbFg = CLR_DEFAULT;
1171 imldp.fStyle = fStyle;
1172 imldp.dwRop = 0;
1174 return ImageList_DrawIndirect (&imldp);
1178 /*************************************************************************
1179 * ImageList_DrawEx [COMCTL32.51]
1181 * Draws an image and allows to use extended drawing features.
1183 * PARAMS
1184 * himl [I] handle to image list
1185 * i [I] image index
1186 * hdc [I] handle to device context
1187 * x [I] X position
1188 * y [I] Y position
1189 * xOffs [I] X offset
1190 * yOffs [I] Y offset
1191 * rgbBk [I] background color
1192 * rgbFg [I] foreground color
1193 * fStyle [I] drawing flags
1195 * RETURNS
1196 * Success: TRUE
1197 * Failure: FALSE
1199 * NOTES
1200 * Calls ImageList_DrawIndirect.
1202 * SEE
1203 * ImageList_DrawIndirect.
1206 BOOL WINAPI
1207 ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y,
1208 INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg,
1209 UINT fStyle)
1211 IMAGELISTDRAWPARAMS imldp;
1213 imldp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
1214 imldp.himl = himl;
1215 imldp.i = i;
1216 imldp.hdcDst = hdc,
1217 imldp.x = x;
1218 imldp.y = y;
1219 imldp.cx = dx;
1220 imldp.cy = dy;
1221 imldp.xBitmap = 0;
1222 imldp.yBitmap = 0;
1223 imldp.rgbBk = rgbBk;
1224 imldp.rgbFg = rgbFg;
1225 imldp.fStyle = fStyle;
1226 imldp.dwRop = 0;
1228 return ImageList_DrawIndirect (&imldp);
1232 /*************************************************************************
1233 * ImageList_DrawIndirect [COMCTL32.52]
1235 * Draws an image using ...
1237 * PARAMS
1238 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
1240 * RETURNS
1241 * Success: TRUE
1242 * Failure: FALSE
1245 BOOL WINAPI
1246 ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
1248 INT cx, cy;
1250 Do some Error Checking
1252 if (pimldp == NULL)
1253 return FALSE;
1254 if (pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS))
1255 return FALSE;
1256 if (pimldp->himl == NULL)
1257 return FALSE;
1258 if ((pimldp->i < 0) || (pimldp->i > pimldp->himl->cCurImage)) {
1259 ERR("%d not within range (max %d)\n",pimldp->i,pimldp->himl->cCurImage);
1260 return FALSE;
1263 Get the Height and Width to display
1265 cx = (pimldp->cx == 0) ? pimldp->himl->cx : pimldp->cx;
1266 cy = (pimldp->cy == 0) ? pimldp->himl->cy : pimldp->cy;
1268 Draw the image
1270 if(pimldp->himl->hbmMask != 0)
1272 IMAGELIST_InternalDrawMask(pimldp, cx, cy);
1274 else
1276 IMAGELIST_InternalDraw(pimldp, cx, cy);
1279 Apply the blend if needed to the Image
1281 if((pimldp->fStyle & ILD_BLEND50)
1282 || (pimldp->fStyle & ILD_BLEND25))
1284 IMAGELIST_InternalDrawBlend(pimldp, cx, cy);
1287 Apply the Overlay if needed
1289 if (pimldp->fStyle & ILD_OVERLAYMASK)
1291 IMAGELIST_InternalDrawOverlay(pimldp, cx, cy);
1294 return TRUE;
1298 /*************************************************************************
1299 * ImageList_Duplicate [COMCTL32.53] Duplicates an image list.
1301 * PARAMS
1302 * himlSrc [I] source image list handle
1304 * RETURNS
1305 * Success: Handle of duplicated image list.
1306 * Failure: NULL
1309 HIMAGELIST WINAPI
1310 ImageList_Duplicate (HIMAGELIST himlSrc)
1312 HIMAGELIST himlDst;
1313 HDC hdcSrc, hdcDst;
1315 if (himlSrc == NULL) {
1316 ERR("Invalid image list handle!\n");
1317 return NULL;
1320 himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
1321 himlSrc->cInitial, himlSrc->cGrow);
1323 if (himlDst)
1325 hdcSrc = CreateCompatibleDC (0);
1326 hdcDst = CreateCompatibleDC (0);
1327 SelectObject (hdcSrc, himlSrc->hbmImage);
1328 SelectObject (hdcDst, himlDst->hbmImage);
1329 BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy,
1330 hdcSrc, 0, 0, SRCCOPY);
1332 if (himlDst->hbmMask)
1334 SelectObject (hdcSrc, himlSrc->hbmMask);
1335 SelectObject (hdcDst, himlDst->hbmMask);
1336 BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx,
1337 himlSrc->cy, hdcSrc, 0, 0, SRCCOPY);
1340 DeleteDC (hdcDst);
1341 DeleteDC (hdcSrc);
1343 himlDst->cCurImage = himlSrc->cCurImage;
1344 himlDst->cMaxImage = himlSrc->cMaxImage;
1346 return himlDst;
1350 /*************************************************************************
1351 * ImageList_EndDrag [COMCTL32.54] Finishes a drag operation.
1353 * Finishes a drag operation.
1355 * PARAMS
1356 * no Parameters
1358 * RETURNS
1359 * Success: TRUE
1360 * Failure: FALSE
1362 * BUGS
1363 * semi-stub.
1366 BOOL WINAPI
1367 ImageList_EndDrag (void)
1369 FIXME("semi-stub!\n");
1371 if (himlInternalDrag)
1374 ImageList_Destroy (himlInternalDrag);
1375 himlInternalDrag = NULL;
1377 nInternalDragHotspotX = 0;
1378 nInternalDragHotspotY = 0;
1382 return TRUE;
1386 /*************************************************************************
1387 * ImageList_GetBkColor [COMCTL32.55]
1389 * Returns the background color of an image list.
1391 * PARAMS
1392 * himl [I] Image list handle.
1394 * RETURNS
1395 * Success: background color
1396 * Failure: CLR_NONE
1399 COLORREF WINAPI
1400 ImageList_GetBkColor (HIMAGELIST himl)
1402 if (himl == NULL)
1403 return CLR_NONE;
1405 return himl->clrBk;
1409 /*************************************************************************
1410 * ImageList_GetDragImage [COMCTL32.56]
1412 * Returns the handle to the internal drag image list.
1414 * PARAMS
1415 * ppt [O] Pointer to the drag position. Can be NULL.
1416 * pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
1418 * RETURNS
1419 * Success: Handle of the drag image list.
1420 * Failure: NULL.
1422 * BUGS
1423 * semi-stub.
1426 HIMAGELIST WINAPI
1427 ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot)
1429 FIXME("semi-stub!\n");
1431 if (himlInternalDrag)
1432 return (himlInternalDrag);
1434 return NULL;
1438 /*************************************************************************
1439 * ImageList_GetIcon [COMCTL32.57]
1441 * Creates an icon from a masked image of an image list.
1443 * PARAMS
1444 * himl [I] handle to image list
1445 * i [I] image index
1446 * flags [I] drawing style flags
1448 * RETURNS
1449 * Success: icon handle
1450 * Failure: NULL
1453 HICON WINAPI
1454 ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle)
1456 ICONINFO ii;
1457 HICON hIcon;
1458 HBITMAP hOldSrcBitmap,hOldDstBitmap;
1459 HDC hdcSrc, hdcDst;
1461 if ((himl == NULL) || (i < 0) || (i >= himl->cCurImage)) {
1462 FIXME("(%p,%d,%x), params out of range!\n",himl,i,fStyle);
1463 return 0;
1466 hdcSrc = CreateCompatibleDC(0);
1467 hdcDst = CreateCompatibleDC(0);
1469 ii.fIcon = TRUE;
1470 ii.hbmMask = CreateCompatibleBitmap (hdcDst, himl->cx, himl->cy);
1472 /* draw mask*/
1473 hOldDstBitmap = (HBITMAP)SelectObject (hdcDst, ii.hbmMask);
1474 if (himl->hbmMask) {
1475 SelectObject (hdcSrc, himl->hbmMask);
1476 BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1477 hdcSrc, i * himl->cx, 0, SRCCOPY);
1479 else
1480 PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS);
1482 /* draw image*/
1483 hOldSrcBitmap = (HBITMAP)SelectObject (hdcSrc, himl->hbmImage);
1484 ii.hbmColor = CreateCompatibleBitmap (hdcSrc, himl->cx, himl->cy);
1485 SelectObject (hdcDst, ii.hbmColor);
1486 BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1487 hdcSrc, i * himl->cx, 0, SRCCOPY);
1490 * CreateIconIndirect requires us to deselect the bitmaps from
1491 * the DCs before calling
1493 SelectObject(hdcSrc, hOldSrcBitmap);
1494 SelectObject(hdcDst, hOldDstBitmap);
1496 hIcon = CreateIconIndirect (&ii);
1498 DeleteDC (hdcSrc);
1499 DeleteDC (hdcDst);
1500 DeleteObject (ii.hbmMask);
1501 DeleteObject (ii.hbmColor);
1503 return hIcon;
1507 /*************************************************************************
1508 * ImageList_GetIconSize [COMCTL32.58]
1510 * Retrieves the size of an image in an image list.
1512 * PARAMS
1513 * himl [I] handle to image list
1514 * cx [O] pointer to the image width.
1515 * cy [O] pointer to the image height.
1517 * RETURNS
1518 * Success: TRUE
1519 * Failure: FALSE
1521 * NOTES
1522 * All images in an image list have the same size.
1525 BOOL WINAPI
1526 ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy)
1528 if (himl == NULL)
1529 return FALSE;
1530 if ((himl->cx <= 0) || (himl->cy <= 0))
1531 return FALSE;
1533 if (cx)
1534 *cx = himl->cx;
1535 if (cy)
1536 *cy = himl->cy;
1538 return TRUE;
1542 /*************************************************************************
1543 * ImageList_GetImageCount [COMCTL32.59]
1545 * Returns the number of images in an image list.
1547 * PARAMS
1548 * himl [I] handle to image list
1550 * RETURNS
1551 * Success: Number of images.
1552 * Failure: 0
1555 INT WINAPI
1556 ImageList_GetImageCount (HIMAGELIST himl)
1558 if (himl == NULL)
1559 return 0;
1561 return himl->cCurImage;
1565 /*************************************************************************
1566 * ImageList_GetImageInfo [COMCTL32.60]
1568 * Returns information about an image in an image list.
1570 * PARAMS
1571 * himl [I] handle to image list
1572 * i [I] image index
1573 * pImageInfo [O] pointer to the image information
1575 * RETURNS
1576 * Success: TRUE
1577 * Failure: FALSE
1580 BOOL WINAPI
1581 ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
1583 if ((himl == NULL) || (pImageInfo == NULL))
1584 return FALSE;
1585 if ((i < 0) || (i >= himl->cCurImage))
1586 return FALSE;
1588 pImageInfo->hbmImage = himl->hbmImage;
1589 pImageInfo->hbmMask = himl->hbmMask;
1591 pImageInfo->rcImage.top = 0;
1592 pImageInfo->rcImage.bottom = himl->cy;
1593 pImageInfo->rcImage.left = i * himl->cx;
1594 pImageInfo->rcImage.right = (i+1) * himl->cx;
1596 return TRUE;
1600 /*************************************************************************
1601 * ImageList_GetImageRect [COMCTL32.61]
1603 * Retrieves the rectangle of the specified image in an image list.
1605 * PARAMS
1606 * himl [I] handle to image list
1607 * i [I] image index
1608 * lpRect [O] pointer to the image rectangle
1610 * RETURNS
1611 * Success: TRUE
1612 * Failure: FALSE
1614 * NOTES
1615 * This is an UNDOCUMENTED function!!!
1618 BOOL WINAPI
1619 ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect)
1621 if ((himl == NULL) || (lpRect == NULL))
1622 return FALSE;
1623 if ((i < 0) || (i >= himl->cCurImage))
1624 return FALSE;
1626 lpRect->left = i * himl->cx;
1627 lpRect->top = 0;
1628 lpRect->right = lpRect->left + himl->cx;
1629 lpRect->bottom = himl->cy;
1631 return TRUE;
1635 /*************************************************************************
1636 * ImageList_LoadImageA [COMCTL32.63][COMCTL32.62]
1638 * Creates an image list from a bitmap, icon or cursor.
1640 * PARAMS
1641 * hi [I] instance handle
1642 * lpbmp [I] name or id of the image
1643 * cx [I] width of each image
1644 * cGrow [I] number of images to expand
1645 * clrMask [I] mask color
1646 * uType [I] type of image to load
1647 * uFlags [I] loading flags
1649 * RETURNS
1650 * Success: handle to the loaded image list
1651 * Failure: NULL
1653 * SEE
1654 * LoadImage ()
1657 HIMAGELIST WINAPI
1658 ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx, INT cGrow,
1659 COLORREF clrMask, UINT uType, UINT uFlags)
1661 HIMAGELIST himl = NULL;
1662 HANDLE handle;
1663 INT nImageCount;
1665 handle = LoadImageA (hi, lpbmp, uType, 0, 0, uFlags);
1666 if (!handle) {
1667 ERR("Error loading image!\n");
1668 return NULL;
1671 if (uType == IMAGE_BITMAP) {
1672 BITMAP bmp;
1673 GetObjectA (handle, sizeof(BITMAP), &bmp);
1675 /* To match windows behavior, if cx is set to zero and
1676 the flag DI_DEFAULTSIZE is specified, cx becomes the
1677 system metric value for icons. If the flag is not specified
1678 the function sets the size to the height of the bitmap */
1679 if (cx == 0)
1681 if (uFlags & DI_DEFAULTSIZE)
1682 cx = GetSystemMetrics (SM_CXICON);
1683 else
1684 cx = bmp.bmHeight;
1687 nImageCount = bmp.bmWidth / cx;
1689 himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1690 nImageCount, cGrow);
1691 ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1693 else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1694 ICONINFO ii;
1695 BITMAP bmp;
1697 GetIconInfo (handle, &ii);
1698 GetObjectA (ii.hbmColor, sizeof(BITMAP), (LPVOID)&bmp);
1699 himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1700 ILC_MASK | ILC_COLOR, 1, cGrow);
1701 ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1702 DeleteObject (ii.hbmColor);
1703 DeleteObject (ii.hbmMask);
1706 DeleteObject (handle);
1708 return himl;
1712 /*************************************************************************
1713 * ImageList_LoadImageW [COMCTL32.64]
1715 * Creates an image list from a bitmap, icon or cursor.
1717 * PARAMS
1718 * hi [I] instance handle
1719 * lpbmp [I] name or id of the image
1720 * cx [I] width of each image
1721 * cGrow [I] number of images to expand
1722 * clrMask [I] mask color
1723 * uType [I] type of image to load
1724 * uFlags [I] loading flags
1726 * RETURNS
1727 * Success: handle to the loaded image list
1728 * Failure: NULL
1730 * SEE
1731 * LoadImage ()
1734 HIMAGELIST WINAPI
1735 ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow,
1736 COLORREF clrMask, UINT uType, UINT uFlags)
1738 HIMAGELIST himl = NULL;
1739 HANDLE handle;
1740 INT nImageCount;
1742 handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags);
1743 if (!handle) {
1744 ERR("Error loading image!\n");
1745 return NULL;
1748 if (uType == IMAGE_BITMAP) {
1749 BITMAP bmp;
1750 GetObjectA (handle, sizeof(BITMAP), &bmp);
1751 nImageCount = bmp.bmWidth / cx;
1753 himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1754 nImageCount, cGrow);
1755 ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1757 else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1758 ICONINFO ii;
1759 BITMAP bmp;
1761 GetIconInfo (handle, &ii);
1762 GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
1763 himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1764 ILC_MASK | ILC_COLOR, 1, cGrow);
1765 ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1766 DeleteObject (ii.hbmColor);
1767 DeleteObject (ii.hbmMask);
1770 DeleteObject (handle);
1772 return himl;
1776 /*************************************************************************
1777 * ImageList_Merge [COMCTL32.65]
1779 * Creates a new image list that contains a merged image from the specified
1780 * images of both source image lists.
1782 * PARAMS
1783 * himl1 [I] handle to first image list
1784 * i1 [I] first image index
1785 * himl2 [I] handle to second image list
1786 * i2 [I] second image index
1787 * dx [I] X offset of the second image relative to the first.
1788 * dy [I] Y offset of the second image relative to the first.
1790 * RETURNS
1791 * Success: handle of the merged image list.
1792 * Failure: NULL
1795 HIMAGELIST WINAPI
1796 ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
1797 INT dx, INT dy)
1799 HIMAGELIST himlDst = NULL;
1800 HDC hdcSrcImage, hdcDstImage;
1801 INT cxDst, cyDst;
1802 INT xOff1, yOff1, xOff2, yOff2;
1803 INT nX1, nX2;
1805 if ((himl1 == NULL) || (himl2 == NULL))
1806 return NULL;
1808 /* check indices */
1809 if ((i1 < 0) || (i1 >= himl1->cCurImage)) {
1810 ERR("Index 1 out of range! %d\n", i1);
1811 return NULL;
1814 if ((i2 < 0) || (i2 >= himl2->cCurImage)) {
1815 ERR("Index 2 out of range! %d\n", i2);
1816 return NULL;
1819 if (dx > 0) {
1820 cxDst = _MAX (himl1->cx, dx + himl2->cx);
1821 xOff1 = 0;
1822 xOff2 = dx;
1824 else if (dx < 0) {
1825 cxDst = _MAX (himl2->cx, himl1->cx - dx);
1826 xOff1 = -dx;
1827 xOff2 = 0;
1829 else {
1830 cxDst = _MAX (himl1->cx, himl2->cx);
1831 xOff1 = 0;
1832 xOff2 = 0;
1835 if (dy > 0) {
1836 cyDst = _MAX (himl1->cy, dy + himl2->cy);
1837 yOff1 = 0;
1838 yOff2 = dy;
1840 else if (dy < 0) {
1841 cyDst = _MAX (himl2->cy, himl1->cy - dy);
1842 yOff1 = -dy;
1843 yOff2 = 0;
1845 else {
1846 cyDst = _MAX (himl1->cy, himl2->cy);
1847 yOff1 = 0;
1848 yOff2 = 0;
1851 himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
1853 if (himlDst) {
1854 hdcSrcImage = CreateCompatibleDC (0);
1855 hdcDstImage = CreateCompatibleDC (0);
1856 nX1 = i1 * himl1->cx;
1857 nX2 = i2 * himl2->cx;
1859 /* copy image */
1860 SelectObject (hdcSrcImage, himl1->hbmImage);
1861 SelectObject (hdcDstImage, himlDst->hbmImage);
1862 BitBlt (hdcDstImage, 0, 0, cxDst, cyDst,
1863 hdcSrcImage, 0, 0, BLACKNESS);
1864 BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy,
1865 hdcSrcImage, nX1, 0, SRCCOPY);
1867 SelectObject (hdcSrcImage, himl2->hbmMask);
1868 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1869 hdcSrcImage, nX2, 0, SRCAND);
1871 SelectObject (hdcSrcImage, himl2->hbmImage);
1872 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1873 hdcSrcImage, nX2, 0, SRCPAINT);
1875 /* copy mask */
1876 SelectObject (hdcSrcImage, himl1->hbmMask);
1877 SelectObject (hdcDstImage, himlDst->hbmMask);
1878 BitBlt (hdcDstImage, 0, 0, cxDst, cyDst,
1879 hdcSrcImage, 0, 0, WHITENESS);
1880 BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy,
1881 hdcSrcImage, nX1, 0, SRCCOPY);
1883 SelectObject (hdcSrcImage, himl2->hbmMask);
1884 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1885 hdcSrcImage, nX2, 0, SRCAND);
1887 DeleteDC (hdcSrcImage);
1888 DeleteDC (hdcDstImage);
1891 return himlDst;
1895 /* helper for _read_bitmap currently unused */
1896 #if 0
1897 static int may_use_dibsection(HDC hdc) {
1898 int bitspixel = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES);
1899 if (bitspixel>8)
1900 return TRUE;
1901 if (bitspixel<=4)
1902 return FALSE;
1903 return GetDeviceCaps(hdc,94) & 0x10;
1905 #endif
1907 /* helper for ImageList_Read, see comments below */
1908 static HBITMAP _read_bitmap(LPSTREAM pstm,int ilcFlag,int cx,int cy) {
1909 HDC xdc = 0;
1910 BITMAPFILEHEADER bmfh;
1911 BITMAPINFOHEADER bmih;
1912 int bitsperpixel,palspace,longsperline,width,height;
1913 LPBITMAPINFOHEADER bmihc = NULL;
1914 int result = 0;
1915 HBITMAP hbitmap = 0;
1916 LPBYTE bits = NULL,nbits = NULL;
1917 int nbytesperline,bytesperline;
1919 if (!SUCCEEDED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL)) ||
1920 (bmfh.bfType != (('M'<<8)|'B')) ||
1921 !SUCCEEDED(IStream_Read ( pstm, &bmih, sizeof(bmih), NULL)) ||
1922 (bmih.biSize != sizeof(bmih))
1924 return 0;
1926 bitsperpixel = bmih.biPlanes * bmih.biBitCount;
1927 if (bitsperpixel<=8)
1928 palspace = (1<<bitsperpixel)*sizeof(RGBQUAD);
1929 else
1930 palspace = 0;
1931 width = bmih.biWidth;
1932 height = bmih.biHeight;
1933 bmihc = (LPBITMAPINFOHEADER)LocalAlloc(LMEM_ZEROINIT,sizeof(bmih)+palspace);
1934 memcpy(bmihc,&bmih,sizeof(bmih));
1935 longsperline = ((width*bitsperpixel+31)&~0x1f)>>5;
1936 bmihc->biSizeImage = (longsperline*height)<<2;
1938 /* read the palette right after the end of the bitmapinfoheader */
1939 if (palspace)
1940 if (!SUCCEEDED(IStream_Read ( pstm, bmihc+1, palspace, NULL)))
1941 goto ret1;
1943 xdc = GetDC(0);
1944 #if 0 /* Magic for NxM -> 1x(N*M) not implemented for DIB Sections */
1945 if ((bitsperpixel>1) &&
1946 ((ilcFlag!=ILC_COLORDDB) && (!ilcFlag || may_use_dibsection(xdc)))
1948 hbitmap = CreateDIBSection(xdc,(BITMAPINFO*)bmihc,0,(LPVOID*)&bits,0,0);
1949 if (!hbitmap)
1950 goto ret1;
1951 if (!SUCCEEDED(IStream_Read( pstm, bits, bmihc->biSizeImage, NULL)))
1952 goto ret1;
1953 result = 1;
1954 } else
1955 #endif
1957 int i,nwidth,nheight;
1959 nwidth = width*(height/cy);
1960 nheight = cy;
1962 if (bitsperpixel==1)
1963 hbitmap = CreateBitmap(nwidth,nheight,1,1,NULL);
1964 else
1965 hbitmap = CreateCompatibleBitmap(xdc,nwidth,nheight);
1967 /* Might be a bit excessive memory use here */
1968 bits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage);
1969 nbits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage);
1970 if (!SUCCEEDED(IStream_Read ( pstm, bits, bmihc->biSizeImage, NULL)))
1971 goto ret1;
1973 /* Copy the NxM bitmap into a 1x(N*M) bitmap we need, linewise */
1974 /* Do not forget that windows bitmaps are bottom->top */
1975 bytesperline = longsperline*4;
1976 nbytesperline = (height/cy)*bytesperline;
1977 for (i=0;i<height;i++) {
1978 memcpy(
1979 nbits+((height-1-i)%cy)*nbytesperline+(i/cy)*bytesperline,
1980 bits+bytesperline*(height-1-i),
1981 bytesperline
1984 bmihc->biWidth = nwidth;
1985 bmihc->biHeight = nheight;
1986 if (!SetDIBits(xdc,hbitmap,0,nheight,nbits,(BITMAPINFO*)bmihc,0))
1987 goto ret1;
1988 LocalFree((HLOCAL)nbits);
1989 LocalFree((HLOCAL)bits);
1990 result = 1;
1992 ret1:
1993 if (xdc) ReleaseDC(0,xdc);
1994 if (bmihc) LocalFree((HLOCAL)bmihc);
1995 if (!result) {
1996 if (hbitmap) {
1997 DeleteObject(hbitmap);
1998 hbitmap = 0;
2001 return hbitmap;
2004 /*************************************************************************
2005 * ImageList_Read [COMCTL32.66]
2007 * Reads an image list from a stream.
2009 * PARAMS
2010 * pstm [I] pointer to a stream
2012 * RETURNS
2013 * Success: handle to image list
2014 * Failure: NULL
2016 * The format is like this:
2017 * ILHEAD ilheadstruct;
2019 * for the color image part:
2020 * BITMAPFILEHEADER bmfh;
2021 * BITMAPINFOHEADER bmih;
2022 * only if it has a palette:
2023 * RGBQUAD rgbs[nr_of_paletted_colors];
2025 * BYTE colorbits[imagesize];
2027 * the following only if the ILC_MASK bit is set in ILHEAD.ilFlags:
2028 * BITMAPFILEHEADER bmfh_mask;
2029 * BITMAPINFOHEADER bmih_mask;
2030 * only if it has a palette (it usually does not):
2031 * RGBQUAD rgbs[nr_of_paletted_colors];
2033 * BYTE maskbits[imagesize];
2035 * CAVEAT: Those images are within a NxM bitmap, not the 1xN we expect.
2036 * _read_bitmap needs to convert them.
2038 HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
2040 ILHEAD ilHead;
2041 HIMAGELIST himl;
2042 HBITMAP hbmColor=0,hbmMask=0;
2043 int i;
2045 if (!SUCCEEDED(IStream_Read (pstm, &ilHead, sizeof(ILHEAD), NULL)))
2046 return NULL;
2047 if (ilHead.usMagic != (('L' << 8) | 'I'))
2048 return NULL;
2049 if (ilHead.usVersion != 0x101) /* probably version? */
2050 return NULL;
2052 #if 0
2053 FIXME(" ilHead.cCurImage = %d\n",ilHead.cCurImage);
2054 FIXME(" ilHead.cMaxImage = %d\n",ilHead.cMaxImage);
2055 FIXME(" ilHead.cGrow = %d\n",ilHead.cGrow);
2056 FIXME(" ilHead.cx = %d\n",ilHead.cx);
2057 FIXME(" ilHead.cy = %d\n",ilHead.cy);
2058 FIXME(" ilHead.flags = %x\n",ilHead.flags);
2059 FIXME(" ilHead.ovls[0] = %d\n",ilHead.ovls[0]);
2060 FIXME(" ilHead.ovls[1] = %d\n",ilHead.ovls[1]);
2061 FIXME(" ilHead.ovls[2] = %d\n",ilHead.ovls[2]);
2062 FIXME(" ilHead.ovls[3] = %d\n",ilHead.ovls[3]);
2063 #endif
2065 hbmColor = _read_bitmap(pstm,ilHead.flags & ~ILC_MASK,ilHead.cx,ilHead.cy);
2066 if (!hbmColor)
2067 return NULL;
2068 if (ilHead.flags & ILC_MASK) {
2069 hbmMask = _read_bitmap(pstm,0,ilHead.cx,ilHead.cy);
2070 if (!hbmMask) {
2071 DeleteObject(hbmColor);
2072 return NULL;
2076 himl = ImageList_Create (
2077 ilHead.cx,
2078 ilHead.cy,
2079 ilHead.flags,
2080 1, /* initial */
2081 ilHead.cGrow
2083 if (!himl) {
2084 DeleteObject(hbmColor);
2085 DeleteObject(hbmMask);
2086 return NULL;
2088 himl->hbmImage = hbmColor;
2089 himl->hbmMask = hbmMask;
2090 himl->cCurImage = ilHead.cCurImage;
2091 himl->cMaxImage = ilHead.cMaxImage;
2093 ImageList_SetBkColor(himl,ilHead.bkcolor);
2094 for (i=0;i<4;i++)
2095 ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1);
2096 return himl;
2100 /*************************************************************************
2101 * ImageList_Remove [COMCTL32.67] Removes an image from an image list
2103 * PARAMS
2104 * himl [I] image list handle
2105 * i [I] image index
2107 * RETURNS
2108 * Success: TRUE
2109 * Failure: FALSE
2112 BOOL WINAPI
2113 ImageList_Remove (HIMAGELIST himl, INT i)
2115 HBITMAP hbmNewImage, hbmNewMask;
2116 HDC hdcSrc, hdcDst;
2117 INT cxNew, nCount;
2119 if ((i < -1) || (i >= himl->cCurImage)) {
2120 ERR("index out of range! %d\n", i);
2121 return FALSE;
2124 if (himl->cCurImage == 0) {
2125 ERR("image list is already empty!\n");
2126 return FALSE;
2129 if (i == -1) {
2130 /* remove all */
2131 TRACE("remove all!\n");
2133 himl->cMaxImage = himl->cInitial + himl->cGrow;
2134 himl->cCurImage = 0;
2135 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2136 himl->nOvlIdx[nCount] = -1;
2138 DeleteObject (himl->hbmImage);
2139 himl->hbmImage =
2140 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2141 1, himl->uBitsPixel, NULL);
2143 if (himl->hbmMask) {
2144 DeleteObject (himl->hbmMask);
2145 himl->hbmMask =
2146 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2147 1, 1, NULL);
2150 else {
2151 /* delete one image */
2152 TRACE("Remove single image! %d\n", i);
2154 /* create new bitmap(s) */
2155 cxNew = (himl->cCurImage + himl->cGrow - 1) * himl->cx;
2157 TRACE(" - Number of images: %d / %d (Old/New)\n",
2158 himl->cCurImage, himl->cCurImage - 1);
2159 TRACE(" - Max. number of images: %d / %d (Old/New)\n",
2160 himl->cMaxImage, himl->cCurImage + himl->cGrow - 1);
2162 hbmNewImage =
2163 CreateBitmap (cxNew, himl->cy, 1, himl->uBitsPixel, NULL);
2165 if (himl->hbmMask)
2166 hbmNewMask = CreateBitmap (cxNew, himl->cy, 1, 1, NULL);
2167 else
2168 hbmNewMask = 0; /* Just to keep compiler happy! */
2170 hdcSrc = CreateCompatibleDC (0);
2171 hdcDst = CreateCompatibleDC (0);
2173 /* copy all images and masks prior to the "removed" image */
2174 if (i > 0) {
2175 TRACE("Pre image copy: Copy %d images\n", i);
2177 SelectObject (hdcSrc, himl->hbmImage);
2178 SelectObject (hdcDst, hbmNewImage);
2179 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2180 hdcSrc, 0, 0, SRCCOPY);
2182 if (himl->hbmMask) {
2183 SelectObject (hdcSrc, himl->hbmMask);
2184 SelectObject (hdcDst, hbmNewMask);
2185 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2186 hdcSrc, 0, 0, SRCCOPY);
2190 /* copy all images and masks behind the removed image */
2191 if (i < himl->cCurImage - 1) {
2192 TRACE("Post image copy!\n");
2193 SelectObject (hdcSrc, himl->hbmImage);
2194 SelectObject (hdcDst, hbmNewImage);
2195 BitBlt (hdcDst, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx,
2196 himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2198 if (himl->hbmMask) {
2199 SelectObject (hdcSrc, himl->hbmMask);
2200 SelectObject (hdcDst, hbmNewMask);
2201 BitBlt (hdcDst, i * himl->cx, 0,
2202 (himl->cCurImage - i - 1) * himl->cx,
2203 himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2207 DeleteDC (hdcSrc);
2208 DeleteDC (hdcDst);
2210 /* delete old images and insert new ones */
2211 DeleteObject (himl->hbmImage);
2212 himl->hbmImage = hbmNewImage;
2213 if (himl->hbmMask) {
2214 DeleteObject (himl->hbmMask);
2215 himl->hbmMask = hbmNewMask;
2218 himl->cCurImage--;
2219 himl->cMaxImage = himl->cCurImage + himl->cGrow;
2222 return TRUE;
2226 /*************************************************************************
2227 * ImageList_Replace [COMCTL32.68]
2229 * Replaces an image in an image list with a new image.
2231 * PARAMS
2232 * himl [I] handle to image list
2233 * i [I] image index
2234 * hbmImage [I] handle to image bitmap
2235 * hbmMask [I] handle to mask bitmap. Can be NULL.
2237 * RETURNS
2238 * Success: TRUE
2239 * Failure: FALSE
2242 BOOL WINAPI
2243 ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage,
2244 HBITMAP hbmMask)
2246 HDC hdcImageList, hdcImage;
2247 BITMAP bmp;
2249 if (himl == NULL) {
2250 ERR("Invalid image list handle!\n");
2251 return FALSE;
2254 if ((i >= himl->cCurImage) || (i < 0)) {
2255 ERR("Invalid image index!\n");
2256 return FALSE;
2259 hdcImageList = CreateCompatibleDC (0);
2260 hdcImage = CreateCompatibleDC (0);
2261 GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
2263 /* Replace Image */
2264 SelectObject (hdcImageList, himl->hbmImage);
2265 SelectObject (hdcImage, hbmImage);
2267 StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2268 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2270 if (himl->hbmMask)
2272 /* Replace Mask */
2273 SelectObject (hdcImageList, himl->hbmMask);
2274 SelectObject (hdcImage, hbmMask);
2276 StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2277 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2280 /* Remove the background from the image
2282 SelectObject (hdcImageList, himl->hbmImage);
2283 StretchBlt (hdcImageList,
2284 i*himl->cx, 0, himl->cx, himl->cy,
2285 hdcImage,
2286 0, 0, bmp.bmWidth, bmp.bmHeight,
2287 0x220326); /* NOTSRCAND */
2290 DeleteDC (hdcImage);
2291 DeleteDC (hdcImageList);
2293 return TRUE;
2297 /*************************************************************************
2298 * ImageList_ReplaceIcon [COMCTL32.69]
2300 * Replaces an image in an image list using an icon.
2302 * PARAMS
2303 * himl [I] handle to image list
2304 * i [I] image index
2305 * hIcon [I] handle to icon
2307 * RETURNS
2308 * Success: index of the replaced image
2309 * Failure: -1
2312 INT WINAPI
2313 ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon)
2315 HDC hdcImageList, hdcImage;
2316 INT nIndex;
2317 HICON hBestFitIcon;
2318 HBITMAP hbmOldSrc, hbmOldDst;
2319 ICONINFO ii;
2320 BITMAP bmp;
2322 TRACE("(0x%lx 0x%x 0x%x)\n", (DWORD)himl, i, hIcon);
2324 if (himl == NULL)
2325 return -1;
2326 if ((i >= himl->cCurImage) || (i < -1))
2327 return -1;
2329 hBestFitIcon = CopyImage(
2330 hIcon, IMAGE_ICON,
2331 himl->cx, himl->cy,
2332 LR_COPYFROMRESOURCE);
2334 GetIconInfo (hBestFitIcon, &ii);
2335 if (ii.hbmMask == 0)
2336 ERR("no mask!\n");
2337 if (ii.hbmColor == 0)
2338 ERR("no color!\n");
2339 GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
2341 if (i == -1) {
2342 if (himl->cCurImage + 1 >= himl->cMaxImage)
2343 IMAGELIST_InternalExpandBitmaps (himl, 1, 0, 0);
2345 nIndex = himl->cCurImage;
2346 himl->cCurImage++;
2348 else
2349 nIndex = i;
2351 hdcImageList = CreateCompatibleDC (0);
2352 TRACE("hdcImageList=0x%x!\n", hdcImageList);
2353 if (hdcImageList == 0)
2354 ERR("invalid hdcImageList!\n");
2356 hdcImage = CreateCompatibleDC (0);
2357 TRACE("hdcImage=0x%x!\n", hdcImage);
2358 if (hdcImage == 0)
2359 ERR("invalid hdcImage!\n");
2361 hbmOldDst = SelectObject (hdcImageList, himl->hbmImage);
2362 SetTextColor( hdcImageList, RGB(0,0,0));
2363 SetBkColor( hdcImageList, RGB(255,255,255));
2364 hbmOldSrc = SelectObject (hdcImage, ii.hbmColor);
2365 StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2366 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2368 if (himl->hbmMask) {
2369 SelectObject (hdcImageList, himl->hbmMask);
2370 SelectObject (hdcImage, ii.hbmMask);
2371 StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2372 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2375 SelectObject (hdcImage, hbmOldSrc);
2376 SelectObject (hdcImageList, hbmOldDst);
2378 if(hBestFitIcon)
2379 DestroyIcon(hBestFitIcon);
2380 if (hdcImageList)
2381 DeleteDC (hdcImageList);
2382 if (hdcImage)
2383 DeleteDC (hdcImage);
2384 if (ii.hbmColor)
2385 DeleteObject (ii.hbmColor);
2386 if (ii.hbmMask)
2387 DeleteObject (ii.hbmMask);
2389 return nIndex;
2393 /*************************************************************************
2394 * ImageList_SetBkColor [COMCTL32.70]
2396 * Sets the background color of an image list.
2398 * PARAMS
2399 * himl [I] handle to image list
2400 * clrBk [I] background color
2402 * RETURNS
2403 * Success: previous background color
2404 * Failure: CLR_NONE
2407 COLORREF WINAPI
2408 ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
2410 COLORREF clrOldBk;
2412 if (himl == NULL)
2413 return CLR_NONE;
2415 clrOldBk = himl->clrBk;
2416 himl->clrBk = clrBk;
2417 return clrOldBk;
2421 /*************************************************************************
2422 * ImageList_SetDragCursorImage [COMCTL32.75]
2424 * Combines the specified image with the current drag image
2426 * PARAMS
2427 * himlDrag [I] handle to drag image list
2428 * iDrag [I] drag image index
2429 * dxHotspot [I] X position of the hot spot
2430 * dyHotspot [I] Y position of the hot spot
2432 * RETURNS
2433 * Success: TRUE
2434 * Failure: FALSE
2436 * BUGS
2437 * semi-stub.
2440 BOOL WINAPI
2441 ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag,
2442 INT dxHotspot, INT dyHotspot)
2444 HIMAGELIST himlTemp;
2446 FIXME("semi-stub!\n");
2448 if (himlInternalDrag == NULL)
2449 return FALSE;
2451 TRACE(" dxH=%d dyH=%d nX=%d nY=%d\n",
2452 dxHotspot, dyHotspot, nInternalDragHotspotX, nInternalDragHotspotY);
2454 himlTemp = ImageList_Merge (himlInternalDrag, 0, himlDrag, iDrag,
2455 dxHotspot, dyHotspot);
2457 ImageList_Destroy (himlInternalDrag);
2458 himlInternalDrag = himlTemp;
2460 nInternalDragHotspotX = dxHotspot;
2461 nInternalDragHotspotY = dyHotspot;
2463 return FALSE;
2467 /*************************************************************************
2468 * ImageList_SetFilter [COMCTL32.76]
2470 * Sets a filter (or does something completely different)!!???
2472 * PARAMS
2473 * himl [I] handle to image list
2474 * i [I] ???
2475 * dwFilter [I] ???
2477 * RETURNS
2478 * Success: TRUE ???
2479 * Failure: FALSE ???
2481 * BUGS
2482 * This is an UNDOCUMENTED function!!!!
2483 * empty stub.
2486 BOOL WINAPI
2487 ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter)
2489 FIXME("(%p 0x%x 0x%lx):empty stub!\n",
2490 himl, i, dwFilter);
2492 return FALSE;
2496 /*************************************************************************
2497 * ImageList_SetIconSize [COMCTL32.77]
2499 * Sets the image size of the bitmap and deletes all images.
2501 * PARAMS
2502 * himl [I] handle to image list
2503 * cx [I] image width
2504 * cy [I] image height
2506 * RETURNS
2507 * Success: TRUE
2508 * Failure: FALSE
2511 BOOL WINAPI
2512 ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy)
2514 INT nCount;
2516 if (!himl)
2517 return FALSE;
2519 /* remove all images*/
2520 himl->cMaxImage = himl->cInitial + himl->cGrow;
2521 himl->cCurImage = 0;
2522 himl->cx = cx;
2523 himl->cy = cy;
2525 /* initialize overlay mask indices */
2526 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2527 himl->nOvlIdx[nCount] = -1;
2529 DeleteObject (himl->hbmImage);
2530 himl->hbmImage =
2531 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2532 1, himl->uBitsPixel, NULL);
2534 if (himl->hbmMask) {
2535 DeleteObject (himl->hbmMask);
2536 himl->hbmMask =
2537 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2538 1, 1, NULL);
2541 return TRUE;
2545 /*************************************************************************
2546 * ImageList_SetImageCount [COMCTL32.78]
2548 * Resizes an image list to the specified number of images.
2550 * PARAMS
2551 * himl [I] handle to image list
2552 * iImageCount [I] number of images in the image list
2554 * RETURNS
2555 * Success: TRUE
2556 * Failure: FALSE
2559 BOOL WINAPI
2560 ImageList_SetImageCount (HIMAGELIST himl, INT iImageCount)
2562 HDC hdcImageList, hdcBitmap;
2563 HBITMAP hbmNewBitmap;
2564 INT nNewCount, nCopyCount;
2566 if (!himl)
2567 return FALSE;
2568 if (himl->cCurImage >= iImageCount)
2569 return FALSE;
2570 if (himl->cMaxImage > iImageCount)
2571 return TRUE;
2573 nNewCount = iImageCount + himl->cGrow;
2574 nCopyCount = _MIN(himl->cCurImage, iImageCount);
2576 hdcImageList = CreateCompatibleDC (0);
2577 hdcBitmap = CreateCompatibleDC (0);
2579 hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2580 1, himl->uBitsPixel, NULL);
2581 if (hbmNewBitmap != 0)
2583 SelectObject (hdcImageList, himl->hbmImage);
2584 SelectObject (hdcBitmap, hbmNewBitmap);
2586 /* copy images */
2587 BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2588 hdcImageList, 0, 0, SRCCOPY);
2589 #if 0
2590 /* delete 'empty' image space */
2591 SetBkColor (hdcBitmap, RGB(255, 255, 255));
2592 SetTextColor (hdcBitmap, RGB(0, 0, 0));
2593 PatBlt (hdcBitmap, nCopyCount * himl->cx, 0,
2594 (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2595 #endif
2596 DeleteObject (himl->hbmImage);
2597 himl->hbmImage = hbmNewBitmap;
2599 else
2600 ERR("Could not create new image bitmap !\n");
2602 if (himl->hbmMask)
2604 hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2605 1, 1, NULL);
2606 if (hbmNewBitmap != 0)
2608 SelectObject (hdcImageList, himl->hbmMask);
2609 SelectObject (hdcBitmap, hbmNewBitmap);
2611 /* copy images */
2612 BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2613 hdcImageList, 0, 0, SRCCOPY);
2614 #if 0
2615 /* delete 'empty' image space */
2616 SetBkColor (hdcBitmap, RGB(255, 255, 255));
2617 SetTextColor (hdcBitmap, RGB(0, 0, 0));
2618 PatBlt (hdcBitmap, nCopyCount * himl->cx, 0,
2619 (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2620 #endif
2621 DeleteObject (himl->hbmMask);
2622 himl->hbmMask = hbmNewBitmap;
2624 else
2625 ERR("Could not create new mask bitmap!\n");
2628 DeleteDC (hdcImageList);
2629 DeleteDC (hdcBitmap);
2631 /* Update max image count and current image count */
2632 himl->cMaxImage = nNewCount;
2633 if (himl->cCurImage > nCopyCount)
2634 himl->cCurImage = nCopyCount;
2636 return TRUE;
2640 /*************************************************************************
2641 * ImageList_SetOverlayImage [COMCTL32.79]
2643 * Assigns an overlay mask index to an existing image in an image list.
2645 * PARAMS
2646 * himl [I] handle to image list
2647 * iImage [I] image index
2648 * iOverlay [I] overlay mask index
2650 * RETURNS
2651 * Success: TRUE
2652 * Failure: FALSE
2655 BOOL WINAPI
2656 ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay)
2658 if (!himl)
2659 return FALSE;
2660 if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
2661 return FALSE;
2662 if ((iImage!=-1) && ((iImage < 0) || (iImage > himl->cCurImage)))
2663 return FALSE;
2664 himl->nOvlIdx[iOverlay - 1] = iImage;
2665 return TRUE;
2669 /*************************************************************************
2670 * ImageList_Write [COMCTL32.80]
2672 * Writes an image list to a stream.
2674 * PARAMS
2675 * himl [I] handle to image list
2676 * pstm [O] Pointer to a stream.
2678 * RETURNS
2679 * Success: TRUE
2680 * Failure: FALSE
2682 * NOTES
2683 * This function can not be implemented yet, because
2684 * IStream32::Write is not implemented.
2686 * BUGS
2687 * empty stub.
2690 BOOL WINAPI
2691 ImageList_Write (HIMAGELIST himl, LPSTREAM pstm)
2693 if (!himl)
2694 return FALSE;
2696 FIXME("empty stub!\n");
2698 return FALSE;