- Implemented MESSAGETABLE resource type.
[wine.git] / dlls / comctl32 / imagelist.c
blob2ee0eb4c8be6fc79a1e23a4090abb8d4c248c822
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;
194 UINT fStyle = pimldp->fStyle & (~ILD_OVERLAYMASK);
196 bUseCustomBackground = (himlLocal->clrBk != CLR_NONE);
197 bBlendFlag = (fStyle & ILD_BLEND50 ) || (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 &&
207 (fStyle == ILD_NORMAL || fStyle & ILD_IMAGE || bBlendFlag))
209 hBrush = CreateSolidBrush (himlLocal->clrBk);
210 hOldBrush = SelectObject (pimldp->hdcDst, hBrush);
211 PatBlt (pimldp->hdcDst,
212 pimldp->x, pimldp->y, cx, cy,
213 PATCOPY);
215 DeleteObject (SelectObject (pimldp->hdcDst, hOldBrush));
218 /* Draw Image Transparently over the current background
220 if(fStyle == ILD_NORMAL
221 || (fStyle & ILD_TRANSPARENT)
222 || ((fStyle & ILD_IMAGE) && bUseCustomBackground)
223 || bBlendFlag)
225 /* to obtain a transparent look, background color should be set
226 to white and foreground color to black when blting the
227 monochrome mask. */
228 oldBkColor = SetBkColor(pimldp->hdcDst, RGB(0xff, 0xff, 0xff));
229 oldFgColor = SetTextColor(pimldp->hdcDst, RGB(0, 0, 0));
231 BitBlt(pimldp->hdcDst,
232 pimldp->x, pimldp->y, cx, cy,
233 hMaskDC,
234 himlLocal->cx * pimldp->i, 0,
235 SRCAND);
237 BitBlt(pimldp->hdcDst,
238 pimldp->x, pimldp->y, cx, cy,
239 hImageDC,
240 himlLocal->cx * pimldp->i, 0,
241 SRCPAINT);
243 SetBkColor(pimldp->hdcDst, oldBkColor);
244 SetTextColor(pimldp->hdcDst, oldFgColor);
246 /* Draw the image when no Background is specified
248 else if((fStyle & ILD_IMAGE) && !bUseCustomBackground)
250 BitBlt(pimldp->hdcDst,
251 pimldp->x, pimldp->y, cx, cy,
252 hImageDC,
253 himlLocal->cx * pimldp->i, 0,
254 SRCCOPY);
256 /* Draw the mask with or without a background
258 else if(fStyle & ILD_MASK)
260 BitBlt(pimldp->hdcDst,
261 pimldp->x, pimldp->y, cx, cy,
262 hMaskDC,
263 himlLocal->cx * pimldp->i, 0,
264 bUseCustomBackground ? SRCCOPY : SRCAND);
266 SelectObject(hImageDC, hOldBitmapImage);
267 SelectObject(hMaskDC, hOldBitmapMask);
268 DeleteDC(hImageDC);
269 DeleteDC(hMaskDC);
272 /*************************************************************************
273 * IMAGELIST_InternalDrawBlend [Internal]
275 * Draws the Blend over the current image
277 * PARAMS
278 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
279 * cx [I] the width of the image to display
280 * cy............[I] the height of the image to display
282 * RETURNS
283 * nothing
285 * NOTES
286 * This functions is used by ImageList_DrawIndirect, when it is
287 * required to add the blend to the current image.
290 static VOID
291 IMAGELIST_InternalDrawBlend(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
294 HDC hBlendMaskDC,hMaskDC;
295 HBRUSH hBlendColorBrush, hBlendBrush, hOldBrush;
296 HBITMAP hBlendMaskBitmap, hOldBitmap;
297 COLORREF clrBlend, OldTextColor, OldBkColor;
298 HIMAGELIST himlLocal = pimldp->himl;
300 clrBlend = GetSysColor (COLOR_HIGHLIGHT);
301 if (!(pimldp->rgbFg == CLR_DEFAULT))
303 clrBlend = pimldp->rgbFg;
305 /* Create the blend Mask
307 hBlendMaskDC = CreateCompatibleDC(0);
308 hBlendBrush = pimldp->fStyle & ILD_BLEND50 ?
309 himlLocal->hbrBlend50 : himlLocal->hbrBlend25;
311 hBlendMaskBitmap = CreateBitmap(cx, cy, 1, 1, NULL);
312 hOldBitmap = SelectObject(hBlendMaskDC, hBlendMaskBitmap);
314 hOldBrush = (HBRUSH) SelectObject(hBlendMaskDC, hBlendBrush);
315 PatBlt(hBlendMaskDC, 0, 0, cx, cy, PATCOPY);
316 SelectObject(hBlendMaskDC, hOldBrush);
318 /* Modify the blend mask if an Image Mask exist
320 if(pimldp->himl->hbmMask != 0)
322 HBITMAP hOldMaskBitmap;
323 hMaskDC = CreateCompatibleDC(0);
324 hOldMaskBitmap = (HBITMAP) SelectObject(hMaskDC, himlLocal->hbmMask);
326 BitBlt(hBlendMaskDC,
327 0,0, cx, cy,
328 hMaskDC,
329 himlLocal->cx * pimldp->i,0,
330 0x220326); /* NOTSRCAND */
332 BitBlt(hBlendMaskDC,
333 0,0, cx, cy,
334 hBlendMaskDC,
335 0,0,
336 NOTSRCCOPY);
338 SelectObject(hMaskDC, hOldMaskBitmap);
339 DeleteDC(hMaskDC);
342 /* Apply blend to the current image given the BlendMask
344 OldTextColor = SetTextColor(pimldp->hdcDst, 0);
345 OldBkColor = SetBkColor(pimldp->hdcDst, RGB(255,255,255));
346 hBlendColorBrush = CreateSolidBrush(clrBlend);
347 hOldBrush = (HBRUSH) SelectObject (pimldp->hdcDst, hBlendColorBrush);
349 BitBlt (pimldp->hdcDst,
350 pimldp->x, pimldp->y, cx, cy,
351 hBlendMaskDC,
352 0, 0,
353 0xB8074A); /* PSDPxax */
355 SelectObject(pimldp->hdcDst, hOldBrush);
356 SetTextColor(pimldp->hdcDst, OldTextColor);
357 SetBkColor(pimldp->hdcDst, OldBkColor);
358 SelectObject(hBlendMaskDC, hOldBitmap);
359 DeleteDC(hBlendMaskDC);
360 DeleteObject(hBlendMaskBitmap);
361 DeleteObject(hBlendColorBrush);
364 /*************************************************************************
365 * IMAGELIST_InternalDrawOverlay [Internal]
367 * Draws the overlay image
369 * PARAMS
370 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
371 * cx [I] the width of the image to display
372 * cy............[I] the height of the image to display
374 * RETURNS
375 * nothing
377 * NOTES
378 * This functions is used by ImageList_DrawIndirect, when it is
379 * required to draw the overlay
383 static VOID
384 IMAGELIST_InternalDrawOverlay(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
386 INT nOvlIdx;
387 HDC hImageDC;
388 HBITMAP hOldBitmap;
390 nOvlIdx = (pimldp->fStyle & ILD_OVERLAYMASK) >> 8;
391 if ((nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE))
393 nOvlIdx = pimldp->himl->nOvlIdx[nOvlIdx - 1];
394 if ((nOvlIdx >= 0) && (nOvlIdx <= pimldp->himl->cCurImage))
396 hImageDC = CreateCompatibleDC(0);
397 if (pimldp->himl->hbmMask)
399 hOldBitmap = (HBITMAP) SelectObject (hImageDC,
400 pimldp->himl->hbmMask);
402 BitBlt (pimldp->hdcDst,
403 pimldp->x, pimldp->y, cx, cy,
404 hImageDC, pimldp->himl->cx * nOvlIdx, 0,
405 SRCAND);
407 SelectObject(hImageDC, hOldBitmap);
409 hOldBitmap = (HBITMAP) SelectObject (hImageDC,
410 pimldp->himl->hbmImage);
412 BitBlt (pimldp->hdcDst,
413 pimldp->x, pimldp->y, cx, cy,
414 hImageDC,
415 pimldp->himl->cx * nOvlIdx, 0,
416 SRCPAINT);
418 SelectObject(hImageDC, hOldBitmap);
419 DeleteDC(hImageDC);
428 /*************************************************************************
429 * ImageList_Add [COMCTL32.39]
431 * Add an image or images to an image list.
433 * PARAMS
434 * himl [I] handle to image list
435 * hbmImage [I] handle to image bitmap
436 * hbmMask [I] handle to mask bitmap
438 * RETURNS
439 * Success: Index of the first new image.
440 * Failure: -1
443 INT WINAPI
444 ImageList_Add (HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
446 HDC hdcImage, hdcBitmap;
447 INT nFirstIndex, nImageCount;
448 INT nStartX;
449 BITMAP bmp;
450 HBITMAP hOldBitmapImage, hOldBitmap;
452 if (!himl || !hbmImage)
453 return -1;
455 GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
456 nImageCount = bmp.bmWidth / himl->cx;
458 if (himl->cCurImage + nImageCount >= himl->cMaxImage)
459 IMAGELIST_InternalExpandBitmaps (himl, nImageCount);
461 nStartX = himl->cCurImage * himl->cx;
463 hdcImage = CreateCompatibleDC(0);
464 hdcBitmap = CreateCompatibleDC(0);
466 hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
467 hOldBitmap = SelectObject(hdcBitmap, hbmImage);
469 /* Copy result to the imagelist
471 BitBlt (hdcImage, nStartX, 0, bmp.bmWidth, himl->cy,
472 hdcBitmap, 0, 0, SRCCOPY);
474 if(himl->hbmMask)
476 HDC hdcMask, hdcTemp, hOldBitmapMask, hOldBitmapTemp;
478 hdcMask = CreateCompatibleDC (0);
479 hdcTemp = CreateCompatibleDC(0);
480 hOldBitmapMask = (HBITMAP) SelectObject(hdcMask, himl->hbmMask);
481 hOldBitmapTemp = (HBITMAP) SelectObject(hdcTemp, hbmMask);
483 BitBlt (hdcMask,
484 nStartX, 0, bmp.bmWidth, himl->cy,
485 hdcTemp,
486 0, 0,
487 SRCCOPY);
489 SelectObject(hdcTemp, hOldBitmapTemp);
490 DeleteDC(hdcTemp);
492 /* Remove the background from the image
494 BitBlt (hdcImage,
495 nStartX, 0, bmp.bmWidth, himl->cy,
496 hdcMask,
497 nStartX, 0,
498 0x220326); /* NOTSRCAND */
500 SelectObject(hdcMask, hOldBitmapMask);
501 DeleteDC(hdcMask);
504 SelectObject(hdcImage, hOldBitmapImage);
505 SelectObject(hdcBitmap, hOldBitmap);
506 DeleteDC(hdcImage);
507 DeleteDC(hdcBitmap);
509 nFirstIndex = himl->cCurImage;
510 himl->cCurImage += nImageCount;
512 return nFirstIndex;
516 /*************************************************************************
517 * ImageList_AddIcon [COMCTL32.40]
519 * Adds an icon to an image list.
521 * PARAMS
522 * himl [I] handle to image list
523 * hIcon [I] handle to icon
525 * RETURNS
526 * Success: index of the new image
527 * Failure: -1
530 INT WINAPI
531 ImageList_AddIcon (HIMAGELIST himl, HICON hIcon)
533 return ImageList_ReplaceIcon (himl, -1, hIcon);
537 /*************************************************************************
538 * ImageList_AddMasked [COMCTL32.41]
540 * Adds an image or images to an image list and creates a mask from the
541 * specified bitmap using the mask color.
543 * PARAMS
544 * himl [I] handle to image list.
545 * hBitmap [I] handle to bitmap
546 * clrMask [I] mask color.
548 * RETURNS
549 * Success: Index of the first new image.
550 * Failure: -1
553 INT WINAPI
554 ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
556 HDC hdcImage, hdcMask, hdcBitmap;
557 INT nIndex, nImageCount, nMaskXOffset=0;
558 BITMAP bmp;
559 HBITMAP hOldBitmap, hOldBitmapMask, hOldBitmapImage;
560 HBITMAP hMaskBitmap=0;
561 COLORREF bkColor;
563 if (himl == NULL)
564 return -1;
566 if (!GetObjectA (hBitmap, sizeof(BITMAP), &bmp))
567 return -1;
569 nImageCount = bmp.bmWidth / himl->cx;
571 if (himl->cCurImage + nImageCount >= himl->cMaxImage)
573 IMAGELIST_InternalExpandBitmaps (himl, nImageCount);
576 nIndex = himl->cCurImage;
577 himl->cCurImage += nImageCount;
579 hdcMask = CreateCompatibleDC (0);
580 hdcImage = CreateCompatibleDC(0);
581 hdcBitmap = CreateCompatibleDC(0);
584 hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
585 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
586 if(himl->hbmMask)
588 hOldBitmapMask = SelectObject(hdcMask, himl->hbmMask);
589 nMaskXOffset = nIndex * himl->cx;
591 else
594 Create a temp Mask so we can remove the background of
595 the Image (Windows does this even if there is no mask)
597 hMaskBitmap = CreateBitmap(bmp.bmWidth, himl->cy, 1, 1, NULL);
598 hOldBitmapMask = SelectObject(hdcMask, hMaskBitmap);
599 nMaskXOffset = 0;
601 /* create monochrome image to the mask bitmap */
602 bkColor = (clrMask != CLR_DEFAULT) ? clrMask :
603 GetPixel (hdcBitmap, 0, 0);
604 SetBkColor (hdcBitmap, bkColor);
605 BitBlt (hdcMask,
606 nMaskXOffset, 0, bmp.bmWidth, himl->cy,
607 hdcBitmap, 0, 0,
608 SRCCOPY);
610 SetBkColor(hdcBitmap, RGB(255,255,255));
611 /*Remove the background from the image
614 WINDOWS BUG ALERT!!!!!!
615 The statement below should not be done in common practice
616 but this is how ImageList_AddMasked works in Windows.
617 It overwrites the original bitmap passed, this was discovered
618 by using the same bitmap to itterated the different styles
619 on windows where it failed (BUT ImageList_Add is OK)
620 This is here in case some apps really on this bug
622 BitBlt(hdcBitmap,
623 0, 0, bmp.bmWidth, himl->cy,
624 hdcMask,
625 nMaskXOffset, 0,
626 0x220326); /* NOTSRCAND */
627 /* Copy result to the imagelist
629 BitBlt (hdcImage,
630 nIndex * himl->cx, 0, bmp.bmWidth, himl->cy,
631 hdcBitmap,
632 0, 0,
633 SRCCOPY);
634 /* Clean up
636 SelectObject(hdcMask,hOldBitmapMask);
637 SelectObject(hdcImage, hOldBitmapImage);
638 SelectObject(hdcBitmap, hOldBitmap);
639 DeleteDC(hdcMask);
640 DeleteDC(hdcImage);
641 DeleteDC(hdcBitmap);
642 if(!himl->hbmMask)
644 DeleteObject(hMaskBitmap);
647 return nIndex;
651 /*************************************************************************
652 * ImageList_BeginDrag [COMCTL32.42]
654 * Creates a temporary image list that contains one image. It will be used
655 * as a drag image.
657 * PARAMS
658 * himlTrack [I] handle to the source image list
659 * iTrack [I] index of the drag image in the source image list
660 * dxHotspot [I] X position of the hot spot of the drag image
661 * dyHotspot [I] Y position of the hot spot of the drag image
663 * RETURNS
664 * Success: TRUE
665 * Failure: FALSE
668 BOOL WINAPI
669 ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
670 INT dxHotspot, INT dyHotspot)
672 HDC hdcSrc, hdcDst;
674 FIXME("partially implemented!\n");
676 if (himlTrack == NULL)
677 return FALSE;
679 if (himlInternalDrag)
680 ImageList_EndDrag ();
682 himlInternalDrag =
683 ImageList_Create (himlTrack->cx, himlTrack->cy,
684 himlTrack->flags, 1, 1);
685 if (himlInternalDrag == NULL) {
686 ERR("Error creating drag image list!\n");
687 return FALSE;
690 nInternalDragHotspotX = dxHotspot;
691 nInternalDragHotspotY = dyHotspot;
693 hdcSrc = CreateCompatibleDC (0);
694 hdcDst = CreateCompatibleDC (0);
696 /* copy image */
697 SelectObject (hdcSrc, himlTrack->hbmImage);
698 SelectObject (hdcDst, himlInternalDrag->hbmImage);
699 StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
700 iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
702 /* copy mask */
703 SelectObject (hdcSrc, himlTrack->hbmMask);
704 SelectObject (hdcDst, himlInternalDrag->hbmMask);
705 StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
706 iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
708 DeleteDC (hdcSrc);
709 DeleteDC (hdcDst);
711 himlInternalDrag->cCurImage = 1;
713 return TRUE;
717 /*************************************************************************
718 * ImageList_Copy [COMCTL32.43]
720 * Copies an image of the source image list to an image of the
721 * destination image list. Images can be copied or swapped.
723 * PARAMS
724 * himlDst [I] handle to the destination image list
725 * iDst [I] destination image index.
726 * himlSrc [I] handle to the source image list
727 * iSrc [I] source image index
728 * uFlags [I] flags for the copy operation
730 * RETURNS
731 * Success: TRUE
732 * Failure: FALSE
734 * NOTES
735 * Copying from one image list to another is possible. The original
736 * implementation just copies or swapps within one image list.
737 * Could this feature become a bug??? ;-)
740 BOOL WINAPI
741 ImageList_Copy (HIMAGELIST himlDst, INT iDst, HIMAGELIST himlSrc,
742 INT iSrc, INT uFlags)
744 HDC hdcSrc, hdcDst;
746 TRACE("iDst=%d iSrc=%d\n", iDst, iSrc);
748 if ((himlSrc == NULL) || (himlDst == NULL))
749 return FALSE;
750 if ((iDst < 0) || (iDst >= himlDst->cCurImage))
751 return FALSE;
752 if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage))
753 return FALSE;
755 hdcSrc = CreateCompatibleDC (0);
756 if (himlDst == himlSrc)
757 hdcDst = hdcSrc;
758 else
759 hdcDst = CreateCompatibleDC (0);
761 if (uFlags & ILCF_SWAP) {
762 /* swap */
763 HBITMAP hbmTempImage, hbmTempMask;
765 /* create temporary bitmaps */
766 hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
767 himlSrc->uBitsPixel, NULL);
768 hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
769 1, NULL);
771 /* copy (and stretch) destination to temporary bitmaps.(save) */
772 /* image */
773 SelectObject (hdcSrc, himlDst->hbmImage);
774 SelectObject (hdcDst, hbmTempImage);
775 StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
776 hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
777 SRCCOPY);
778 /* mask */
779 SelectObject (hdcSrc, himlDst->hbmMask);
780 SelectObject (hdcDst, hbmTempMask);
781 StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
782 hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
783 SRCCOPY);
785 /* copy (and stretch) source to destination */
786 /* image */
787 SelectObject (hdcSrc, himlSrc->hbmImage);
788 SelectObject (hdcDst, himlDst->hbmImage);
789 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
790 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
791 SRCCOPY);
792 /* mask */
793 SelectObject (hdcSrc, himlSrc->hbmMask);
794 SelectObject (hdcDst, himlDst->hbmMask);
795 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
796 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
797 SRCCOPY);
799 /* copy (without stretching) temporary bitmaps to source (restore) */
800 /* image */
801 SelectObject (hdcSrc, hbmTempImage);
802 SelectObject (hdcDst, himlSrc->hbmImage);
803 BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
804 hdcSrc, 0, 0, SRCCOPY);
805 /* mask */
806 SelectObject (hdcSrc, hbmTempMask);
807 SelectObject (hdcDst, himlSrc->hbmMask);
808 BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
809 hdcSrc, 0, 0, SRCCOPY);
811 /* delete temporary bitmaps */
812 DeleteObject (hbmTempMask);
813 DeleteObject (hbmTempImage);
815 else {
816 /* copy image */
817 SelectObject (hdcSrc, himlSrc->hbmImage);
818 if (himlSrc == himlDst)
819 hdcDst = hdcSrc;
820 else
821 SelectObject (hdcDst, himlDst->hbmImage);
822 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
823 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
824 SRCCOPY);
826 /* copy mask */
827 SelectObject (hdcSrc, himlSrc->hbmMask);
828 if (himlSrc == himlDst)
829 hdcDst = hdcSrc;
830 else
831 SelectObject (hdcDst, himlDst->hbmMask);
832 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
833 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
834 SRCCOPY);
837 DeleteDC (hdcSrc);
838 if (himlSrc != himlDst)
839 DeleteDC (hdcDst);
841 return TRUE;
845 /*************************************************************************
846 * ImageList_Create [COMCTL32.44] Creates a new image list.
848 * PARAMS
849 * cx [I] image height
850 * cy [I] image width
851 * flags [I] creation flags
852 * cInitial [I] initial number of images in the image list
853 * cGrow [I] number of images by which image list grows
855 * RETURNS
856 * Success: Handle to the created image list
857 * Failure: NULL
860 HIMAGELIST WINAPI
861 ImageList_Create (INT cx, INT cy, UINT flags,
862 INT cInitial, INT cGrow)
864 HIMAGELIST himl;
865 HDC hdc;
866 INT nCount;
867 HBITMAP hbmTemp;
868 static WORD aBitBlend25[] =
869 {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00};
871 static WORD aBitBlend50[] =
872 {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
874 TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow);
876 himl = (HIMAGELIST)COMCTL32_Alloc (sizeof(struct _IMAGELIST));
877 if (!himl)
878 return NULL;
880 himl->cx = cx;
881 himl->cy = cy;
882 himl->flags = flags;
883 himl->cMaxImage = cInitial + cGrow;
884 himl->cInitial = cInitial;
885 himl->cGrow = cGrow;
886 himl->cCurImage = 0;
887 himl->clrFg = CLR_DEFAULT;
888 himl->clrBk = CLR_NONE;
890 /* initialize overlay mask indices */
891 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
892 himl->nOvlIdx[nCount] = -1;
894 hdc = CreateCompatibleDC (0);
895 himl->uBitsPixel = (UINT)GetDeviceCaps (hdc, BITSPIXEL);
896 DeleteDC (hdc);
898 TRACE("Image: %d Bits per Pixel\n", himl->uBitsPixel);
900 if (himl->cMaxImage > 0) {
901 himl->hbmImage =
902 CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
903 1, himl->uBitsPixel, NULL);
904 if (himl->hbmImage == 0) {
905 ERR("Error creating image bitmap!\n");
906 return NULL;
909 else
910 himl->hbmImage = 0;
912 if ( (himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) {
913 himl->hbmMask = CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
914 1, 1, NULL);
915 if (himl->hbmMask == 0) {
916 ERR("Error creating mask bitmap!\n");
917 if (himl->hbmImage)
918 DeleteObject (himl->hbmImage);
919 return NULL;
922 else
923 himl->hbmMask = 0;
925 /* create blending brushes */
926 hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend25);
927 himl->hbrBlend25 = CreatePatternBrush (hbmTemp);
928 DeleteObject (hbmTemp);
930 hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend50);
931 himl->hbrBlend50 = CreatePatternBrush (hbmTemp);
932 DeleteObject (hbmTemp);
934 return himl;
938 /*************************************************************************
939 * ImageList_Destroy [COMCTL32.45]
941 * Destroys an image list.
943 * PARAMS
944 * himl [I] handle to image list
946 * RETURNS
947 * Success: TRUE
948 * Failure: FALSE
951 BOOL WINAPI
952 ImageList_Destroy (HIMAGELIST himl)
954 if (!himl)
955 return FALSE;
957 /* delete image bitmaps */
958 if (himl->hbmImage)
959 DeleteObject (himl->hbmImage);
960 if (himl->hbmMask)
961 DeleteObject (himl->hbmMask);
963 /* delete blending brushes */
964 if (himl->hbrBlend25)
965 DeleteObject (himl->hbrBlend25);
966 if (himl->hbrBlend50)
967 DeleteObject (himl->hbrBlend50);
969 COMCTL32_Free (himl);
971 return TRUE;
975 /*************************************************************************
976 * ImageList_DragEnter [COMCTL32.46]
978 * Locks window update and displays the drag image at the given position.
980 * PARAMS
981 * hwndLock [I] handle of the window that owns the drag image.
982 * x [I] X position of the drag image.
983 * y [I] Y position of the drag image.
985 * RETURNS
986 * Success: TRUE
987 * Failure: FALSE
989 * NOTES
990 * The position of the drag image is relative to the window, not
991 * the client area.
994 BOOL WINAPI
995 ImageList_DragEnter (HWND hwndLock, INT x, INT y)
997 if (himlInternalDrag == NULL)
998 return FALSE;
1000 if (hwndLock)
1001 hwndInternalDrag = hwndLock;
1002 else
1003 hwndInternalDrag = GetDesktopWindow ();
1005 xInternalPos = x;
1006 yInternalPos = y;
1008 hdcBackBuffer = CreateCompatibleDC (0);
1009 hbmBackBuffer = CreateCompatibleBitmap (hdcBackBuffer,
1010 himlInternalDrag->cx, himlInternalDrag->cy);
1012 ImageList_DragShowNolock (TRUE);
1014 return FALSE;
1018 /*************************************************************************
1019 * ImageList_DragLeave [COMCTL32.47]
1021 * Unlocks window update and hides the drag image.
1023 * PARAMS
1024 * hwndLock [I] handle of the window that owns the drag image.
1026 * RETURNS
1027 * Success: TRUE
1028 * Failure: FALSE
1031 BOOL WINAPI
1032 ImageList_DragLeave (HWND hwndLock)
1034 if (hwndLock)
1035 hwndInternalDrag = hwndLock;
1036 else
1037 hwndInternalDrag = GetDesktopWindow ();
1039 ImageList_DragShowNolock (FALSE);
1041 DeleteDC (hdcBackBuffer);
1042 DeleteObject (hbmBackBuffer);
1044 return TRUE;
1048 /*************************************************************************
1049 * ImageList_DragMove [COMCTL32.48]
1051 * Moves the drag image.
1053 * PARAMS
1054 * x [I] X position of the drag image.
1055 * y [I] Y position of the drag image.
1057 * RETURNS
1058 * Success: TRUE
1059 * Failure: FALSE
1061 * NOTES
1062 * The position of the drag image is relative to the window, not
1063 * the client area.
1066 BOOL WINAPI
1067 ImageList_DragMove (INT x, INT y)
1069 ImageList_DragShowNolock (FALSE);
1071 xInternalPos = x;
1072 yInternalPos = y;
1074 ImageList_DragShowNolock (TRUE);
1076 return FALSE;
1080 /*************************************************************************
1081 * ImageList_DragShowNolock [COMCTL32.49]
1083 * Shows or hides the drag image.
1085 * PARAMS
1086 * bShow [I] TRUE shows the drag image, FALSE hides it.
1088 * RETURNS
1089 * Success: TRUE
1090 * Failure: FALSE
1092 * FIXME
1093 * semi-stub.
1096 BOOL WINAPI
1097 ImageList_DragShowNolock (BOOL bShow)
1099 HDC hdcDrag;
1101 FIXME("semi-stub!\n");
1102 TRACE("bShow=0x%X!\n", bShow);
1104 hdcDrag = GetDCEx (hwndInternalDrag, 0,
1105 DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
1107 if (bShow) {
1108 /* show drag image */
1110 /* save background */
1112 /* draw drag image */
1115 else {
1116 /* hide drag image */
1118 /* restore background */
1122 ReleaseDC (hwndInternalDrag, hdcDrag);
1124 return FALSE;
1128 /*************************************************************************
1129 * ImageList_Draw [COMCTL32.50] Draws an image.
1131 * PARAMS
1132 * himl [I] handle to image list
1133 * i [I] image index
1134 * hdc [I] handle to device context
1135 * x [I] x position
1136 * y [I] y position
1137 * fStyle [I] drawing flags
1139 * RETURNS
1140 * Success: TRUE
1141 * Failure: FALSE
1143 * NOTES
1144 * Calls ImageList_DrawIndirect.
1146 * SEE
1147 * ImageList_DrawIndirect.
1150 BOOL WINAPI
1151 ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc,
1152 INT x, INT y, UINT fStyle)
1154 IMAGELISTDRAWPARAMS imldp;
1156 imldp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
1157 imldp.himl = himl;
1158 imldp.i = i;
1159 imldp.hdcDst = hdc,
1160 imldp.x = x;
1161 imldp.y = y;
1162 imldp.cx = 0;
1163 imldp.cy = 0;
1164 imldp.xBitmap = 0;
1165 imldp.yBitmap = 0;
1166 imldp.rgbBk = CLR_DEFAULT;
1167 imldp.rgbFg = CLR_DEFAULT;
1168 imldp.fStyle = fStyle;
1169 imldp.dwRop = 0;
1171 return ImageList_DrawIndirect (&imldp);
1175 /*************************************************************************
1176 * ImageList_DrawEx [COMCTL32.51]
1178 * Draws an image and allows to use extended drawing features.
1180 * PARAMS
1181 * himl [I] handle to image list
1182 * i [I] image index
1183 * hdc [I] handle to device context
1184 * x [I] X position
1185 * y [I] Y position
1186 * xOffs [I] X offset
1187 * yOffs [I] Y offset
1188 * rgbBk [I] background color
1189 * rgbFg [I] foreground color
1190 * fStyle [I] drawing flags
1192 * RETURNS
1193 * Success: TRUE
1194 * Failure: FALSE
1196 * NOTES
1197 * Calls ImageList_DrawIndirect.
1199 * SEE
1200 * ImageList_DrawIndirect.
1203 BOOL WINAPI
1204 ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y,
1205 INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg,
1206 UINT fStyle)
1208 IMAGELISTDRAWPARAMS imldp;
1210 imldp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
1211 imldp.himl = himl;
1212 imldp.i = i;
1213 imldp.hdcDst = hdc,
1214 imldp.x = x;
1215 imldp.y = y;
1216 imldp.cx = dx;
1217 imldp.cy = dy;
1218 imldp.xBitmap = 0;
1219 imldp.yBitmap = 0;
1220 imldp.rgbBk = rgbBk;
1221 imldp.rgbFg = rgbFg;
1222 imldp.fStyle = fStyle;
1223 imldp.dwRop = 0;
1225 return ImageList_DrawIndirect (&imldp);
1229 /*************************************************************************
1230 * ImageList_DrawIndirect [COMCTL32.52]
1232 * Draws an image using ...
1234 * PARAMS
1235 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
1237 * RETURNS
1238 * Success: TRUE
1239 * Failure: FALSE
1242 BOOL WINAPI
1243 ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
1245 INT cx, cy;
1247 Do some Error Checking
1249 if (pimldp == NULL)
1250 return FALSE;
1251 if (pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS))
1252 return FALSE;
1253 if (pimldp->himl == NULL)
1254 return FALSE;
1255 if ((pimldp->i < 0) || (pimldp->i > pimldp->himl->cCurImage)) {
1256 ERR("%d not within range (max %d)\n",pimldp->i,pimldp->himl->cCurImage);
1257 return FALSE;
1260 Get the Height and Width to display
1262 cx = (pimldp->cx == 0) ? pimldp->himl->cx : pimldp->cx;
1263 cy = (pimldp->cy == 0) ? pimldp->himl->cy : pimldp->cy;
1265 Draw the image
1267 if(pimldp->himl->hbmMask != 0)
1269 IMAGELIST_InternalDrawMask(pimldp, cx, cy);
1271 else
1273 IMAGELIST_InternalDraw(pimldp, cx, cy);
1276 Apply the blend if needed to the Image
1278 if((pimldp->fStyle & ILD_BLEND50)
1279 || (pimldp->fStyle & ILD_BLEND25))
1281 IMAGELIST_InternalDrawBlend(pimldp, cx, cy);
1284 Apply the Overlay if needed
1286 if (pimldp->fStyle & ILD_OVERLAYMASK)
1288 IMAGELIST_InternalDrawOverlay(pimldp, cx, cy);
1291 return TRUE;
1295 /*************************************************************************
1296 * ImageList_Duplicate [COMCTL32.53] Duplicates an image list.
1298 * PARAMS
1299 * himlSrc [I] source image list handle
1301 * RETURNS
1302 * Success: Handle of duplicated image list.
1303 * Failure: NULL
1306 HIMAGELIST WINAPI
1307 ImageList_Duplicate (HIMAGELIST himlSrc)
1309 HIMAGELIST himlDst;
1310 HDC hdcSrc, hdcDst;
1312 if (himlSrc == NULL) {
1313 ERR("Invalid image list handle!\n");
1314 return NULL;
1317 himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
1318 himlSrc->cInitial, himlSrc->cGrow);
1320 if (himlDst)
1322 hdcSrc = CreateCompatibleDC (0);
1323 hdcDst = CreateCompatibleDC (0);
1324 SelectObject (hdcSrc, himlSrc->hbmImage);
1325 SelectObject (hdcDst, himlDst->hbmImage);
1326 BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy,
1327 hdcSrc, 0, 0, SRCCOPY);
1329 if (himlDst->hbmMask)
1331 SelectObject (hdcSrc, himlSrc->hbmMask);
1332 SelectObject (hdcDst, himlDst->hbmMask);
1333 BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx,
1334 himlSrc->cy, hdcSrc, 0, 0, SRCCOPY);
1337 DeleteDC (hdcDst);
1338 DeleteDC (hdcSrc);
1340 himlDst->cCurImage = himlSrc->cCurImage;
1341 himlDst->cMaxImage = himlSrc->cMaxImage;
1343 return himlDst;
1347 /*************************************************************************
1348 * ImageList_EndDrag [COMCTL32.54] Finishes a drag operation.
1350 * Finishes a drag operation.
1352 * PARAMS
1353 * no Parameters
1355 * RETURNS
1356 * Success: TRUE
1357 * Failure: FALSE
1359 * BUGS
1360 * semi-stub.
1363 BOOL WINAPI
1364 ImageList_EndDrag (void)
1366 FIXME("semi-stub!\n");
1368 if (himlInternalDrag)
1371 ImageList_Destroy (himlInternalDrag);
1372 himlInternalDrag = NULL;
1374 nInternalDragHotspotX = 0;
1375 nInternalDragHotspotY = 0;
1379 return TRUE;
1383 /*************************************************************************
1384 * ImageList_GetBkColor [COMCTL32.55]
1386 * Returns the background color of an image list.
1388 * PARAMS
1389 * himl [I] Image list handle.
1391 * RETURNS
1392 * Success: background color
1393 * Failure: CLR_NONE
1396 COLORREF WINAPI
1397 ImageList_GetBkColor (HIMAGELIST himl)
1399 if (himl == NULL)
1400 return CLR_NONE;
1402 return himl->clrBk;
1406 /*************************************************************************
1407 * ImageList_GetDragImage [COMCTL32.56]
1409 * Returns the handle to the internal drag image list.
1411 * PARAMS
1412 * ppt [O] Pointer to the drag position. Can be NULL.
1413 * pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
1415 * RETURNS
1416 * Success: Handle of the drag image list.
1417 * Failure: NULL.
1419 * BUGS
1420 * semi-stub.
1423 HIMAGELIST WINAPI
1424 ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot)
1426 FIXME("semi-stub!\n");
1428 if (himlInternalDrag)
1429 return (himlInternalDrag);
1431 return NULL;
1435 /*************************************************************************
1436 * ImageList_GetIcon [COMCTL32.57]
1438 * Creates an icon from a masked image of an image list.
1440 * PARAMS
1441 * himl [I] handle to image list
1442 * i [I] image index
1443 * flags [I] drawing style flags
1445 * RETURNS
1446 * Success: icon handle
1447 * Failure: NULL
1450 HICON WINAPI
1451 ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle)
1453 ICONINFO ii;
1454 HICON hIcon;
1455 HBITMAP hOldSrcBitmap,hOldDstBitmap;
1456 HDC hdcSrc, hdcDst;
1458 if ((himl == NULL) || (i < 0) || (i >= himl->cCurImage)) {
1459 FIXME("(%p,%d,%x), params out of range!\n",himl,i,fStyle);
1460 return 0;
1463 hdcSrc = CreateCompatibleDC(0);
1464 hdcDst = CreateCompatibleDC(0);
1466 ii.fIcon = TRUE;
1467 ii.hbmMask = CreateCompatibleBitmap (hdcDst, himl->cx, himl->cy);
1469 /* draw mask*/
1470 hOldDstBitmap = (HBITMAP)SelectObject (hdcDst, ii.hbmMask);
1471 if (himl->hbmMask) {
1472 SelectObject (hdcSrc, himl->hbmMask);
1473 BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1474 hdcSrc, i * himl->cx, 0, SRCCOPY);
1476 else
1477 PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS);
1479 /* draw image*/
1480 hOldSrcBitmap = (HBITMAP)SelectObject (hdcSrc, himl->hbmImage);
1481 ii.hbmColor = CreateCompatibleBitmap (hdcSrc, himl->cx, himl->cy);
1482 SelectObject (hdcDst, ii.hbmColor);
1483 BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1484 hdcSrc, i * himl->cx, 0, SRCCOPY);
1487 * CreateIconIndirect requires us to deselect the bitmaps from
1488 * the DCs before calling
1490 SelectObject(hdcSrc, hOldSrcBitmap);
1491 SelectObject(hdcDst, hOldDstBitmap);
1493 hIcon = CreateIconIndirect (&ii);
1495 DeleteDC (hdcSrc);
1496 DeleteDC (hdcDst);
1497 DeleteObject (ii.hbmMask);
1498 DeleteObject (ii.hbmColor);
1500 return hIcon;
1504 /*************************************************************************
1505 * ImageList_GetIconSize [COMCTL32.58]
1507 * Retrieves the size of an image in an image list.
1509 * PARAMS
1510 * himl [I] handle to image list
1511 * cx [O] pointer to the image width.
1512 * cy [O] pointer to the image height.
1514 * RETURNS
1515 * Success: TRUE
1516 * Failure: FALSE
1518 * NOTES
1519 * All images in an image list have the same size.
1522 BOOL WINAPI
1523 ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy)
1525 if (himl == NULL)
1526 return FALSE;
1527 if ((himl->cx <= 0) || (himl->cy <= 0))
1528 return FALSE;
1530 if (cx)
1531 *cx = himl->cx;
1532 if (cy)
1533 *cy = himl->cy;
1535 return TRUE;
1539 /*************************************************************************
1540 * ImageList_GetImageCount [COMCTL32.59]
1542 * Returns the number of images in an image list.
1544 * PARAMS
1545 * himl [I] handle to image list
1547 * RETURNS
1548 * Success: Number of images.
1549 * Failure: 0
1552 INT WINAPI
1553 ImageList_GetImageCount (HIMAGELIST himl)
1555 if (himl == NULL)
1556 return 0;
1558 return himl->cCurImage;
1562 /*************************************************************************
1563 * ImageList_GetImageInfo [COMCTL32.60]
1565 * Returns information about an image in an image list.
1567 * PARAMS
1568 * himl [I] handle to image list
1569 * i [I] image index
1570 * pImageInfo [O] pointer to the image information
1572 * RETURNS
1573 * Success: TRUE
1574 * Failure: FALSE
1577 BOOL WINAPI
1578 ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
1580 if ((himl == NULL) || (pImageInfo == NULL))
1581 return FALSE;
1582 if ((i < 0) || (i >= himl->cCurImage))
1583 return FALSE;
1585 pImageInfo->hbmImage = himl->hbmImage;
1586 pImageInfo->hbmMask = himl->hbmMask;
1588 pImageInfo->rcImage.top = 0;
1589 pImageInfo->rcImage.bottom = himl->cy;
1590 pImageInfo->rcImage.left = i * himl->cx;
1591 pImageInfo->rcImage.right = (i+1) * himl->cx;
1593 return TRUE;
1597 /*************************************************************************
1598 * ImageList_GetImageRect [COMCTL32.61]
1600 * Retrieves the rectangle of the specified image in an image list.
1602 * PARAMS
1603 * himl [I] handle to image list
1604 * i [I] image index
1605 * lpRect [O] pointer to the image rectangle
1607 * RETURNS
1608 * Success: TRUE
1609 * Failure: FALSE
1611 * NOTES
1612 * This is an UNDOCUMENTED function!!!
1615 BOOL WINAPI
1616 ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect)
1618 if ((himl == NULL) || (lpRect == NULL))
1619 return FALSE;
1620 if ((i < 0) || (i >= himl->cCurImage))
1621 return FALSE;
1623 lpRect->left = i * himl->cx;
1624 lpRect->top = 0;
1625 lpRect->right = lpRect->left + himl->cx;
1626 lpRect->bottom = himl->cy;
1628 return TRUE;
1632 /*************************************************************************
1633 * ImageList_LoadImageA [COMCTL32.63][COMCTL32.62]
1635 * Creates an image list from a bitmap, icon or cursor.
1637 * PARAMS
1638 * hi [I] instance handle
1639 * lpbmp [I] name or id of the image
1640 * cx [I] width of each image
1641 * cGrow [I] number of images to expand
1642 * clrMask [I] mask color
1643 * uType [I] type of image to load
1644 * uFlags [I] loading flags
1646 * RETURNS
1647 * Success: handle to the loaded image list
1648 * Failure: NULL
1650 * SEE
1651 * LoadImage ()
1654 HIMAGELIST WINAPI
1655 ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx, INT cGrow,
1656 COLORREF clrMask, UINT uType, UINT uFlags)
1658 HIMAGELIST himl = NULL;
1659 HANDLE handle;
1660 INT nImageCount;
1662 handle = LoadImageA (hi, lpbmp, uType, 0, 0, uFlags);
1663 if (!handle) {
1664 ERR("Error loading image!\n");
1665 return NULL;
1668 if (uType == IMAGE_BITMAP) {
1669 BITMAP bmp;
1670 GetObjectA (handle, sizeof(BITMAP), &bmp);
1672 /* To match windows behavior, if cx is set to zero and
1673 the flag DI_DEFAULTSIZE is specified, cx becomes the
1674 system metric value for icons. If the flag is not specified
1675 the function sets the size to the height of the bitmap */
1676 if (cx == 0)
1678 if (uFlags & DI_DEFAULTSIZE)
1679 cx = GetSystemMetrics (SM_CXICON);
1680 else
1681 cx = bmp.bmHeight;
1684 nImageCount = bmp.bmWidth / cx;
1686 himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1687 nImageCount, cGrow);
1688 ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1690 else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1691 ICONINFO ii;
1692 BITMAP bmp;
1694 GetIconInfo (handle, &ii);
1695 GetObjectA (ii.hbmColor, sizeof(BITMAP), (LPVOID)&bmp);
1696 himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1697 ILC_MASK | ILC_COLOR, 1, cGrow);
1698 ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1699 DeleteObject (ii.hbmColor);
1700 DeleteObject (ii.hbmMask);
1703 DeleteObject (handle);
1705 return himl;
1709 /*************************************************************************
1710 * ImageList_LoadImageW [COMCTL32.64]
1712 * Creates an image list from a bitmap, icon or cursor.
1714 * PARAMS
1715 * hi [I] instance handle
1716 * lpbmp [I] name or id of the image
1717 * cx [I] width of each image
1718 * cGrow [I] number of images to expand
1719 * clrMask [I] mask color
1720 * uType [I] type of image to load
1721 * uFlags [I] loading flags
1723 * RETURNS
1724 * Success: handle to the loaded image list
1725 * Failure: NULL
1727 * SEE
1728 * LoadImage ()
1731 HIMAGELIST WINAPI
1732 ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow,
1733 COLORREF clrMask, UINT uType, UINT uFlags)
1735 HIMAGELIST himl = NULL;
1736 HANDLE handle;
1737 INT nImageCount;
1739 handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags);
1740 if (!handle) {
1741 ERR("Error loading image!\n");
1742 return NULL;
1745 if (uType == IMAGE_BITMAP) {
1746 BITMAP bmp;
1747 GetObjectA (handle, sizeof(BITMAP), &bmp);
1748 nImageCount = bmp.bmWidth / cx;
1750 himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1751 nImageCount, cGrow);
1752 ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1754 else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1755 ICONINFO ii;
1756 BITMAP bmp;
1758 GetIconInfo (handle, &ii);
1759 GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
1760 himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1761 ILC_MASK | ILC_COLOR, 1, cGrow);
1762 ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1763 DeleteObject (ii.hbmColor);
1764 DeleteObject (ii.hbmMask);
1767 DeleteObject (handle);
1769 return himl;
1773 /*************************************************************************
1774 * ImageList_Merge [COMCTL32.65]
1776 * Creates a new image list that contains a merged image from the specified
1777 * images of both source image lists.
1779 * PARAMS
1780 * himl1 [I] handle to first image list
1781 * i1 [I] first image index
1782 * himl2 [I] handle to second image list
1783 * i2 [I] second image index
1784 * dx [I] X offset of the second image relative to the first.
1785 * dy [I] Y offset of the second image relative to the first.
1787 * RETURNS
1788 * Success: handle of the merged image list.
1789 * Failure: NULL
1792 HIMAGELIST WINAPI
1793 ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
1794 INT dx, INT dy)
1796 HIMAGELIST himlDst = NULL;
1797 HDC hdcSrcImage, hdcDstImage;
1798 INT cxDst, cyDst;
1799 INT xOff1, yOff1, xOff2, yOff2;
1800 INT nX1, nX2;
1802 if ((himl1 == NULL) || (himl2 == NULL))
1803 return NULL;
1805 /* check indices */
1806 if ((i1 < 0) || (i1 >= himl1->cCurImage)) {
1807 ERR("Index 1 out of range! %d\n", i1);
1808 return NULL;
1811 if ((i2 < 0) || (i2 >= himl2->cCurImage)) {
1812 ERR("Index 2 out of range! %d\n", i2);
1813 return NULL;
1816 if (dx > 0) {
1817 cxDst = _MAX (himl1->cx, dx + himl2->cx);
1818 xOff1 = 0;
1819 xOff2 = dx;
1821 else if (dx < 0) {
1822 cxDst = _MAX (himl2->cx, himl1->cx - dx);
1823 xOff1 = -dx;
1824 xOff2 = 0;
1826 else {
1827 cxDst = _MAX (himl1->cx, himl2->cx);
1828 xOff1 = 0;
1829 xOff2 = 0;
1832 if (dy > 0) {
1833 cyDst = _MAX (himl1->cy, dy + himl2->cy);
1834 yOff1 = 0;
1835 yOff2 = dy;
1837 else if (dy < 0) {
1838 cyDst = _MAX (himl2->cy, himl1->cy - dy);
1839 yOff1 = -dy;
1840 yOff2 = 0;
1842 else {
1843 cyDst = _MAX (himl1->cy, himl2->cy);
1844 yOff1 = 0;
1845 yOff2 = 0;
1848 himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
1850 if (himlDst) {
1851 hdcSrcImage = CreateCompatibleDC (0);
1852 hdcDstImage = CreateCompatibleDC (0);
1853 nX1 = i1 * himl1->cx;
1854 nX2 = i2 * himl2->cx;
1856 /* copy image */
1857 SelectObject (hdcSrcImage, himl1->hbmImage);
1858 SelectObject (hdcDstImage, himlDst->hbmImage);
1859 BitBlt (hdcDstImage, 0, 0, cxDst, cyDst,
1860 hdcSrcImage, 0, 0, BLACKNESS);
1861 BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy,
1862 hdcSrcImage, nX1, 0, SRCCOPY);
1864 SelectObject (hdcSrcImage, himl2->hbmMask);
1865 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1866 hdcSrcImage, nX2, 0, SRCAND);
1868 SelectObject (hdcSrcImage, himl2->hbmImage);
1869 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1870 hdcSrcImage, nX2, 0, SRCPAINT);
1872 /* copy mask */
1873 SelectObject (hdcSrcImage, himl1->hbmMask);
1874 SelectObject (hdcDstImage, himlDst->hbmMask);
1875 BitBlt (hdcDstImage, 0, 0, cxDst, cyDst,
1876 hdcSrcImage, 0, 0, WHITENESS);
1877 BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy,
1878 hdcSrcImage, nX1, 0, SRCCOPY);
1880 SelectObject (hdcSrcImage, himl2->hbmMask);
1881 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1882 hdcSrcImage, nX2, 0, SRCAND);
1884 DeleteDC (hdcSrcImage);
1885 DeleteDC (hdcDstImage);
1888 return himlDst;
1892 /* helper for _read_bitmap currently unused */
1893 #if 0
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;
1902 #endif
1904 /* helper for ImageList_Read, see comments below */
1905 static HBITMAP _read_bitmap(LPSTREAM pstm,int ilcFlag,int cx,int cy) {
1906 HDC xdc = 0;
1907 BITMAPFILEHEADER bmfh;
1908 BITMAPINFOHEADER bmih;
1909 int bitsperpixel,palspace,longsperline,width,height;
1910 LPBITMAPINFOHEADER bmihc = NULL;
1911 int result = 0;
1912 HBITMAP hbitmap = 0;
1913 LPBYTE bits = NULL,nbits = NULL;
1914 int nbytesperline,bytesperline;
1916 if (!SUCCEEDED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL)) ||
1917 (bmfh.bfType != (('M'<<8)|'B')) ||
1918 !SUCCEEDED(IStream_Read ( pstm, &bmih, sizeof(bmih), NULL)) ||
1919 (bmih.biSize != sizeof(bmih))
1921 return 0;
1923 bitsperpixel = bmih.biPlanes * bmih.biBitCount;
1924 if (bitsperpixel<=8)
1925 palspace = (1<<bitsperpixel)*sizeof(RGBQUAD);
1926 else
1927 palspace = 0;
1928 width = bmih.biWidth;
1929 height = bmih.biHeight;
1930 bmihc = (LPBITMAPINFOHEADER)LocalAlloc(LMEM_ZEROINIT,sizeof(bmih)+palspace);
1931 memcpy(bmihc,&bmih,sizeof(bmih));
1932 longsperline = ((width*bitsperpixel+31)&~0x1f)>>5;
1933 bmihc->biSizeImage = (longsperline*height)<<2;
1935 /* read the palette right after the end of the bitmapinfoheader */
1936 if (palspace)
1937 if (!SUCCEEDED(IStream_Read ( pstm, bmihc+1, palspace, NULL)))
1938 goto ret1;
1940 xdc = GetDC(0);
1941 #if 0 /* Magic for NxM -> 1x(N*M) not implemented for DIB Sections */
1942 if ((bitsperpixel>1) &&
1943 ((ilcFlag!=ILC_COLORDDB) && (!ilcFlag || may_use_dibsection(xdc)))
1945 hbitmap = CreateDIBSection(xdc,(BITMAPINFO*)bmihc,0,(LPVOID*)&bits,0,0);
1946 if (!hbitmap)
1947 goto ret1;
1948 if (!SUCCEEDED(IStream_Read( pstm, bits, bmihc->biSizeImage, NULL)))
1949 goto ret1;
1950 result = 1;
1951 } else
1952 #endif
1954 int i,nwidth,nheight;
1956 nwidth = width*(height/cy);
1957 nheight = cy;
1959 if (bitsperpixel==1)
1960 hbitmap = CreateBitmap(nwidth,nheight,1,1,NULL);
1961 else
1962 hbitmap = CreateCompatibleBitmap(xdc,nwidth,nheight);
1964 /* Might be a bit excessive memory use here */
1965 bits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage);
1966 nbits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage);
1967 if (!SUCCEEDED(IStream_Read ( pstm, bits, bmihc->biSizeImage, NULL)))
1968 goto ret1;
1970 /* Copy the NxM bitmap into a 1x(N*M) bitmap we need, linewise */
1971 /* Do not forget that windows bitmaps are bottom->top */
1972 bytesperline = longsperline*4;
1973 nbytesperline = (height/cy)*bytesperline;
1974 for (i=0;i<height;i++) {
1975 memcpy(
1976 nbits+((height-1-i)%cy)*nbytesperline+(i/cy)*bytesperline,
1977 bits+bytesperline*(height-1-i),
1978 bytesperline
1981 bmihc->biWidth = nwidth;
1982 bmihc->biHeight = nheight;
1983 if (!SetDIBits(xdc,hbitmap,0,nheight,nbits,(BITMAPINFO*)bmihc,0))
1984 goto ret1;
1985 LocalFree((HLOCAL)nbits);
1986 LocalFree((HLOCAL)bits);
1987 result = 1;
1989 ret1:
1990 if (xdc) ReleaseDC(0,xdc);
1991 if (bmihc) LocalFree((HLOCAL)bmihc);
1992 if (!result) {
1993 if (hbitmap) {
1994 DeleteObject(hbitmap);
1995 hbitmap = 0;
1998 return hbitmap;
2001 /*************************************************************************
2002 * ImageList_Read [COMCTL32.66]
2004 * Reads an image list from a stream.
2006 * PARAMS
2007 * pstm [I] pointer to a stream
2009 * RETURNS
2010 * Success: handle to image list
2011 * Failure: NULL
2013 * The format is like this:
2014 * ILHEAD ilheadstruct;
2016 * for the color image part:
2017 * BITMAPFILEHEADER bmfh;
2018 * BITMAPINFOHEADER bmih;
2019 * only if it has a palette:
2020 * RGBQUAD rgbs[nr_of_paletted_colors];
2022 * BYTE colorbits[imagesize];
2024 * the following only if the ILC_MASK bit is set in ILHEAD.ilFlags:
2025 * BITMAPFILEHEADER bmfh_mask;
2026 * BITMAPINFOHEADER bmih_mask;
2027 * only if it has a palette (it usually does not):
2028 * RGBQUAD rgbs[nr_of_paletted_colors];
2030 * BYTE maskbits[imagesize];
2032 * CAVEAT: Those images are within a NxM bitmap, not the 1xN we expect.
2033 * _read_bitmap needs to convert them.
2035 HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
2037 ILHEAD ilHead;
2038 HIMAGELIST himl;
2039 HBITMAP hbmColor=0,hbmMask=0;
2040 int i;
2042 if (!SUCCEEDED(IStream_Read (pstm, &ilHead, sizeof(ILHEAD), NULL)))
2043 return NULL;
2044 if (ilHead.usMagic != (('L' << 8) | 'I'))
2045 return NULL;
2046 if (ilHead.usVersion != 0x101) /* probably version? */
2047 return NULL;
2049 #if 0
2050 FIXME(" ilHead.cCurImage = %d\n",ilHead.cCurImage);
2051 FIXME(" ilHead.cMaxImage = %d\n",ilHead.cMaxImage);
2052 FIXME(" ilHead.cGrow = %d\n",ilHead.cGrow);
2053 FIXME(" ilHead.cx = %d\n",ilHead.cx);
2054 FIXME(" ilHead.cy = %d\n",ilHead.cy);
2055 FIXME(" ilHead.flags = %x\n",ilHead.flags);
2056 FIXME(" ilHead.ovls[0] = %d\n",ilHead.ovls[0]);
2057 FIXME(" ilHead.ovls[1] = %d\n",ilHead.ovls[1]);
2058 FIXME(" ilHead.ovls[2] = %d\n",ilHead.ovls[2]);
2059 FIXME(" ilHead.ovls[3] = %d\n",ilHead.ovls[3]);
2060 #endif
2062 hbmColor = _read_bitmap(pstm,ilHead.flags & ~ILC_MASK,ilHead.cx,ilHead.cy);
2063 if (!hbmColor)
2064 return NULL;
2065 if (ilHead.flags & ILC_MASK) {
2066 hbmMask = _read_bitmap(pstm,0,ilHead.cx,ilHead.cy);
2067 if (!hbmMask) {
2068 DeleteObject(hbmColor);
2069 return NULL;
2073 himl = ImageList_Create (
2074 ilHead.cx,
2075 ilHead.cy,
2076 ilHead.flags,
2077 1, /* initial */
2078 ilHead.cGrow
2080 if (!himl) {
2081 DeleteObject(hbmColor);
2082 DeleteObject(hbmMask);
2083 return NULL;
2085 himl->hbmImage = hbmColor;
2086 himl->hbmMask = hbmMask;
2087 himl->cCurImage = ilHead.cCurImage;
2088 himl->cMaxImage = ilHead.cMaxImage;
2090 ImageList_SetBkColor(himl,ilHead.bkcolor);
2091 for (i=0;i<4;i++)
2092 ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1);
2093 return himl;
2097 /*************************************************************************
2098 * ImageList_Remove [COMCTL32.67] Removes an image from an image list
2100 * PARAMS
2101 * himl [I] image list handle
2102 * i [I] image index
2104 * RETURNS
2105 * Success: TRUE
2106 * Failure: FALSE
2109 BOOL WINAPI
2110 ImageList_Remove (HIMAGELIST himl, INT i)
2112 HBITMAP hbmNewImage, hbmNewMask;
2113 HDC hdcSrc, hdcDst;
2114 INT cxNew, nCount;
2116 if ((i < -1) || (i >= himl->cCurImage)) {
2117 ERR("index out of range! %d\n", i);
2118 return FALSE;
2121 if (himl->cCurImage == 0) {
2122 ERR("image list is already empty!\n");
2123 return FALSE;
2126 if (i == -1) {
2127 /* remove all */
2128 TRACE("remove all!\n");
2130 himl->cMaxImage = himl->cInitial + himl->cGrow;
2131 himl->cCurImage = 0;
2132 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2133 himl->nOvlIdx[nCount] = -1;
2135 DeleteObject (himl->hbmImage);
2136 himl->hbmImage =
2137 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2138 1, himl->uBitsPixel, NULL);
2140 if (himl->hbmMask) {
2141 DeleteObject (himl->hbmMask);
2142 himl->hbmMask =
2143 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2144 1, 1, NULL);
2147 else {
2148 /* delete one image */
2149 TRACE("Remove single image! %d\n", i);
2151 /* create new bitmap(s) */
2152 cxNew = (himl->cCurImage + himl->cGrow - 1) * himl->cx;
2154 TRACE(" - Number of images: %d / %d (Old/New)\n",
2155 himl->cCurImage, himl->cCurImage - 1);
2156 TRACE(" - Max. number of images: %d / %d (Old/New)\n",
2157 himl->cMaxImage, himl->cCurImage + himl->cGrow - 1);
2159 hbmNewImage =
2160 CreateBitmap (cxNew, himl->cy, 1, himl->uBitsPixel, NULL);
2162 if (himl->hbmMask)
2163 hbmNewMask = CreateBitmap (cxNew, himl->cy, 1, 1, NULL);
2164 else
2165 hbmNewMask = 0; /* Just to keep compiler happy! */
2167 hdcSrc = CreateCompatibleDC (0);
2168 hdcDst = CreateCompatibleDC (0);
2170 /* copy all images and masks prior to the "removed" image */
2171 if (i > 0) {
2172 TRACE("Pre image copy: Copy %d images\n", i);
2174 SelectObject (hdcSrc, himl->hbmImage);
2175 SelectObject (hdcDst, hbmNewImage);
2176 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2177 hdcSrc, 0, 0, SRCCOPY);
2179 if (himl->hbmMask) {
2180 SelectObject (hdcSrc, himl->hbmMask);
2181 SelectObject (hdcDst, hbmNewMask);
2182 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2183 hdcSrc, 0, 0, SRCCOPY);
2187 /* copy all images and masks behind the removed image */
2188 if (i < himl->cCurImage - 1) {
2189 TRACE("Post image copy!\n");
2190 SelectObject (hdcSrc, himl->hbmImage);
2191 SelectObject (hdcDst, hbmNewImage);
2192 BitBlt (hdcDst, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx,
2193 himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2195 if (himl->hbmMask) {
2196 SelectObject (hdcSrc, himl->hbmMask);
2197 SelectObject (hdcDst, hbmNewMask);
2198 BitBlt (hdcDst, i * himl->cx, 0,
2199 (himl->cCurImage - i - 1) * himl->cx,
2200 himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2204 DeleteDC (hdcSrc);
2205 DeleteDC (hdcDst);
2207 /* delete old images and insert new ones */
2208 DeleteObject (himl->hbmImage);
2209 himl->hbmImage = hbmNewImage;
2210 if (himl->hbmMask) {
2211 DeleteObject (himl->hbmMask);
2212 himl->hbmMask = hbmNewMask;
2215 himl->cCurImage--;
2216 himl->cMaxImage = himl->cCurImage + himl->cGrow;
2219 return TRUE;
2223 /*************************************************************************
2224 * ImageList_Replace [COMCTL32.68]
2226 * Replaces an image in an image list with a new image.
2228 * PARAMS
2229 * himl [I] handle to image list
2230 * i [I] image index
2231 * hbmImage [I] handle to image bitmap
2232 * hbmMask [I] handle to mask bitmap. Can be NULL.
2234 * RETURNS
2235 * Success: TRUE
2236 * Failure: FALSE
2239 BOOL WINAPI
2240 ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage,
2241 HBITMAP hbmMask)
2243 HDC hdcImageList, hdcImage;
2244 BITMAP bmp;
2246 if (himl == NULL) {
2247 ERR("Invalid image list handle!\n");
2248 return FALSE;
2251 if ((i >= himl->cCurImage) || (i < 0)) {
2252 ERR("Invalid image index!\n");
2253 return FALSE;
2256 hdcImageList = CreateCompatibleDC (0);
2257 hdcImage = CreateCompatibleDC (0);
2258 GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
2260 /* Replace Image */
2261 SelectObject (hdcImageList, himl->hbmImage);
2262 SelectObject (hdcImage, hbmImage);
2264 StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2265 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2267 if (himl->hbmMask)
2269 /* Replace Mask */
2270 SelectObject (hdcImageList, himl->hbmMask);
2271 SelectObject (hdcImage, hbmMask);
2273 StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2274 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2277 /* Remove the background from the image
2279 SelectObject (hdcImageList, himl->hbmImage);
2280 StretchBlt (hdcImageList,
2281 i*himl->cx, 0, himl->cx, himl->cy,
2282 hdcImage,
2283 0, 0, bmp.bmWidth, bmp.bmHeight,
2284 0x220326); /* NOTSRCAND */
2287 DeleteDC (hdcImage);
2288 DeleteDC (hdcImageList);
2290 return TRUE;
2294 /*************************************************************************
2295 * ImageList_ReplaceIcon [COMCTL32.69]
2297 * Replaces an image in an image list using an icon.
2299 * PARAMS
2300 * himl [I] handle to image list
2301 * i [I] image index
2302 * hIcon [I] handle to icon
2304 * RETURNS
2305 * Success: index of the replaced image
2306 * Failure: -1
2309 INT WINAPI
2310 ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon)
2312 HDC hdcImageList, hdcImage;
2313 INT nIndex;
2314 HICON hBestFitIcon;
2315 HBITMAP hbmOldSrc, hbmOldDst;
2316 ICONINFO ii;
2317 BITMAP bmp;
2319 TRACE("(0x%lx 0x%x 0x%x)\n", (DWORD)himl, i, hIcon);
2321 if (himl == NULL)
2322 return -1;
2323 if ((i >= himl->cCurImage) || (i < -1))
2324 return -1;
2326 hBestFitIcon = CopyImage(
2327 hIcon, IMAGE_ICON,
2328 himl->cx, himl->cy,
2329 LR_COPYFROMRESOURCE);
2331 GetIconInfo (hBestFitIcon, &ii);
2332 if (ii.hbmMask == 0)
2333 ERR("no mask!\n");
2334 if (ii.hbmColor == 0)
2335 ERR("no color!\n");
2336 GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
2338 if (i == -1) {
2339 if (himl->cCurImage + 1 >= himl->cMaxImage)
2340 IMAGELIST_InternalExpandBitmaps (himl, 1);
2342 nIndex = himl->cCurImage;
2343 himl->cCurImage++;
2345 else
2346 nIndex = i;
2348 hdcImageList = CreateCompatibleDC (0);
2349 TRACE("hdcImageList=0x%x!\n", hdcImageList);
2350 if (hdcImageList == 0)
2351 ERR("invalid hdcImageList!\n");
2353 hdcImage = CreateCompatibleDC (0);
2354 TRACE("hdcImage=0x%x!\n", hdcImage);
2355 if (hdcImage == 0)
2356 ERR("invalid hdcImage!\n");
2358 hbmOldDst = SelectObject (hdcImageList, himl->hbmImage);
2359 SetTextColor( hdcImageList, RGB(0,0,0));
2360 SetBkColor( hdcImageList, RGB(255,255,255));
2361 hbmOldSrc = SelectObject (hdcImage, ii.hbmColor);
2362 StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2363 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2365 if (himl->hbmMask) {
2366 SelectObject (hdcImageList, himl->hbmMask);
2367 SelectObject (hdcImage, ii.hbmMask);
2368 StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2369 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2372 SelectObject (hdcImage, hbmOldSrc);
2373 SelectObject (hdcImageList, hbmOldDst);
2375 if(hBestFitIcon)
2376 DestroyIcon(hBestFitIcon);
2377 if (hdcImageList)
2378 DeleteDC (hdcImageList);
2379 if (hdcImage)
2380 DeleteDC (hdcImage);
2381 if (ii.hbmColor)
2382 DeleteObject (ii.hbmColor);
2383 if (ii.hbmMask)
2384 DeleteObject (ii.hbmMask);
2386 return nIndex;
2390 /*************************************************************************
2391 * ImageList_SetBkColor [COMCTL32.70]
2393 * Sets the background color of an image list.
2395 * PARAMS
2396 * himl [I] handle to image list
2397 * clrBk [I] background color
2399 * RETURNS
2400 * Success: previous background color
2401 * Failure: CLR_NONE
2404 COLORREF WINAPI
2405 ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
2407 COLORREF clrOldBk;
2409 if (himl == NULL)
2410 return CLR_NONE;
2412 clrOldBk = himl->clrBk;
2413 himl->clrBk = clrBk;
2414 return clrOldBk;
2418 /*************************************************************************
2419 * ImageList_SetDragCursorImage [COMCTL32.75]
2421 * Combines the specified image with the current drag image
2423 * PARAMS
2424 * himlDrag [I] handle to drag image list
2425 * iDrag [I] drag image index
2426 * dxHotspot [I] X position of the hot spot
2427 * dyHotspot [I] Y position of the hot spot
2429 * RETURNS
2430 * Success: TRUE
2431 * Failure: FALSE
2433 * BUGS
2434 * semi-stub.
2437 BOOL WINAPI
2438 ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag,
2439 INT dxHotspot, INT dyHotspot)
2441 HIMAGELIST himlTemp;
2443 FIXME("semi-stub!\n");
2445 if (himlInternalDrag == NULL)
2446 return FALSE;
2448 TRACE(" dxH=%d dyH=%d nX=%d nY=%d\n",
2449 dxHotspot, dyHotspot, nInternalDragHotspotX, nInternalDragHotspotY);
2451 himlTemp = ImageList_Merge (himlInternalDrag, 0, himlDrag, iDrag,
2452 dxHotspot, dyHotspot);
2454 ImageList_Destroy (himlInternalDrag);
2455 himlInternalDrag = himlTemp;
2457 nInternalDragHotspotX = dxHotspot;
2458 nInternalDragHotspotY = dyHotspot;
2460 return FALSE;
2464 /*************************************************************************
2465 * ImageList_SetFilter [COMCTL32.76]
2467 * Sets a filter (or does something completely different)!!???
2469 * PARAMS
2470 * himl [I] handle to image list
2471 * i [I] ???
2472 * dwFilter [I] ???
2474 * RETURNS
2475 * Success: TRUE ???
2476 * Failure: FALSE ???
2478 * BUGS
2479 * This is an UNDOCUMENTED function!!!!
2480 * empty stub.
2483 BOOL WINAPI
2484 ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter)
2486 FIXME("(%p 0x%x 0x%lx):empty stub!\n",
2487 himl, i, dwFilter);
2489 return FALSE;
2493 /*************************************************************************
2494 * ImageList_SetIconSize [COMCTL32.77]
2496 * Sets the image size of the bitmap and deletes all images.
2498 * PARAMS
2499 * himl [I] handle to image list
2500 * cx [I] image width
2501 * cy [I] image height
2503 * RETURNS
2504 * Success: TRUE
2505 * Failure: FALSE
2508 BOOL WINAPI
2509 ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy)
2511 INT nCount;
2513 if (!himl)
2514 return FALSE;
2516 /* remove all images*/
2517 himl->cMaxImage = himl->cInitial + himl->cGrow;
2518 himl->cCurImage = 0;
2519 himl->cx = cx;
2520 himl->cy = cy;
2522 /* initialize overlay mask indices */
2523 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2524 himl->nOvlIdx[nCount] = -1;
2526 DeleteObject (himl->hbmImage);
2527 himl->hbmImage =
2528 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2529 1, himl->uBitsPixel, NULL);
2531 if (himl->hbmMask) {
2532 DeleteObject (himl->hbmMask);
2533 himl->hbmMask =
2534 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2535 1, 1, NULL);
2538 return TRUE;
2542 /*************************************************************************
2543 * ImageList_SetImageCount [COMCTL32.78]
2545 * Resizes an image list to the specified number of images.
2547 * PARAMS
2548 * himl [I] handle to image list
2549 * iImageCount [I] number of images in the image list
2551 * RETURNS
2552 * Success: TRUE
2553 * Failure: FALSE
2556 BOOL WINAPI
2557 ImageList_SetImageCount (HIMAGELIST himl, INT iImageCount)
2559 HDC hdcImageList, hdcBitmap;
2560 HBITMAP hbmNewBitmap;
2561 INT nNewCount, nCopyCount;
2563 if (!himl)
2564 return FALSE;
2565 if (himl->cCurImage >= iImageCount)
2566 return FALSE;
2567 if (himl->cMaxImage > iImageCount)
2568 return TRUE;
2570 nNewCount = iImageCount + himl->cGrow;
2571 nCopyCount = _MIN(himl->cCurImage, iImageCount);
2573 hdcImageList = CreateCompatibleDC (0);
2574 hdcBitmap = CreateCompatibleDC (0);
2576 hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2577 1, himl->uBitsPixel, NULL);
2578 if (hbmNewBitmap != 0)
2580 SelectObject (hdcImageList, himl->hbmImage);
2581 SelectObject (hdcBitmap, hbmNewBitmap);
2583 /* copy images */
2584 BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2585 hdcImageList, 0, 0, SRCCOPY);
2586 #if 0
2587 /* delete 'empty' image space */
2588 SetBkColor (hdcBitmap, RGB(255, 255, 255));
2589 SetTextColor (hdcBitmap, RGB(0, 0, 0));
2590 PatBlt (hdcBitmap, nCopyCount * himl->cx, 0,
2591 (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2592 #endif
2593 DeleteObject (himl->hbmImage);
2594 himl->hbmImage = hbmNewBitmap;
2596 else
2597 ERR("Could not create new image bitmap !\n");
2599 if (himl->hbmMask)
2601 hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2602 1, 1, NULL);
2603 if (hbmNewBitmap != 0)
2605 SelectObject (hdcImageList, himl->hbmMask);
2606 SelectObject (hdcBitmap, hbmNewBitmap);
2608 /* copy images */
2609 BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2610 hdcImageList, 0, 0, SRCCOPY);
2611 #if 0
2612 /* delete 'empty' image space */
2613 SetBkColor (hdcBitmap, RGB(255, 255, 255));
2614 SetTextColor (hdcBitmap, RGB(0, 0, 0));
2615 PatBlt (hdcBitmap, nCopyCount * himl->cx, 0,
2616 (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2617 #endif
2618 DeleteObject (himl->hbmMask);
2619 himl->hbmMask = hbmNewBitmap;
2621 else
2622 ERR("Could not create new mask bitmap!\n");
2625 DeleteDC (hdcImageList);
2626 DeleteDC (hdcBitmap);
2628 /* Update max image count and current image count */
2629 himl->cMaxImage = nNewCount;
2630 if (himl->cCurImage > nCopyCount)
2631 himl->cCurImage = nCopyCount;
2633 return TRUE;
2637 /*************************************************************************
2638 * ImageList_SetOverlayImage [COMCTL32.79]
2640 * Assigns an overlay mask index to an existing image in an image list.
2642 * PARAMS
2643 * himl [I] handle to image list
2644 * iImage [I] image index
2645 * iOverlay [I] overlay mask index
2647 * RETURNS
2648 * Success: TRUE
2649 * Failure: FALSE
2652 BOOL WINAPI
2653 ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay)
2655 if (!himl)
2656 return FALSE;
2657 if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
2658 return FALSE;
2659 if ((iImage!=-1) && ((iImage < 0) || (iImage > himl->cCurImage)))
2660 return FALSE;
2661 himl->nOvlIdx[iOverlay - 1] = iImage;
2662 return TRUE;
2666 /*************************************************************************
2667 * ImageList_Write [COMCTL32.80]
2669 * Writes an image list to a stream.
2671 * PARAMS
2672 * himl [I] handle to image list
2673 * pstm [O] Pointer to a stream.
2675 * RETURNS
2676 * Success: TRUE
2677 * Failure: FALSE
2679 * NOTES
2680 * This function can not be implemented yet, because
2681 * IStream32::Write is not implemented.
2683 * BUGS
2684 * empty stub.
2687 BOOL WINAPI
2688 ImageList_Write (HIMAGELIST himl, LPSTREAM pstm)
2690 if (!himl)
2691 return FALSE;
2693 FIXME("empty stub!\n");
2695 return FALSE;