Use the min/max in windef.h instead.
[wine/hacks.git] / dlls / comctl32 / imagelist.c
blob152371a2bea19c72a501a1eb3cb090bf1ecec1be
1 /*
2 * ImageList implementation
4 * Copyright 1998 Eric Kohl
5 * 2000 Jason Mawdsley.
7 * TODO:
8 * - Fix ImageList_DrawIndirect (xBitmap, yBitmap, rgbFg, rgbBk, dwRop).
9 * - Fix ImageList_GetIcon.
10 * - Fix drag functions.
11 * - Fix ImageList_Write.
12 * - Fix ImageList_SetFilter (undocumented).
13 * BTW does anybody know anything about this function???
14 * - It removes 12 Bytes from the stack (3 Parameters).
15 * - First parameter SHOULD be a HIMAGELIST.
16 * - Second parameter COULD be an index?????
17 * - Third parameter.... ?????????????????????
19 * Comments:
20 * - ImageList_Draw, ImageList_DrawEx and ImageList_GetIcon use
21 * ImageList_DrawIndirect. Since ImageList_DrawIndirect is still
22 * partially implemented, the functions mentioned above will be
23 * limited in functionality too.
26 #include <string.h>
27 #include "winerror.h"
28 #include "winbase.h"
29 #include "wine/obj_base.h"
30 #include "wine/obj_storage.h"
31 #include "commctrl.h"
32 #include "imagelist.h"
33 #include "debugtools.h"
35 DEFAULT_DEBUG_CHANNEL(imagelist);
38 #define MAX_OVERLAYIMAGE 15
41 /* internal image list data used for Drag & Drop operations */
43 static HIMAGELIST himlInternalDrag = NULL;
44 static INT nInternalDragHotspotX = 0;
45 static INT nInternalDragHotspotY = 0;
47 static HWND hwndInternalDrag = 0;
48 static INT xInternalPos = 0;
49 static INT yInternalPos = 0;
51 static HDC hdcBackBuffer = 0;
52 static HBITMAP hbmBackBuffer = 0;
55 /*************************************************************************
56 * IMAGELIST_InternalExpandBitmaps [Internal]
58 * Expands the bitmaps of an image list by the given number of images.
60 * PARAMS
61 * himl [I] handle to image list
62 * nImageCount [I] number of images to add
64 * RETURNS
65 * nothing
67 * NOTES
68 * This function can NOT be used to reduce the number of images.
70 static VOID
71 IMAGELIST_InternalExpandBitmaps (HIMAGELIST himl, INT nImageCount, INT cx, INT cy)
73 HDC hdcImageList, hdcBitmap;
74 HBITMAP hbmNewBitmap;
75 INT nNewWidth, nNewCount;
77 if ((himl->cCurImage + nImageCount < himl->cMaxImage)
78 && (himl->cy >= cy))
79 return;
81 if (cy == 0) cy = himl->cy;
82 nNewCount = himl->cCurImage + nImageCount + himl->cGrow;
83 nNewWidth = nNewCount * himl->cx;
85 TRACE("Create expanded bitmaps : himl=%p x=%d y=%d count=%d\n", himl, nNewWidth, cy, nNewCount);
86 hdcImageList = CreateCompatibleDC (0);
87 hdcBitmap = CreateCompatibleDC (0);
89 hbmNewBitmap =
90 CreateBitmap (nNewWidth, cy, 1, himl->uBitsPixel, NULL);
91 if (hbmNewBitmap == 0)
92 ERR("creating new image bitmap (x=%d y=%d)!\n", nNewWidth, cy);
94 SelectObject (hdcImageList, himl->hbmImage);
95 SelectObject (hdcBitmap, hbmNewBitmap);
96 BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy,
97 hdcImageList, 0, 0, SRCCOPY);
99 DeleteObject (himl->hbmImage);
100 himl->hbmImage = hbmNewBitmap;
102 if (himl->hbmMask) {
103 hbmNewBitmap =
104 CreateBitmap (nNewWidth, cy, 1, 1, NULL);
106 if (hbmNewBitmap == 0)
107 ERR("creating new mask bitmap!\n");
109 SelectObject (hdcImageList, himl->hbmMask);
110 SelectObject (hdcBitmap, hbmNewBitmap);
111 BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy,
112 hdcImageList, 0, 0, SRCCOPY);
113 DeleteObject (himl->hbmMask);
114 himl->hbmMask = hbmNewBitmap;
117 himl->cMaxImage = nNewCount;
119 DeleteDC (hdcImageList);
120 DeleteDC (hdcBitmap);
124 /*************************************************************************
125 * IMAGELIST_InternalDraw [Internal]
127 * Draws the image in the ImageList (without the mask)
129 * PARAMS
130 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
131 * cx [I] the width of the image to display
132 * cy............[I] the height of the image to display
134 * RETURNS
135 * nothing
137 * NOTES
138 * This function is used by ImageList_DrawIndirect, when it is
139 * required to draw only the Image (without the mask) to the screen.
141 * Blending and Overlays styles are accomplished by another function
143 static VOID
144 IMAGELIST_InternalDraw(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
146 HDC hImageDC;
147 HBITMAP hOldBitmap;
149 hImageDC = CreateCompatibleDC(0);
150 hOldBitmap = SelectObject(hImageDC, pimldp->himl->hbmImage);
151 BitBlt(pimldp->hdcDst,
152 pimldp->x, pimldp->y, cx, cy,
153 hImageDC,
154 pimldp->himl->cx * pimldp->i, 0,
155 SRCCOPY);
157 SelectObject(hImageDC, hOldBitmap);
158 DeleteDC(hImageDC);
162 /*************************************************************************
163 * IMAGELIST_InternalDrawMask [Internal]
165 * Draws the image in the ImageList with the mask
167 * PARAMS
168 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
169 * cx [I] the width of the image to display
170 * cy............[I] the height of the image to display
172 * RETURNS
173 * nothing
175 * NOTES
176 * This function is used by ImageList_DrawIndirect, when it is
177 * required to draw the Image with the mask to the screen.
179 * Blending and Overlays styles are accomplished by another function.
181 static VOID
182 IMAGELIST_InternalDrawMask(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
184 BOOL bUseCustomBackground, bBlendFlag;
185 HBRUSH hBrush, hOldBrush;
186 HDC hMaskDC, hImageDC;
187 HBITMAP hOldBitmapImage, hOldBitmapMask;
188 HIMAGELIST himlLocal = pimldp->himl;
189 COLORREF oldBkColor, oldFgColor;
190 UINT fStyle = pimldp->fStyle & (~ILD_OVERLAYMASK);
193 * We need a dc and bitmap to draw on that is
194 * not on the screen.
196 HDC hOffScreenDC = 0;
197 HBITMAP hOffScreenBmp = 0;
199 bUseCustomBackground = (himlLocal->clrBk != CLR_NONE);
200 bBlendFlag = (fStyle & ILD_BLEND50 ) || (fStyle & ILD_BLEND25);
202 hImageDC = CreateCompatibleDC(0);
203 hMaskDC = CreateCompatibleDC(0);
205 /* Create a compatible DC. */
206 hOffScreenDC = CreateCompatibleDC( pimldp->hdcDst );
208 if ( hOffScreenDC )
210 hOffScreenBmp = CreateCompatibleBitmap( pimldp->hdcDst, cx, cy );
212 if ( hOffScreenBmp )
213 SelectObject( hOffScreenDC, hOffScreenBmp );
214 else
215 goto cleanup;
217 else
218 goto cleanup;
220 hOldBitmapImage = SelectObject(hImageDC, himlLocal->hbmImage);
221 hOldBitmapMask = SelectObject(hMaskDC, himlLocal->hbmMask);
224 * Get a copy of the image for the masking operations.
225 * We will use the copy, and this dc for all the various
226 * blitting, and then do one final blit to the screen dc.
227 * This should clean up most of the flickering.
229 BitBlt( hOffScreenDC, 0, 0, cx, cy, pimldp->hdcDst, pimldp->x,
230 pimldp->y, SRCCOPY);
233 * Draw the Background for the appropriate Styles
235 if( bUseCustomBackground && (fStyle == ILD_NORMAL || fStyle & ILD_IMAGE
236 || bBlendFlag) )
239 hBrush = CreateSolidBrush (himlLocal->clrBk);
240 hOldBrush = SelectObject (pimldp->hdcDst, hBrush);
242 PatBlt( hOffScreenDC, pimldp->x, pimldp->y, cx, cy, PATCOPY );
244 DeleteObject (SelectObject (pimldp->hdcDst, hOldBrush));
248 * Draw Image Transparently over the current background
250 if(fStyle == ILD_NORMAL || (fStyle & ILD_TRANSPARENT) ||
251 ((fStyle & ILD_IMAGE) && bUseCustomBackground) || bBlendFlag)
252 { /*
253 * To obtain a transparent look, background color should be set
254 * to white and foreground color to black when blting the
255 * monochrome mask.
258 oldBkColor = SetBkColor( hOffScreenDC, RGB( 0xff, 0xff, 0xff ) );
259 oldFgColor = SetTextColor( hOffScreenDC, RGB( 0, 0, 0 ) );
261 BitBlt( hOffScreenDC, 0, 0, cx, cy,hMaskDC, himlLocal->cx * pimldp->i,
262 0, SRCAND );
264 BitBlt( hOffScreenDC, 0, 0, cx, cy, hImageDC,himlLocal->cx * pimldp->i,
265 0, SRCPAINT );
270 * Draw the image when no Background is specified
272 else if((fStyle & ILD_IMAGE) && !bUseCustomBackground)
274 BitBlt( hOffScreenDC, 0, 0, cx, cy, hImageDC,
275 himlLocal->cx * pimldp->i, 0, SRCCOPY);
278 * Draw the mask with or without a background
280 else if(fStyle & ILD_MASK)
282 BitBlt( hOffScreenDC, 0, 0, cx, cy, hMaskDC, himlLocal->cx * pimldp->i,
283 0, bUseCustomBackground ? SRCCOPY : SRCAND);
287 * Blit the bitmap to the screen now.
289 BitBlt( pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
290 hOffScreenDC, 0, 0, SRCCOPY);
293 SelectObject(hImageDC, hOldBitmapImage);
294 SelectObject(hMaskDC, hOldBitmapMask);
296 cleanup:
298 DeleteDC(hImageDC);
299 DeleteDC(hMaskDC);
301 DeleteDC( hOffScreenDC );
302 DeleteObject( hOffScreenBmp );
304 return;
307 /*************************************************************************
308 * IMAGELIST_InternalDrawBlend [Internal]
310 * Draws the Blend over the current image
312 * PARAMS
313 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
314 * cx [I] the width of the image to display
315 * cy............[I] the height of the image to display
317 * RETURNS
318 * nothing
320 * NOTES
321 * This functions is used by ImageList_DrawIndirect, when it is
322 * required to add the blend to the current image.
325 static VOID
326 IMAGELIST_InternalDrawBlend(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
329 HDC hBlendMaskDC,hMaskDC;
330 HBRUSH hBlendColorBrush, hBlendBrush, hOldBrush;
331 HBITMAP hBlendMaskBitmap, hOldBitmap;
332 COLORREF clrBlend, OldTextColor, OldBkColor;
333 HIMAGELIST himlLocal = pimldp->himl;
335 clrBlend = GetSysColor (COLOR_HIGHLIGHT);
336 if (!(pimldp->rgbFg == CLR_DEFAULT))
338 clrBlend = pimldp->rgbFg;
340 /* Create the blend Mask
342 hBlendMaskDC = CreateCompatibleDC(0);
343 hBlendBrush = pimldp->fStyle & ILD_BLEND50 ?
344 himlLocal->hbrBlend50 : himlLocal->hbrBlend25;
346 hBlendMaskBitmap = CreateBitmap(cx, cy, 1, 1, NULL);
347 hOldBitmap = SelectObject(hBlendMaskDC, hBlendMaskBitmap);
349 hOldBrush = (HBRUSH) SelectObject(hBlendMaskDC, hBlendBrush);
350 PatBlt(hBlendMaskDC, 0, 0, cx, cy, PATCOPY);
351 SelectObject(hBlendMaskDC, hOldBrush);
353 /* Modify the blend mask if an Image Mask exist
355 if(pimldp->himl->hbmMask != 0)
357 HBITMAP hOldMaskBitmap;
358 hMaskDC = CreateCompatibleDC(0);
359 hOldMaskBitmap = (HBITMAP) SelectObject(hMaskDC, himlLocal->hbmMask);
361 BitBlt(hBlendMaskDC,
362 0,0, cx, cy,
363 hMaskDC,
364 himlLocal->cx * pimldp->i,0,
365 0x220326); /* NOTSRCAND */
367 BitBlt(hBlendMaskDC,
368 0,0, cx, cy,
369 hBlendMaskDC,
370 0,0,
371 NOTSRCCOPY);
373 SelectObject(hMaskDC, hOldMaskBitmap);
374 DeleteDC(hMaskDC);
377 /* Apply blend to the current image given the BlendMask
379 OldTextColor = SetTextColor(pimldp->hdcDst, 0);
380 OldBkColor = SetBkColor(pimldp->hdcDst, RGB(255,255,255));
381 hBlendColorBrush = CreateSolidBrush(clrBlend);
382 hOldBrush = (HBRUSH) SelectObject (pimldp->hdcDst, hBlendColorBrush);
384 BitBlt (pimldp->hdcDst,
385 pimldp->x, pimldp->y, cx, cy,
386 hBlendMaskDC,
387 0, 0,
388 0xB8074A); /* PSDPxax */
390 SelectObject(pimldp->hdcDst, hOldBrush);
391 SetTextColor(pimldp->hdcDst, OldTextColor);
392 SetBkColor(pimldp->hdcDst, OldBkColor);
393 SelectObject(hBlendMaskDC, hOldBitmap);
394 DeleteDC(hBlendMaskDC);
395 DeleteObject(hBlendMaskBitmap);
396 DeleteObject(hBlendColorBrush);
399 /*************************************************************************
400 * IMAGELIST_InternalDrawOverlay [Internal]
402 * Draws the overlay image
404 * PARAMS
405 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
406 * cx [I] the width of the image to display
407 * cy............[I] the height of the image to display
409 * RETURNS
410 * nothing
412 * NOTES
413 * This functions is used by ImageList_DrawIndirect, when it is
414 * required to draw the overlay
418 static VOID
419 IMAGELIST_InternalDrawOverlay(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
421 INT nOvlIdx;
422 HDC hImageDC;
423 HBITMAP hOldBitmap;
425 nOvlIdx = (pimldp->fStyle & ILD_OVERLAYMASK) >> 8;
426 if ((nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE))
428 nOvlIdx = pimldp->himl->nOvlIdx[nOvlIdx - 1];
429 if ((nOvlIdx >= 0) && (nOvlIdx <= pimldp->himl->cCurImage))
431 hImageDC = CreateCompatibleDC(0);
432 if (pimldp->himl->hbmMask)
434 hOldBitmap = (HBITMAP) SelectObject (hImageDC,
435 pimldp->himl->hbmMask);
437 BitBlt (pimldp->hdcDst,
438 pimldp->x, pimldp->y, cx, cy,
439 hImageDC, pimldp->himl->cx * nOvlIdx, 0,
440 SRCAND);
442 SelectObject(hImageDC, hOldBitmap);
444 hOldBitmap = (HBITMAP) SelectObject (hImageDC,
445 pimldp->himl->hbmImage);
447 BitBlt (pimldp->hdcDst,
448 pimldp->x, pimldp->y, cx, cy,
449 hImageDC,
450 pimldp->himl->cx * nOvlIdx, 0,
451 SRCPAINT);
453 SelectObject(hImageDC, hOldBitmap);
454 DeleteDC(hImageDC);
463 /*************************************************************************
464 * ImageList_Add [COMCTL32.40]
466 * Add an image or images to an image list.
468 * PARAMS
469 * himl [I] handle to image list
470 * hbmImage [I] handle to image bitmap
471 * hbmMask [I] handle to mask bitmap
473 * RETURNS
474 * Success: Index of the first new image.
475 * Failure: -1
478 INT WINAPI
479 ImageList_Add (HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
481 HDC hdcImage, hdcBitmap;
482 INT nFirstIndex, nImageCount;
483 INT nStartX;
484 BITMAP bmp;
485 HBITMAP hOldBitmapImage, hOldBitmap;
487 TRACE("himl=%p hbmimage=%x hbmmask=%x\n", himl, hbmImage, hbmMask);
488 if (!himl || !hbmImage)
489 return -1;
491 GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
492 nImageCount = bmp.bmWidth / himl->cx;
494 IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight);
496 nStartX = himl->cCurImage * himl->cx;
498 hdcImage = CreateCompatibleDC(0);
499 hdcBitmap = CreateCompatibleDC(0);
501 hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
502 hOldBitmap = SelectObject(hdcBitmap, hbmImage);
504 /* Copy result to the imagelist
506 BitBlt (hdcImage, nStartX, 0, bmp.bmWidth, bmp.bmHeight,
507 hdcBitmap, 0, 0, SRCCOPY);
509 if(himl->hbmMask)
511 HDC hdcMask, hdcTemp, hOldBitmapMask, hOldBitmapTemp;
513 hdcMask = CreateCompatibleDC (0);
514 hdcTemp = CreateCompatibleDC(0);
515 hOldBitmapMask = (HBITMAP) SelectObject(hdcMask, himl->hbmMask);
516 hOldBitmapTemp = (HBITMAP) SelectObject(hdcTemp, hbmMask);
518 BitBlt (hdcMask,
519 nStartX, 0, bmp.bmWidth, bmp.bmHeight,
520 hdcTemp,
521 0, 0,
522 SRCCOPY);
524 SelectObject(hdcTemp, hOldBitmapTemp);
525 DeleteDC(hdcTemp);
527 /* Remove the background from the image
529 BitBlt (hdcImage,
530 nStartX, 0, bmp.bmWidth, bmp.bmHeight,
531 hdcMask,
532 nStartX, 0,
533 0x220326); /* NOTSRCAND */
535 SelectObject(hdcMask, hOldBitmapMask);
536 DeleteDC(hdcMask);
539 SelectObject(hdcImage, hOldBitmapImage);
540 SelectObject(hdcBitmap, hOldBitmap);
541 DeleteDC(hdcImage);
542 DeleteDC(hdcBitmap);
544 nFirstIndex = himl->cCurImage;
545 himl->cCurImage += nImageCount;
547 return nFirstIndex;
551 /*************************************************************************
552 * ImageList_AddIcon [COMCTL32.41]
554 * Adds an icon to an image list.
556 * PARAMS
557 * himl [I] handle to image list
558 * hIcon [I] handle to icon
560 * RETURNS
561 * Success: index of the new image
562 * Failure: -1
565 INT WINAPI
566 ImageList_AddIcon (HIMAGELIST himl, HICON hIcon)
568 return ImageList_ReplaceIcon (himl, -1, hIcon);
572 /*************************************************************************
573 * ImageList_AddMasked [COMCTL32.42]
575 * Adds an image or images to an image list and creates a mask from the
576 * specified bitmap using the mask color.
578 * PARAMS
579 * himl [I] handle to image list.
580 * hBitmap [I] handle to bitmap
581 * clrMask [I] mask color.
583 * RETURNS
584 * Success: Index of the first new image.
585 * Failure: -1
588 INT WINAPI
589 ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
591 HDC hdcImage, hdcMask, hdcBitmap;
592 INT nIndex, nImageCount, nMaskXOffset=0;
593 BITMAP bmp;
594 HBITMAP hOldBitmap, hOldBitmapMask, hOldBitmapImage;
595 HBITMAP hMaskBitmap=0;
596 COLORREF bkColor;
598 TRACE("himl=%p hbitmap=%x clrmask=%lx\n", himl, hBitmap, clrMask);
599 if (himl == NULL)
600 return -1;
602 if (!GetObjectA (hBitmap, sizeof(BITMAP), &bmp))
603 return -1;
605 nImageCount = bmp.bmWidth / himl->cx;
607 IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight);
609 nIndex = himl->cCurImage;
610 himl->cCurImage += nImageCount;
612 hdcMask = CreateCompatibleDC (0);
613 hdcImage = CreateCompatibleDC(0);
614 hdcBitmap = CreateCompatibleDC(0);
617 hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
618 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
619 if(himl->hbmMask)
621 hOldBitmapMask = SelectObject(hdcMask, himl->hbmMask);
622 nMaskXOffset = nIndex * himl->cx;
624 else
627 Create a temp Mask so we can remove the background of
628 the Image (Windows does this even if there is no mask)
630 hMaskBitmap = CreateBitmap(bmp.bmWidth, bmp.bmHeight, 1, 1, NULL);
631 hOldBitmapMask = SelectObject(hdcMask, hMaskBitmap);
632 nMaskXOffset = 0;
634 /* create monochrome image to the mask bitmap */
635 bkColor = (clrMask != CLR_DEFAULT) ? clrMask :
636 GetPixel (hdcBitmap, 0, 0);
637 SetBkColor (hdcBitmap, bkColor);
638 BitBlt (hdcMask,
639 nMaskXOffset, 0, bmp.bmWidth, bmp.bmHeight,
640 hdcBitmap, 0, 0,
641 SRCCOPY);
643 SetBkColor(hdcBitmap, RGB(255,255,255));
644 /*Remove the background from the image
647 WINDOWS BUG ALERT!!!!!!
648 The statement below should not be done in common practice
649 but this is how ImageList_AddMasked works in Windows.
650 It overwrites the original bitmap passed, this was discovered
651 by using the same bitmap to iterate the different styles
652 on windows where it failed (BUT ImageList_Add is OK)
653 This is here in case some apps rely on this bug
655 BitBlt(hdcBitmap,
656 0, 0, bmp.bmWidth, bmp.bmHeight,
657 hdcMask,
658 nMaskXOffset, 0,
659 0x220326); /* NOTSRCAND */
660 /* Copy result to the imagelist
662 BitBlt (hdcImage,
663 nIndex * himl->cx, 0, bmp.bmWidth, bmp.bmHeight,
664 hdcBitmap,
665 0, 0,
666 SRCCOPY);
667 /* Clean up
669 SelectObject(hdcMask,hOldBitmapMask);
670 SelectObject(hdcImage, hOldBitmapImage);
671 SelectObject(hdcBitmap, hOldBitmap);
672 DeleteDC(hdcMask);
673 DeleteDC(hdcImage);
674 DeleteDC(hdcBitmap);
675 if(!himl->hbmMask)
677 DeleteObject(hMaskBitmap);
680 return nIndex;
684 /*************************************************************************
685 * ImageList_BeginDrag [COMCTL32.43]
687 * Creates a temporary image list that contains one image. It will be used
688 * as a drag image.
690 * PARAMS
691 * himlTrack [I] handle to the source image list
692 * iTrack [I] index of the drag image in the source image list
693 * dxHotspot [I] X position of the hot spot of the drag image
694 * dyHotspot [I] Y position of the hot spot of the drag image
696 * RETURNS
697 * Success: TRUE
698 * Failure: FALSE
701 BOOL WINAPI
702 ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
703 INT dxHotspot, INT dyHotspot)
705 HDC hdcSrc, hdcDst;
707 FIXME("partially implemented!\n");
709 if (himlTrack == NULL)
710 return FALSE;
712 if (himlInternalDrag)
713 ImageList_EndDrag ();
715 himlInternalDrag =
716 ImageList_Create (himlTrack->cx, himlTrack->cy,
717 himlTrack->flags, 1, 1);
718 if (himlInternalDrag == NULL) {
719 ERR("Error creating drag image list!\n");
720 return FALSE;
723 nInternalDragHotspotX = dxHotspot;
724 nInternalDragHotspotY = dyHotspot;
726 hdcSrc = CreateCompatibleDC (0);
727 hdcDst = CreateCompatibleDC (0);
729 /* copy image */
730 SelectObject (hdcSrc, himlTrack->hbmImage);
731 SelectObject (hdcDst, himlInternalDrag->hbmImage);
732 StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
733 iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
735 /* copy mask */
736 SelectObject (hdcSrc, himlTrack->hbmMask);
737 SelectObject (hdcDst, himlInternalDrag->hbmMask);
738 StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
739 iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
741 DeleteDC (hdcSrc);
742 DeleteDC (hdcDst);
744 himlInternalDrag->cCurImage = 1;
746 return TRUE;
750 /*************************************************************************
751 * ImageList_Copy [COMCTL32.44]
753 * Copies an image of the source image list to an image of the
754 * destination image list. Images can be copied or swapped.
756 * PARAMS
757 * himlDst [I] handle to the destination image list
758 * iDst [I] destination image index.
759 * himlSrc [I] handle to the source image list
760 * iSrc [I] source image index
761 * uFlags [I] flags for the copy operation
763 * RETURNS
764 * Success: TRUE
765 * Failure: FALSE
767 * NOTES
768 * Copying from one image list to another is possible. The original
769 * implementation just copies or swaps within one image list.
770 * Could this feature become a bug??? ;-)
773 BOOL WINAPI
774 ImageList_Copy (HIMAGELIST himlDst, INT iDst, HIMAGELIST himlSrc,
775 INT iSrc, INT uFlags)
777 HDC hdcSrc, hdcDst;
779 TRACE("iDst=%d iSrc=%d\n", iDst, iSrc);
781 if ((himlSrc == NULL) || (himlDst == NULL))
782 return FALSE;
783 if ((iDst < 0) || (iDst >= himlDst->cCurImage))
784 return FALSE;
785 if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage))
786 return FALSE;
788 hdcSrc = CreateCompatibleDC (0);
789 if (himlDst == himlSrc)
790 hdcDst = hdcSrc;
791 else
792 hdcDst = CreateCompatibleDC (0);
794 if (uFlags & ILCF_SWAP) {
795 /* swap */
796 HBITMAP hbmTempImage, hbmTempMask;
798 /* create temporary bitmaps */
799 hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
800 himlSrc->uBitsPixel, NULL);
801 hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
802 1, NULL);
804 /* copy (and stretch) destination to temporary bitmaps.(save) */
805 /* image */
806 SelectObject (hdcSrc, himlDst->hbmImage);
807 SelectObject (hdcDst, hbmTempImage);
808 StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
809 hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
810 SRCCOPY);
811 /* mask */
812 SelectObject (hdcSrc, himlDst->hbmMask);
813 SelectObject (hdcDst, hbmTempMask);
814 StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
815 hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
816 SRCCOPY);
818 /* copy (and stretch) source to destination */
819 /* image */
820 SelectObject (hdcSrc, himlSrc->hbmImage);
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);
825 /* mask */
826 SelectObject (hdcSrc, himlSrc->hbmMask);
827 SelectObject (hdcDst, himlDst->hbmMask);
828 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
829 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
830 SRCCOPY);
832 /* copy (without stretching) temporary bitmaps to source (restore) */
833 /* image */
834 SelectObject (hdcSrc, hbmTempImage);
835 SelectObject (hdcDst, himlSrc->hbmImage);
836 BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
837 hdcSrc, 0, 0, SRCCOPY);
838 /* mask */
839 SelectObject (hdcSrc, hbmTempMask);
840 SelectObject (hdcDst, himlSrc->hbmMask);
841 BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
842 hdcSrc, 0, 0, SRCCOPY);
844 /* delete temporary bitmaps */
845 DeleteObject (hbmTempMask);
846 DeleteObject (hbmTempImage);
848 else {
849 /* copy image */
850 SelectObject (hdcSrc, himlSrc->hbmImage);
851 if (himlSrc == himlDst)
852 hdcDst = hdcSrc;
853 else
854 SelectObject (hdcDst, himlDst->hbmImage);
855 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
856 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
857 SRCCOPY);
859 /* copy mask */
860 SelectObject (hdcSrc, himlSrc->hbmMask);
861 if (himlSrc == himlDst)
862 hdcDst = hdcSrc;
863 else
864 SelectObject (hdcDst, himlDst->hbmMask);
865 StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
866 hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
867 SRCCOPY);
870 DeleteDC (hdcSrc);
871 if (himlSrc != himlDst)
872 DeleteDC (hdcDst);
874 return TRUE;
878 /*************************************************************************
879 * ImageList_Create [COMCTL32.45] Creates a new image list.
881 * PARAMS
882 * cx [I] image height
883 * cy [I] image width
884 * flags [I] creation flags
885 * cInitial [I] initial number of images in the image list
886 * cGrow [I] number of images by which image list grows
888 * RETURNS
889 * Success: Handle to the created image list
890 * Failure: NULL
893 HIMAGELIST WINAPI
894 ImageList_Create (INT cx, INT cy, UINT flags,
895 INT cInitial, INT cGrow)
897 HIMAGELIST himl;
898 HDC hdc;
899 INT nCount;
900 HBITMAP hbmTemp;
901 static WORD aBitBlend25[] =
902 {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00};
904 static WORD aBitBlend50[] =
905 {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
907 TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow);
909 himl = (HIMAGELIST)COMCTL32_Alloc (sizeof(struct _IMAGELIST));
910 if (!himl)
911 return NULL;
913 himl->cx = cx;
914 himl->cy = cy;
915 himl->flags = flags;
916 himl->cMaxImage = cInitial + cGrow;
917 himl->cInitial = cInitial;
918 himl->cGrow = cGrow;
919 himl->cCurImage = 0;
920 himl->clrFg = CLR_DEFAULT;
921 himl->clrBk = CLR_NONE;
923 /* initialize overlay mask indices */
924 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
925 himl->nOvlIdx[nCount] = -1;
927 hdc = CreateCompatibleDC (0);
928 himl->uBitsPixel = (UINT)GetDeviceCaps (hdc, BITSPIXEL);
929 DeleteDC (hdc);
931 TRACE("Image: %d Bits per Pixel\n", himl->uBitsPixel);
933 if (himl->cMaxImage > 0) {
934 himl->hbmImage =
935 CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
936 1, himl->uBitsPixel, NULL);
937 if (himl->hbmImage == 0) {
938 ERR("Error creating image bitmap!\n");
939 return NULL;
942 else
943 himl->hbmImage = 0;
945 if ( (himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) {
946 himl->hbmMask = CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
947 1, 1, NULL);
948 if (himl->hbmMask == 0) {
949 ERR("Error creating mask bitmap!\n");
950 if (himl->hbmImage)
951 DeleteObject (himl->hbmImage);
952 return NULL;
955 else
956 himl->hbmMask = 0;
958 /* create blending brushes */
959 hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend25);
960 himl->hbrBlend25 = CreatePatternBrush (hbmTemp);
961 DeleteObject (hbmTemp);
963 hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend50);
964 himl->hbrBlend50 = CreatePatternBrush (hbmTemp);
965 DeleteObject (hbmTemp);
967 TRACE("created imagelist %p\n", himl);
968 return himl;
972 /*************************************************************************
973 * ImageList_Destroy [COMCTL32.46]
975 * Destroys an image list.
977 * PARAMS
978 * himl [I] handle to image list
980 * RETURNS
981 * Success: TRUE
982 * Failure: FALSE
985 BOOL WINAPI
986 ImageList_Destroy (HIMAGELIST himl)
988 if (!himl)
989 return FALSE;
991 /* delete image bitmaps */
992 if (himl->hbmImage)
993 DeleteObject (himl->hbmImage);
994 if (himl->hbmMask)
995 DeleteObject (himl->hbmMask);
997 /* delete blending brushes */
998 if (himl->hbrBlend25)
999 DeleteObject (himl->hbrBlend25);
1000 if (himl->hbrBlend50)
1001 DeleteObject (himl->hbrBlend50);
1003 COMCTL32_Free (himl);
1005 return TRUE;
1009 /*************************************************************************
1010 * ImageList_DragEnter [COMCTL32.47]
1012 * Locks window update and displays the drag image at the given position.
1014 * PARAMS
1015 * hwndLock [I] handle of the window that owns the drag image.
1016 * x [I] X position of the drag image.
1017 * y [I] Y position of the drag image.
1019 * RETURNS
1020 * Success: TRUE
1021 * Failure: FALSE
1023 * NOTES
1024 * The position of the drag image is relative to the window, not
1025 * the client area.
1028 BOOL WINAPI
1029 ImageList_DragEnter (HWND hwndLock, INT x, INT y)
1031 if (himlInternalDrag == NULL)
1032 return FALSE;
1034 if (hwndLock)
1035 hwndInternalDrag = hwndLock;
1036 else
1037 hwndInternalDrag = GetDesktopWindow ();
1039 xInternalPos = x;
1040 yInternalPos = y;
1042 hdcBackBuffer = CreateCompatibleDC (0);
1043 hbmBackBuffer = CreateCompatibleBitmap (hdcBackBuffer,
1044 himlInternalDrag->cx, himlInternalDrag->cy);
1046 ImageList_DragShowNolock (TRUE);
1048 return FALSE;
1052 /*************************************************************************
1053 * ImageList_DragLeave [COMCTL32.48]
1055 * Unlocks window update and hides the drag image.
1057 * PARAMS
1058 * hwndLock [I] handle of the window that owns the drag image.
1060 * RETURNS
1061 * Success: TRUE
1062 * Failure: FALSE
1065 BOOL WINAPI
1066 ImageList_DragLeave (HWND hwndLock)
1068 if (hwndLock)
1069 hwndInternalDrag = hwndLock;
1070 else
1071 hwndInternalDrag = GetDesktopWindow ();
1073 ImageList_DragShowNolock (FALSE);
1075 DeleteDC (hdcBackBuffer);
1076 DeleteObject (hbmBackBuffer);
1078 return TRUE;
1082 /*************************************************************************
1083 * ImageList_DragMove [COMCTL32.49]
1085 * Moves the drag image.
1087 * PARAMS
1088 * x [I] X position of the drag image.
1089 * y [I] Y position of the drag image.
1091 * RETURNS
1092 * Success: TRUE
1093 * Failure: FALSE
1095 * NOTES
1096 * The position of the drag image is relative to the window, not
1097 * the client area.
1100 BOOL WINAPI
1101 ImageList_DragMove (INT x, INT y)
1103 ImageList_DragShowNolock (FALSE);
1105 xInternalPos = x;
1106 yInternalPos = y;
1108 ImageList_DragShowNolock (TRUE);
1110 return FALSE;
1114 /*************************************************************************
1115 * ImageList_DragShowNolock [COMCTL32.50]
1117 * Shows or hides the drag image.
1119 * PARAMS
1120 * bShow [I] TRUE shows the drag image, FALSE hides it.
1122 * RETURNS
1123 * Success: TRUE
1124 * Failure: FALSE
1126 * FIXME
1127 * semi-stub.
1130 BOOL WINAPI
1131 ImageList_DragShowNolock (BOOL bShow)
1133 HDC hdcDrag;
1135 FIXME("semi-stub!\n");
1136 TRACE("bShow=0x%X!\n", bShow);
1138 hdcDrag = GetDCEx (hwndInternalDrag, 0,
1139 DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
1141 if (bShow) {
1142 /* show drag image */
1144 /* save background */
1146 /* draw drag image */
1149 else {
1150 /* hide drag image */
1152 /* restore background */
1156 ReleaseDC (hwndInternalDrag, hdcDrag);
1158 return FALSE;
1162 /*************************************************************************
1163 * ImageList_Draw [COMCTL32.51] Draws an image.
1165 * PARAMS
1166 * himl [I] handle to image list
1167 * i [I] image index
1168 * hdc [I] handle to device context
1169 * x [I] x position
1170 * y [I] y position
1171 * fStyle [I] drawing flags
1173 * RETURNS
1174 * Success: TRUE
1175 * Failure: FALSE
1177 * NOTES
1178 * Calls ImageList_DrawIndirect.
1180 * SEE
1181 * ImageList_DrawIndirect.
1184 BOOL WINAPI
1185 ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc,
1186 INT x, INT y, UINT fStyle)
1188 IMAGELISTDRAWPARAMS imldp;
1190 imldp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
1191 imldp.himl = himl;
1192 imldp.i = i;
1193 imldp.hdcDst = hdc,
1194 imldp.x = x;
1195 imldp.y = y;
1196 imldp.cx = 0;
1197 imldp.cy = 0;
1198 imldp.xBitmap = 0;
1199 imldp.yBitmap = 0;
1200 imldp.rgbBk = CLR_DEFAULT;
1201 imldp.rgbFg = CLR_DEFAULT;
1202 imldp.fStyle = fStyle;
1203 imldp.dwRop = 0;
1205 return ImageList_DrawIndirect (&imldp);
1209 /*************************************************************************
1210 * ImageList_DrawEx [COMCTL32.52]
1212 * Draws an image and allows to use extended drawing features.
1214 * PARAMS
1215 * himl [I] handle to image list
1216 * i [I] image index
1217 * hdc [I] handle to device context
1218 * x [I] X position
1219 * y [I] Y position
1220 * xOffs [I] X offset
1221 * yOffs [I] Y offset
1222 * rgbBk [I] background color
1223 * rgbFg [I] foreground color
1224 * fStyle [I] drawing flags
1226 * RETURNS
1227 * Success: TRUE
1228 * Failure: FALSE
1230 * NOTES
1231 * Calls ImageList_DrawIndirect.
1233 * SEE
1234 * ImageList_DrawIndirect.
1237 BOOL WINAPI
1238 ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y,
1239 INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg,
1240 UINT fStyle)
1242 IMAGELISTDRAWPARAMS imldp;
1244 imldp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
1245 imldp.himl = himl;
1246 imldp.i = i;
1247 imldp.hdcDst = hdc,
1248 imldp.x = x;
1249 imldp.y = y;
1250 imldp.cx = dx;
1251 imldp.cy = dy;
1252 imldp.xBitmap = 0;
1253 imldp.yBitmap = 0;
1254 imldp.rgbBk = rgbBk;
1255 imldp.rgbFg = rgbFg;
1256 imldp.fStyle = fStyle;
1257 imldp.dwRop = 0;
1259 return ImageList_DrawIndirect (&imldp);
1263 /*************************************************************************
1264 * ImageList_DrawIndirect [COMCTL32.53]
1266 * Draws an image using ...
1268 * PARAMS
1269 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
1271 * RETURNS
1272 * Success: TRUE
1273 * Failure: FALSE
1276 BOOL WINAPI
1277 ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
1279 INT cx, cy;
1281 Do some Error Checking
1283 if (pimldp == NULL)
1284 return FALSE;
1285 if (pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS))
1286 return FALSE;
1287 if (pimldp->himl == NULL)
1288 return FALSE;
1289 if ((pimldp->i < 0) || (pimldp->i >= pimldp->himl->cCurImage)) {
1290 ERR("%d not within range (max %d)\n",pimldp->i,pimldp->himl->cCurImage-1);
1291 return FALSE;
1294 Get the Height and Width to display
1296 cx = (pimldp->cx == 0) ? pimldp->himl->cx : pimldp->cx;
1297 cy = (pimldp->cy == 0) ? pimldp->himl->cy : pimldp->cy;
1299 Draw the image
1301 if(pimldp->himl->hbmMask != 0)
1303 IMAGELIST_InternalDrawMask(pimldp, cx, cy);
1305 else
1307 IMAGELIST_InternalDraw(pimldp, cx, cy);
1310 Apply the blend if needed to the Image
1312 if((pimldp->fStyle & ILD_BLEND50)
1313 || (pimldp->fStyle & ILD_BLEND25))
1315 IMAGELIST_InternalDrawBlend(pimldp, cx, cy);
1318 Apply the Overlay if needed
1320 if (pimldp->fStyle & ILD_OVERLAYMASK)
1322 IMAGELIST_InternalDrawOverlay(pimldp, cx, cy);
1325 return TRUE;
1329 /*************************************************************************
1330 * ImageList_Duplicate [COMCTL32.54] Duplicates an image list.
1332 * PARAMS
1333 * himlSrc [I] source image list handle
1335 * RETURNS
1336 * Success: Handle of duplicated image list.
1337 * Failure: NULL
1340 HIMAGELIST WINAPI
1341 ImageList_Duplicate (HIMAGELIST himlSrc)
1343 HIMAGELIST himlDst;
1344 HDC hdcSrc, hdcDst;
1346 if (himlSrc == NULL) {
1347 ERR("Invalid image list handle!\n");
1348 return NULL;
1351 himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
1352 himlSrc->cInitial, himlSrc->cGrow);
1354 if (himlDst)
1356 hdcSrc = CreateCompatibleDC (0);
1357 hdcDst = CreateCompatibleDC (0);
1358 SelectObject (hdcSrc, himlSrc->hbmImage);
1359 SelectObject (hdcDst, himlDst->hbmImage);
1360 BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy,
1361 hdcSrc, 0, 0, SRCCOPY);
1363 if (himlDst->hbmMask)
1365 SelectObject (hdcSrc, himlSrc->hbmMask);
1366 SelectObject (hdcDst, himlDst->hbmMask);
1367 BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx,
1368 himlSrc->cy, hdcSrc, 0, 0, SRCCOPY);
1371 DeleteDC (hdcDst);
1372 DeleteDC (hdcSrc);
1374 himlDst->cCurImage = himlSrc->cCurImage;
1375 himlDst->cMaxImage = himlSrc->cMaxImage;
1377 return himlDst;
1381 /*************************************************************************
1382 * ImageList_EndDrag [COMCTL32.55] Finishes a drag operation.
1384 * Finishes a drag operation.
1386 * PARAMS
1387 * no Parameters
1389 * RETURNS
1390 * Success: TRUE
1391 * Failure: FALSE
1393 * BUGS
1394 * semi-stub.
1397 BOOL WINAPI
1398 ImageList_EndDrag (void)
1400 FIXME("semi-stub!\n");
1402 if (himlInternalDrag)
1405 ImageList_Destroy (himlInternalDrag);
1406 himlInternalDrag = NULL;
1408 nInternalDragHotspotX = 0;
1409 nInternalDragHotspotY = 0;
1413 return TRUE;
1417 /*************************************************************************
1418 * ImageList_GetBkColor [COMCTL32.56]
1420 * Returns the background color of an image list.
1422 * PARAMS
1423 * himl [I] Image list handle.
1425 * RETURNS
1426 * Success: background color
1427 * Failure: CLR_NONE
1430 COLORREF WINAPI
1431 ImageList_GetBkColor (HIMAGELIST himl)
1433 if (himl == NULL)
1434 return CLR_NONE;
1436 return himl->clrBk;
1440 /*************************************************************************
1441 * ImageList_GetDragImage [COMCTL32.57]
1443 * Returns the handle to the internal drag image list.
1445 * PARAMS
1446 * ppt [O] Pointer to the drag position. Can be NULL.
1447 * pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
1449 * RETURNS
1450 * Success: Handle of the drag image list.
1451 * Failure: NULL.
1453 * BUGS
1454 * semi-stub.
1457 HIMAGELIST WINAPI
1458 ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot)
1460 FIXME("semi-stub!\n");
1462 if (himlInternalDrag)
1463 return (himlInternalDrag);
1465 return NULL;
1469 /*************************************************************************
1470 * ImageList_GetIcon [COMCTL32.59]
1472 * Creates an icon from a masked image of an image list.
1474 * PARAMS
1475 * himl [I] handle to image list
1476 * i [I] image index
1477 * flags [I] drawing style flags
1479 * RETURNS
1480 * Success: icon handle
1481 * Failure: NULL
1484 HICON WINAPI
1485 ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle)
1487 ICONINFO ii;
1488 HICON hIcon;
1489 HBITMAP hOldSrcBitmap,hOldDstBitmap;
1490 HDC hdcSrc, hdcDst;
1492 if ((himl == NULL) || (i < 0) || (i >= himl->cCurImage)) {
1493 FIXME("(%p,%d,%x), params out of range!\n",himl,i,fStyle);
1494 return 0;
1497 hdcSrc = CreateCompatibleDC(0);
1498 hdcDst = CreateCompatibleDC(0);
1500 ii.fIcon = TRUE;
1501 ii.hbmMask = CreateCompatibleBitmap (hdcDst, himl->cx, himl->cy);
1503 /* draw mask*/
1504 hOldDstBitmap = (HBITMAP)SelectObject (hdcDst, ii.hbmMask);
1505 if (himl->hbmMask) {
1506 SelectObject (hdcSrc, himl->hbmMask);
1507 BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1508 hdcSrc, i * himl->cx, 0, SRCCOPY);
1510 else
1511 PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS);
1513 /* draw image*/
1514 hOldSrcBitmap = (HBITMAP)SelectObject (hdcSrc, himl->hbmImage);
1515 ii.hbmColor = CreateCompatibleBitmap (hdcSrc, himl->cx, himl->cy);
1516 SelectObject (hdcDst, ii.hbmColor);
1517 BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1518 hdcSrc, i * himl->cx, 0, SRCCOPY);
1521 * CreateIconIndirect requires us to deselect the bitmaps from
1522 * the DCs before calling
1524 SelectObject(hdcSrc, hOldSrcBitmap);
1525 SelectObject(hdcDst, hOldDstBitmap);
1527 hIcon = CreateIconIndirect (&ii);
1529 DeleteDC (hdcSrc);
1530 DeleteDC (hdcDst);
1531 DeleteObject (ii.hbmMask);
1532 DeleteObject (ii.hbmColor);
1534 return hIcon;
1538 /*************************************************************************
1539 * ImageList_GetIconSize [COMCTL32.60]
1541 * Retrieves the size of an image in an image list.
1543 * PARAMS
1544 * himl [I] handle to image list
1545 * cx [O] pointer to the image width.
1546 * cy [O] pointer to the image height.
1548 * RETURNS
1549 * Success: TRUE
1550 * Failure: FALSE
1552 * NOTES
1553 * All images in an image list have the same size.
1556 BOOL WINAPI
1557 ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy)
1559 if (himl == NULL)
1560 return FALSE;
1561 if ((himl->cx <= 0) || (himl->cy <= 0))
1562 return FALSE;
1564 if (cx)
1565 *cx = himl->cx;
1566 if (cy)
1567 *cy = himl->cy;
1569 return TRUE;
1573 /*************************************************************************
1574 * ImageList_GetImageCount [COMCTL32.61]
1576 * Returns the number of images in an image list.
1578 * PARAMS
1579 * himl [I] handle to image list
1581 * RETURNS
1582 * Success: Number of images.
1583 * Failure: 0
1586 INT WINAPI
1587 ImageList_GetImageCount (HIMAGELIST himl)
1589 if (himl == NULL)
1590 return 0;
1592 return himl->cCurImage;
1596 /*************************************************************************
1597 * ImageList_GetImageInfo [COMCTL32.62]
1599 * Returns information about an image in an image list.
1601 * PARAMS
1602 * himl [I] handle to image list
1603 * i [I] image index
1604 * pImageInfo [O] pointer to the image information
1606 * RETURNS
1607 * Success: TRUE
1608 * Failure: FALSE
1611 BOOL WINAPI
1612 ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
1614 if ((himl == NULL) || (pImageInfo == NULL))
1615 return FALSE;
1616 if ((i < 0) || (i >= himl->cCurImage))
1617 return FALSE;
1619 pImageInfo->hbmImage = himl->hbmImage;
1620 pImageInfo->hbmMask = himl->hbmMask;
1622 pImageInfo->rcImage.top = 0;
1623 pImageInfo->rcImage.bottom = himl->cy;
1624 pImageInfo->rcImage.left = i * himl->cx;
1625 pImageInfo->rcImage.right = (i+1) * himl->cx;
1627 return TRUE;
1631 /*************************************************************************
1632 * ImageList_GetImageRect [COMCTL32.63]
1634 * Retrieves the rectangle of the specified image in an image list.
1636 * PARAMS
1637 * himl [I] handle to image list
1638 * i [I] image index
1639 * lpRect [O] pointer to the image rectangle
1641 * RETURNS
1642 * Success: TRUE
1643 * Failure: FALSE
1645 * NOTES
1646 * This is an UNDOCUMENTED function!!!
1649 BOOL WINAPI
1650 ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect)
1652 if ((himl == NULL) || (lpRect == NULL))
1653 return FALSE;
1654 if ((i < 0) || (i >= himl->cCurImage))
1655 return FALSE;
1657 lpRect->left = i * himl->cx;
1658 lpRect->top = 0;
1659 lpRect->right = lpRect->left + himl->cx;
1660 lpRect->bottom = himl->cy;
1662 return TRUE;
1666 /*************************************************************************
1667 * ImageList_LoadImage [COMCTL32.64]
1668 * ImageList_LoadImageA [COMCTL32.65]
1670 * Creates an image list from a bitmap, icon or cursor.
1672 * PARAMS
1673 * hi [I] instance handle
1674 * lpbmp [I] name or id of the image
1675 * cx [I] width of each image
1676 * cGrow [I] number of images to expand
1677 * clrMask [I] mask color
1678 * uType [I] type of image to load
1679 * uFlags [I] loading flags
1681 * RETURNS
1682 * Success: handle to the loaded image list
1683 * Failure: NULL
1685 * SEE
1686 * LoadImage ()
1689 HIMAGELIST WINAPI
1690 ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx, INT cGrow,
1691 COLORREF clrMask, UINT uType, UINT uFlags)
1693 HIMAGELIST himl = NULL;
1694 HANDLE handle;
1695 INT nImageCount;
1697 handle = LoadImageA (hi, lpbmp, uType, 0, 0, uFlags);
1698 if (!handle) {
1699 ERR("Error loading image!\n");
1700 return NULL;
1703 if (uType == IMAGE_BITMAP) {
1704 BITMAP bmp;
1705 GetObjectA (handle, sizeof(BITMAP), &bmp);
1707 /* To match windows behavior, if cx is set to zero and
1708 the flag DI_DEFAULTSIZE is specified, cx becomes the
1709 system metric value for icons. If the flag is not specified
1710 the function sets the size to the height of the bitmap */
1711 if (cx == 0)
1713 if (uFlags & DI_DEFAULTSIZE)
1714 cx = GetSystemMetrics (SM_CXICON);
1715 else
1716 cx = bmp.bmHeight;
1719 nImageCount = bmp.bmWidth / cx;
1721 himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1722 nImageCount, cGrow);
1723 ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1725 else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1726 ICONINFO ii;
1727 BITMAP bmp;
1729 GetIconInfo (handle, &ii);
1730 GetObjectA (ii.hbmColor, sizeof(BITMAP), (LPVOID)&bmp);
1731 himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1732 ILC_MASK | ILC_COLOR, 1, cGrow);
1733 ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1734 DeleteObject (ii.hbmColor);
1735 DeleteObject (ii.hbmMask);
1738 DeleteObject (handle);
1740 return himl;
1744 /*************************************************************************
1745 * ImageList_LoadImageW [COMCTL32.66]
1747 * Creates an image list from a bitmap, icon or cursor.
1749 * PARAMS
1750 * hi [I] instance handle
1751 * lpbmp [I] name or id of the image
1752 * cx [I] width of each image
1753 * cGrow [I] number of images to expand
1754 * clrMask [I] mask color
1755 * uType [I] type of image to load
1756 * uFlags [I] loading flags
1758 * RETURNS
1759 * Success: handle to the loaded image list
1760 * Failure: NULL
1762 * SEE
1763 * LoadImage ()
1766 HIMAGELIST WINAPI
1767 ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow,
1768 COLORREF clrMask, UINT uType, UINT uFlags)
1770 HIMAGELIST himl = NULL;
1771 HANDLE handle;
1772 INT nImageCount;
1774 handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags);
1775 if (!handle) {
1776 ERR("Error loading image!\n");
1777 return NULL;
1780 if (uType == IMAGE_BITMAP) {
1781 BITMAP bmp;
1782 GetObjectA (handle, sizeof(BITMAP), &bmp);
1783 nImageCount = bmp.bmWidth / cx;
1785 himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1786 nImageCount, cGrow);
1787 ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1789 else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1790 ICONINFO ii;
1791 BITMAP bmp;
1793 GetIconInfo (handle, &ii);
1794 GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
1795 himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1796 ILC_MASK | ILC_COLOR, 1, cGrow);
1797 ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1798 DeleteObject (ii.hbmColor);
1799 DeleteObject (ii.hbmMask);
1802 DeleteObject (handle);
1804 return himl;
1808 /*************************************************************************
1809 * ImageList_Merge [COMCTL32.67]
1811 * Creates a new image list that contains a merged image from the specified
1812 * images of both source image lists.
1814 * PARAMS
1815 * himl1 [I] handle to first image list
1816 * i1 [I] first image index
1817 * himl2 [I] handle to second image list
1818 * i2 [I] second image index
1819 * dx [I] X offset of the second image relative to the first.
1820 * dy [I] Y offset of the second image relative to the first.
1822 * RETURNS
1823 * Success: handle of the merged image list.
1824 * Failure: NULL
1827 HIMAGELIST WINAPI
1828 ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
1829 INT dx, INT dy)
1831 HIMAGELIST himlDst = NULL;
1832 HDC hdcSrcImage, hdcDstImage;
1833 INT cxDst, cyDst;
1834 INT xOff1, yOff1, xOff2, yOff2;
1835 INT nX1, nX2;
1837 if ((himl1 == NULL) || (himl2 == NULL))
1838 return NULL;
1840 /* check indices */
1841 if ((i1 < 0) || (i1 >= himl1->cCurImage)) {
1842 ERR("Index 1 out of range! %d\n", i1);
1843 return NULL;
1846 if ((i2 < 0) || (i2 >= himl2->cCurImage)) {
1847 ERR("Index 2 out of range! %d\n", i2);
1848 return NULL;
1851 if (dx > 0) {
1852 cxDst = max (himl1->cx, dx + himl2->cx);
1853 xOff1 = 0;
1854 xOff2 = dx;
1856 else if (dx < 0) {
1857 cxDst = max (himl2->cx, himl1->cx - dx);
1858 xOff1 = -dx;
1859 xOff2 = 0;
1861 else {
1862 cxDst = max (himl1->cx, himl2->cx);
1863 xOff1 = 0;
1864 xOff2 = 0;
1867 if (dy > 0) {
1868 cyDst = max (himl1->cy, dy + himl2->cy);
1869 yOff1 = 0;
1870 yOff2 = dy;
1872 else if (dy < 0) {
1873 cyDst = max (himl2->cy, himl1->cy - dy);
1874 yOff1 = -dy;
1875 yOff2 = 0;
1877 else {
1878 cyDst = max (himl1->cy, himl2->cy);
1879 yOff1 = 0;
1880 yOff2 = 0;
1883 himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
1885 if (himlDst) {
1886 hdcSrcImage = CreateCompatibleDC (0);
1887 hdcDstImage = CreateCompatibleDC (0);
1888 nX1 = i1 * himl1->cx;
1889 nX2 = i2 * himl2->cx;
1891 /* copy image */
1892 SelectObject (hdcSrcImage, himl1->hbmImage);
1893 SelectObject (hdcDstImage, himlDst->hbmImage);
1894 BitBlt (hdcDstImage, 0, 0, cxDst, cyDst,
1895 hdcSrcImage, 0, 0, BLACKNESS);
1896 BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy,
1897 hdcSrcImage, nX1, 0, SRCCOPY);
1899 SelectObject (hdcSrcImage, himl2->hbmMask);
1900 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1901 hdcSrcImage, nX2, 0, SRCAND);
1903 SelectObject (hdcSrcImage, himl2->hbmImage);
1904 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1905 hdcSrcImage, nX2, 0, SRCPAINT);
1907 /* copy mask */
1908 SelectObject (hdcSrcImage, himl1->hbmMask);
1909 SelectObject (hdcDstImage, himlDst->hbmMask);
1910 BitBlt (hdcDstImage, 0, 0, cxDst, cyDst,
1911 hdcSrcImage, 0, 0, WHITENESS);
1912 BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy,
1913 hdcSrcImage, nX1, 0, SRCCOPY);
1915 SelectObject (hdcSrcImage, himl2->hbmMask);
1916 BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,
1917 hdcSrcImage, nX2, 0, SRCAND);
1919 DeleteDC (hdcSrcImage);
1920 DeleteDC (hdcDstImage);
1923 return himlDst;
1927 /* helper for _read_bitmap currently unused */
1928 #if 0
1929 static int may_use_dibsection(HDC hdc) {
1930 int bitspixel = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES);
1931 if (bitspixel>8)
1932 return TRUE;
1933 if (bitspixel<=4)
1934 return FALSE;
1935 return GetDeviceCaps(hdc,CAPS1) & C1_DIBENGINE;
1937 #endif
1939 /* helper for ImageList_Read, see comments below */
1940 static HBITMAP _read_bitmap(LPSTREAM pstm,int ilcFlag,int cx,int cy) {
1941 HDC xdc = 0;
1942 BITMAPFILEHEADER bmfh;
1943 BITMAPINFOHEADER bmih;
1944 int bitsperpixel,palspace,longsperline,width,height;
1945 LPBITMAPINFOHEADER bmihc = NULL;
1946 int result = 0;
1947 HBITMAP hbitmap = 0;
1948 LPBYTE bits = NULL,nbits = NULL;
1949 int nbytesperline,bytesperline;
1951 if (!SUCCEEDED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL)) ||
1952 (bmfh.bfType != (('M'<<8)|'B')) ||
1953 !SUCCEEDED(IStream_Read ( pstm, &bmih, sizeof(bmih), NULL)) ||
1954 (bmih.biSize != sizeof(bmih))
1956 return 0;
1958 bitsperpixel = bmih.biPlanes * bmih.biBitCount;
1959 if (bitsperpixel<=8)
1960 palspace = (1<<bitsperpixel)*sizeof(RGBQUAD);
1961 else
1962 palspace = 0;
1963 width = bmih.biWidth;
1964 height = bmih.biHeight;
1965 bmihc = (LPBITMAPINFOHEADER)LocalAlloc(LMEM_ZEROINIT,sizeof(bmih)+palspace);
1966 memcpy(bmihc,&bmih,sizeof(bmih));
1967 longsperline = ((width*bitsperpixel+31)&~0x1f)>>5;
1968 bmihc->biSizeImage = (longsperline*height)<<2;
1970 /* read the palette right after the end of the bitmapinfoheader */
1971 if (palspace)
1972 if (!SUCCEEDED(IStream_Read ( pstm, bmihc+1, palspace, NULL)))
1973 goto ret1;
1975 xdc = GetDC(0);
1976 #if 0 /* Magic for NxM -> 1x(N*M) not implemented for DIB Sections */
1977 if ((bitsperpixel>1) &&
1978 ((ilcFlag!=ILC_COLORDDB) && (!ilcFlag || may_use_dibsection(xdc)))
1980 hbitmap = CreateDIBSection(xdc,(BITMAPINFO*)bmihc,0,(LPVOID*)&bits,0,0);
1981 if (!hbitmap)
1982 goto ret1;
1983 if (!SUCCEEDED(IStream_Read( pstm, bits, bmihc->biSizeImage, NULL)))
1984 goto ret1;
1985 result = 1;
1986 } else
1987 #endif
1989 int i,nwidth,nheight;
1991 nwidth = width*(height/cy);
1992 nheight = cy;
1994 if (bitsperpixel==1)
1995 hbitmap = CreateBitmap(nwidth,nheight,1,1,NULL);
1996 else
1997 hbitmap = CreateCompatibleBitmap(xdc,nwidth,nheight);
1999 /* Might be a bit excessive memory use here */
2000 bits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage);
2001 nbits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage);
2002 if (!SUCCEEDED(IStream_Read ( pstm, bits, bmihc->biSizeImage, NULL)))
2003 goto ret1;
2005 /* Copy the NxM bitmap into a 1x(N*M) bitmap we need, linewise */
2006 /* Do not forget that windows bitmaps are bottom->top */
2007 bytesperline = longsperline*4;
2008 nbytesperline = (height/cy)*bytesperline;
2009 for (i=0;i<height;i++) {
2010 memcpy(
2011 nbits+((height-1-i)%cy)*nbytesperline+(i/cy)*bytesperline,
2012 bits+bytesperline*(height-1-i),
2013 bytesperline
2016 bmihc->biWidth = nwidth;
2017 bmihc->biHeight = nheight;
2018 if (!SetDIBits(xdc,hbitmap,0,nheight,nbits,(BITMAPINFO*)bmihc,0))
2019 goto ret1;
2020 LocalFree((HLOCAL)nbits);
2021 LocalFree((HLOCAL)bits);
2022 result = 1;
2024 ret1:
2025 if (xdc) ReleaseDC(0,xdc);
2026 if (bmihc) LocalFree((HLOCAL)bmihc);
2027 if (!result) {
2028 if (hbitmap) {
2029 DeleteObject(hbitmap);
2030 hbitmap = 0;
2033 return hbitmap;
2036 /*************************************************************************
2037 * ImageList_Read [COMCTL32.68]
2039 * Reads an image list from a stream.
2041 * PARAMS
2042 * pstm [I] pointer to a stream
2044 * RETURNS
2045 * Success: handle to image list
2046 * Failure: NULL
2048 * The format is like this:
2049 * ILHEAD ilheadstruct;
2051 * for the color image part:
2052 * BITMAPFILEHEADER bmfh;
2053 * BITMAPINFOHEADER bmih;
2054 * only if it has a palette:
2055 * RGBQUAD rgbs[nr_of_paletted_colors];
2057 * BYTE colorbits[imagesize];
2059 * the following only if the ILC_MASK bit is set in ILHEAD.ilFlags:
2060 * BITMAPFILEHEADER bmfh_mask;
2061 * BITMAPINFOHEADER bmih_mask;
2062 * only if it has a palette (it usually does not):
2063 * RGBQUAD rgbs[nr_of_paletted_colors];
2065 * BYTE maskbits[imagesize];
2067 * CAVEAT: Those images are within a NxM bitmap, not the 1xN we expect.
2068 * _read_bitmap needs to convert them.
2070 HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
2072 ILHEAD ilHead;
2073 HIMAGELIST himl;
2074 HBITMAP hbmColor=0,hbmMask=0;
2075 int i;
2077 if (!SUCCEEDED(IStream_Read (pstm, &ilHead, sizeof(ILHEAD), NULL)))
2078 return NULL;
2079 if (ilHead.usMagic != (('L' << 8) | 'I'))
2080 return NULL;
2081 if (ilHead.usVersion != 0x101) /* probably version? */
2082 return NULL;
2084 #if 0
2085 FIXME(" ilHead.cCurImage = %d\n",ilHead.cCurImage);
2086 FIXME(" ilHead.cMaxImage = %d\n",ilHead.cMaxImage);
2087 FIXME(" ilHead.cGrow = %d\n",ilHead.cGrow);
2088 FIXME(" ilHead.cx = %d\n",ilHead.cx);
2089 FIXME(" ilHead.cy = %d\n",ilHead.cy);
2090 FIXME(" ilHead.flags = %x\n",ilHead.flags);
2091 FIXME(" ilHead.ovls[0] = %d\n",ilHead.ovls[0]);
2092 FIXME(" ilHead.ovls[1] = %d\n",ilHead.ovls[1]);
2093 FIXME(" ilHead.ovls[2] = %d\n",ilHead.ovls[2]);
2094 FIXME(" ilHead.ovls[3] = %d\n",ilHead.ovls[3]);
2095 #endif
2097 hbmColor = _read_bitmap(pstm,ilHead.flags & ~ILC_MASK,ilHead.cx,ilHead.cy);
2098 if (!hbmColor)
2099 return NULL;
2100 if (ilHead.flags & ILC_MASK) {
2101 hbmMask = _read_bitmap(pstm,0,ilHead.cx,ilHead.cy);
2102 if (!hbmMask) {
2103 DeleteObject(hbmColor);
2104 return NULL;
2108 himl = ImageList_Create (
2109 ilHead.cx,
2110 ilHead.cy,
2111 ilHead.flags,
2112 1, /* initial */
2113 ilHead.cGrow
2115 if (!himl) {
2116 DeleteObject(hbmColor);
2117 DeleteObject(hbmMask);
2118 return NULL;
2120 himl->hbmImage = hbmColor;
2121 himl->hbmMask = hbmMask;
2122 himl->cCurImage = ilHead.cCurImage;
2123 himl->cMaxImage = ilHead.cMaxImage;
2125 ImageList_SetBkColor(himl,ilHead.bkcolor);
2126 for (i=0;i<4;i++)
2127 ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1);
2128 return himl;
2132 /*************************************************************************
2133 * ImageList_Remove [COMCTL32.69] Removes an image from an image list
2135 * PARAMS
2136 * himl [I] image list handle
2137 * i [I] image index
2139 * RETURNS
2140 * Success: TRUE
2141 * Failure: FALSE
2144 BOOL WINAPI
2145 ImageList_Remove (HIMAGELIST himl, INT i)
2147 HBITMAP hbmNewImage, hbmNewMask;
2148 HDC hdcSrc, hdcDst;
2149 INT cxNew, nCount;
2151 if (himl == NULL) {
2152 ERR("Invalid image list handle!\n");
2153 return FALSE;
2156 if ((i < -1) || (i >= himl->cCurImage)) {
2157 ERR("index out of range! %d\n", i);
2158 return FALSE;
2161 if (himl->cCurImage == 0) {
2162 ERR("image list is already empty!\n");
2163 return FALSE;
2166 if (i == -1) {
2167 /* remove all */
2168 TRACE("remove all!\n");
2170 himl->cMaxImage = himl->cInitial + himl->cGrow;
2171 himl->cCurImage = 0;
2172 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2173 himl->nOvlIdx[nCount] = -1;
2175 DeleteObject (himl->hbmImage);
2176 himl->hbmImage =
2177 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2178 1, himl->uBitsPixel, NULL);
2180 if (himl->hbmMask) {
2181 DeleteObject (himl->hbmMask);
2182 himl->hbmMask =
2183 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2184 1, 1, NULL);
2187 else {
2188 /* delete one image */
2189 TRACE("Remove single image! %d\n", i);
2191 /* create new bitmap(s) */
2192 cxNew = (himl->cCurImage + himl->cGrow - 1) * himl->cx;
2194 TRACE(" - Number of images: %d / %d (Old/New)\n",
2195 himl->cCurImage, himl->cCurImage - 1);
2196 TRACE(" - Max. number of images: %d / %d (Old/New)\n",
2197 himl->cMaxImage, himl->cCurImage + himl->cGrow - 1);
2199 hbmNewImage =
2200 CreateBitmap (cxNew, himl->cy, 1, himl->uBitsPixel, NULL);
2202 if (himl->hbmMask)
2203 hbmNewMask = CreateBitmap (cxNew, himl->cy, 1, 1, NULL);
2204 else
2205 hbmNewMask = 0; /* Just to keep compiler happy! */
2207 hdcSrc = CreateCompatibleDC (0);
2208 hdcDst = CreateCompatibleDC (0);
2210 /* copy all images and masks prior to the "removed" image */
2211 if (i > 0) {
2212 TRACE("Pre image copy: Copy %d images\n", i);
2214 SelectObject (hdcSrc, himl->hbmImage);
2215 SelectObject (hdcDst, hbmNewImage);
2216 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2217 hdcSrc, 0, 0, SRCCOPY);
2219 if (himl->hbmMask) {
2220 SelectObject (hdcSrc, himl->hbmMask);
2221 SelectObject (hdcDst, hbmNewMask);
2222 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2223 hdcSrc, 0, 0, SRCCOPY);
2227 /* copy all images and masks behind the removed image */
2228 if (i < himl->cCurImage - 1) {
2229 TRACE("Post image copy!\n");
2230 SelectObject (hdcSrc, himl->hbmImage);
2231 SelectObject (hdcDst, hbmNewImage);
2232 BitBlt (hdcDst, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx,
2233 himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2235 if (himl->hbmMask) {
2236 SelectObject (hdcSrc, himl->hbmMask);
2237 SelectObject (hdcDst, hbmNewMask);
2238 BitBlt (hdcDst, i * himl->cx, 0,
2239 (himl->cCurImage - i - 1) * himl->cx,
2240 himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2244 DeleteDC (hdcSrc);
2245 DeleteDC (hdcDst);
2247 /* delete old images and insert new ones */
2248 DeleteObject (himl->hbmImage);
2249 himl->hbmImage = hbmNewImage;
2250 if (himl->hbmMask) {
2251 DeleteObject (himl->hbmMask);
2252 himl->hbmMask = hbmNewMask;
2255 himl->cCurImage--;
2256 himl->cMaxImage = himl->cCurImage + himl->cGrow;
2259 return TRUE;
2263 /*************************************************************************
2264 * ImageList_Replace [COMCTL32.70]
2266 * Replaces an image in an image list with a new image.
2268 * PARAMS
2269 * himl [I] handle to image list
2270 * i [I] image index
2271 * hbmImage [I] handle to image bitmap
2272 * hbmMask [I] handle to mask bitmap. Can be NULL.
2274 * RETURNS
2275 * Success: TRUE
2276 * Failure: FALSE
2279 BOOL WINAPI
2280 ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage,
2281 HBITMAP hbmMask)
2283 HDC hdcImageList, hdcImage;
2284 BITMAP bmp;
2286 if (himl == NULL) {
2287 ERR("Invalid image list handle!\n");
2288 return FALSE;
2291 if ((i >= himl->cMaxImage) || (i < 0)) {
2292 ERR("Invalid image index!\n");
2293 return FALSE;
2296 hdcImageList = CreateCompatibleDC (0);
2297 hdcImage = CreateCompatibleDC (0);
2298 GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
2300 /* Replace Image */
2301 SelectObject (hdcImageList, himl->hbmImage);
2302 SelectObject (hdcImage, hbmImage);
2304 StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2305 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2307 if (himl->hbmMask)
2309 /* Replace Mask */
2310 SelectObject (hdcImageList, himl->hbmMask);
2311 SelectObject (hdcImage, hbmMask);
2313 StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2314 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2317 /* Remove the background from the image
2319 SelectObject (hdcImageList, himl->hbmImage);
2320 StretchBlt (hdcImageList,
2321 i*himl->cx, 0, himl->cx, himl->cy,
2322 hdcImage,
2323 0, 0, bmp.bmWidth, bmp.bmHeight,
2324 0x220326); /* NOTSRCAND */
2327 DeleteDC (hdcImage);
2328 DeleteDC (hdcImageList);
2330 return TRUE;
2334 /*************************************************************************
2335 * ImageList_ReplaceIcon [COMCTL32.75]
2337 * Replaces an image in an image list using an icon.
2339 * PARAMS
2340 * himl [I] handle to image list
2341 * i [I] image index
2342 * hIcon [I] handle to icon
2344 * RETURNS
2345 * Success: index of the replaced image
2346 * Failure: -1
2349 INT WINAPI
2350 ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon)
2352 HDC hdcImageList, hdcImage;
2353 INT nIndex;
2354 HICON hBestFitIcon;
2355 HBITMAP hbmOldSrc, hbmOldDst;
2356 ICONINFO ii;
2357 BITMAP bmp;
2359 TRACE("(0x%lx 0x%x 0x%x)\n", (DWORD)himl, i, hIcon);
2361 if (himl == NULL)
2362 return -1;
2363 if ((i >= himl->cMaxImage) || (i < -1))
2364 return -1;
2366 hBestFitIcon = CopyImage(
2367 hIcon, IMAGE_ICON,
2368 himl->cx, himl->cy,
2369 LR_COPYFROMRESOURCE);
2371 GetIconInfo (hBestFitIcon, &ii);
2372 if (ii.hbmMask == 0)
2373 ERR("no mask!\n");
2374 if (ii.hbmColor == 0)
2375 ERR("no color!\n");
2376 GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
2378 if (i == -1) {
2379 if (himl->cCurImage + 1 >= himl->cMaxImage)
2380 IMAGELIST_InternalExpandBitmaps (himl, 1, 0, 0);
2382 nIndex = himl->cCurImage;
2383 himl->cCurImage++;
2385 else
2386 nIndex = i;
2388 hdcImageList = CreateCompatibleDC (0);
2389 TRACE("hdcImageList=0x%x!\n", hdcImageList);
2390 if (hdcImageList == 0)
2391 ERR("invalid hdcImageList!\n");
2393 hdcImage = CreateCompatibleDC (0);
2394 TRACE("hdcImage=0x%x!\n", hdcImage);
2395 if (hdcImage == 0)
2396 ERR("invalid hdcImage!\n");
2398 hbmOldDst = SelectObject (hdcImageList, himl->hbmImage);
2399 SetTextColor( hdcImageList, RGB(0,0,0));
2400 SetBkColor( hdcImageList, RGB(255,255,255));
2401 hbmOldSrc = SelectObject (hdcImage, ii.hbmColor);
2402 StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2403 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2405 if (himl->hbmMask) {
2406 SelectObject (hdcImageList, himl->hbmMask);
2407 SelectObject (hdcImage, ii.hbmMask);
2408 StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2409 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2412 SelectObject (hdcImage, hbmOldSrc);
2413 SelectObject (hdcImageList, hbmOldDst);
2415 if(hBestFitIcon)
2416 DestroyIcon(hBestFitIcon);
2417 if (hdcImageList)
2418 DeleteDC (hdcImageList);
2419 if (hdcImage)
2420 DeleteDC (hdcImage);
2421 if (ii.hbmColor)
2422 DeleteObject (ii.hbmColor);
2423 if (ii.hbmMask)
2424 DeleteObject (ii.hbmMask);
2426 return nIndex;
2430 /*************************************************************************
2431 * ImageList_SetBkColor [COMCTL32.76]
2433 * Sets the background color of an image list.
2435 * PARAMS
2436 * himl [I] handle to image list
2437 * clrBk [I] background color
2439 * RETURNS
2440 * Success: previous background color
2441 * Failure: CLR_NONE
2444 COLORREF WINAPI
2445 ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
2447 COLORREF clrOldBk;
2449 if (himl == NULL)
2450 return CLR_NONE;
2452 clrOldBk = himl->clrBk;
2453 himl->clrBk = clrBk;
2454 return clrOldBk;
2458 /*************************************************************************
2459 * ImageList_SetDragCursorImage [COMCTL32.77]
2461 * Combines the specified image with the current drag image
2463 * PARAMS
2464 * himlDrag [I] handle to drag image list
2465 * iDrag [I] drag image index
2466 * dxHotspot [I] X position of the hot spot
2467 * dyHotspot [I] Y position of the hot spot
2469 * RETURNS
2470 * Success: TRUE
2471 * Failure: FALSE
2473 * BUGS
2474 * semi-stub.
2477 BOOL WINAPI
2478 ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag,
2479 INT dxHotspot, INT dyHotspot)
2481 HIMAGELIST himlTemp;
2483 FIXME("semi-stub!\n");
2485 if (himlInternalDrag == NULL)
2486 return FALSE;
2488 TRACE(" dxH=%d dyH=%d nX=%d nY=%d\n",
2489 dxHotspot, dyHotspot, nInternalDragHotspotX, nInternalDragHotspotY);
2491 himlTemp = ImageList_Merge (himlInternalDrag, 0, himlDrag, iDrag,
2492 dxHotspot, dyHotspot);
2494 ImageList_Destroy (himlInternalDrag);
2495 himlInternalDrag = himlTemp;
2497 nInternalDragHotspotX = dxHotspot;
2498 nInternalDragHotspotY = dyHotspot;
2500 return FALSE;
2504 /*************************************************************************
2505 * ImageList_SetFilter [COMCTL32.78]
2507 * Sets a filter (or does something completely different)!!???
2509 * PARAMS
2510 * himl [I] handle to image list
2511 * i [I] ???
2512 * dwFilter [I] ???
2514 * RETURNS
2515 * Success: TRUE ???
2516 * Failure: FALSE ???
2518 * BUGS
2519 * This is an UNDOCUMENTED function!!!!
2520 * empty stub.
2523 BOOL WINAPI
2524 ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter)
2526 FIXME("(%p 0x%x 0x%lx):empty stub!\n",
2527 himl, i, dwFilter);
2529 return FALSE;
2533 /*************************************************************************
2534 * ImageList_SetIconSize [COMCTL32.80]
2536 * Sets the image size of the bitmap and deletes all images.
2538 * PARAMS
2539 * himl [I] handle to image list
2540 * cx [I] image width
2541 * cy [I] image height
2543 * RETURNS
2544 * Success: TRUE
2545 * Failure: FALSE
2548 BOOL WINAPI
2549 ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy)
2551 INT nCount;
2553 if (!himl)
2554 return FALSE;
2556 /* remove all images */
2557 himl->cMaxImage = himl->cInitial + himl->cGrow;
2558 himl->cCurImage = 0;
2559 himl->cx = cx;
2560 himl->cy = cy;
2562 /* initialize overlay mask indices */
2563 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2564 himl->nOvlIdx[nCount] = -1;
2566 DeleteObject (himl->hbmImage);
2567 himl->hbmImage =
2568 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2569 1, himl->uBitsPixel, NULL);
2571 if (himl->hbmMask) {
2572 DeleteObject (himl->hbmMask);
2573 himl->hbmMask =
2574 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2575 1, 1, NULL);
2578 return TRUE;
2582 /*************************************************************************
2583 * ImageList_SetImageCount [COMCTL32.81]
2585 * Resizes an image list to the specified number of images.
2587 * PARAMS
2588 * himl [I] handle to image list
2589 * iImageCount [I] number of images in the image list
2591 * RETURNS
2592 * Success: TRUE
2593 * Failure: FALSE
2596 BOOL WINAPI
2597 ImageList_SetImageCount (HIMAGELIST himl, INT iImageCount)
2599 HDC hdcImageList, hdcBitmap;
2600 HBITMAP hbmNewBitmap;
2601 INT nNewCount, nCopyCount;
2603 if (!himl)
2604 return FALSE;
2605 if (himl->cCurImage >= iImageCount)
2606 return FALSE;
2607 if (himl->cMaxImage > iImageCount)
2608 return TRUE;
2610 nNewCount = iImageCount + himl->cGrow;
2611 nCopyCount = min(himl->cCurImage, iImageCount);
2613 hdcImageList = CreateCompatibleDC (0);
2614 hdcBitmap = CreateCompatibleDC (0);
2616 hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2617 1, himl->uBitsPixel, NULL);
2618 if (hbmNewBitmap != 0)
2620 SelectObject (hdcImageList, himl->hbmImage);
2621 SelectObject (hdcBitmap, hbmNewBitmap);
2623 /* copy images */
2624 BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2625 hdcImageList, 0, 0, SRCCOPY);
2626 #if 0
2627 /* delete 'empty' image space */
2628 SetBkColor (hdcBitmap, RGB(255, 255, 255));
2629 SetTextColor (hdcBitmap, RGB(0, 0, 0));
2630 PatBlt (hdcBitmap, nCopyCount * himl->cx, 0,
2631 (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2632 #endif
2633 DeleteObject (himl->hbmImage);
2634 himl->hbmImage = hbmNewBitmap;
2636 else
2637 ERR("Could not create new image bitmap !\n");
2639 if (himl->hbmMask)
2641 hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2642 1, 1, NULL);
2643 if (hbmNewBitmap != 0)
2645 SelectObject (hdcImageList, himl->hbmMask);
2646 SelectObject (hdcBitmap, hbmNewBitmap);
2648 /* copy images */
2649 BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2650 hdcImageList, 0, 0, SRCCOPY);
2651 #if 0
2652 /* delete 'empty' image space */
2653 SetBkColor (hdcBitmap, RGB(255, 255, 255));
2654 SetTextColor (hdcBitmap, RGB(0, 0, 0));
2655 PatBlt (hdcBitmap, nCopyCount * himl->cx, 0,
2656 (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2657 #endif
2658 DeleteObject (himl->hbmMask);
2659 himl->hbmMask = hbmNewBitmap;
2661 else
2662 ERR("Could not create new mask bitmap!\n");
2665 DeleteDC (hdcImageList);
2666 DeleteDC (hdcBitmap);
2668 /* Update max image count and current image count */
2669 himl->cMaxImage = nNewCount;
2670 if (himl->cCurImage > nCopyCount)
2671 himl->cCurImage = nCopyCount;
2673 return TRUE;
2677 /*************************************************************************
2678 * ImageList_SetOverlayImage [COMCTL32.82]
2680 * Assigns an overlay mask index to an existing image in an image list.
2682 * PARAMS
2683 * himl [I] handle to image list
2684 * iImage [I] image index
2685 * iOverlay [I] overlay mask index
2687 * RETURNS
2688 * Success: TRUE
2689 * Failure: FALSE
2692 BOOL WINAPI
2693 ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay)
2695 if (!himl)
2696 return FALSE;
2697 if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
2698 return FALSE;
2699 if ((iImage!=-1) && ((iImage < 0) || (iImage > himl->cCurImage)))
2700 return FALSE;
2701 himl->nOvlIdx[iOverlay - 1] = iImage;
2702 return TRUE;
2706 /*************************************************************************
2707 * ImageList_Write [COMCTL32.83]
2709 * Writes an image list to a stream.
2711 * PARAMS
2712 * himl [I] handle to image list
2713 * pstm [O] Pointer to a stream.
2715 * RETURNS
2716 * Success: TRUE
2717 * Failure: FALSE
2719 * NOTES
2720 * This function can not be implemented yet, because
2721 * IStream32::Write is not implemented.
2723 * BUGS
2724 * empty stub.
2727 BOOL WINAPI
2728 ImageList_Write (HIMAGELIST himl, LPSTREAM pstm)
2730 if (!himl)
2731 return FALSE;
2733 FIXME("empty stub!\n");
2735 return FALSE;