Add entry for int 2 handler.
[wine/wine-kai.git] / dlls / comctl32 / imagelist.c
blobdc191e4a755c611c630dd8d5e0d4c992db78b398
1 /*
2 * ImageList implementation
4 * Copyright 1998 Eric Kohl
5 * Copyright 2000 Jason Mawdsley
6 * Copyright 2001, 2004 Michael Stefaniuc
7 * Copyright 2001 Charles Loep for CodeWeavers
8 * Copyright 2002 Dimitrie O. Paun
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * NOTE
26 * This code was audited for completeness against the documented features
27 * of Comctl32.dll version 6.0 on Sep. 12, 2002, by Dimitrie O. Paun.
29 * Unless otherwise noted, we believe this code to be complete, as per
30 * the specification mentioned above.
31 * If you discover missing features, or bugs, please note them below.
33 * TODO:
34 * - Add support for ILD_PRESERVEALPHA, ILD_SCALE, ILD_DPISCALE
35 * - Add support for ILS_GLOW, ILS_SHADOW, ILS_SATURATE, ILS_ALPHA
36 * - Thread-safe locking
39 #include <stdarg.h>
40 #include <stdlib.h>
41 #include <string.h>
43 #define COBJMACROS
45 #include "winerror.h"
46 #include "windef.h"
47 #include "winbase.h"
48 #include "objbase.h"
49 #include "wingdi.h"
50 #include "winuser.h"
51 #include "commctrl.h"
52 #include "comctl32.h"
53 #include "imagelist.h"
54 #include "wine/debug.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(imagelist);
59 #define MAX_OVERLAYIMAGE 15
61 /* internal image list data used for Drag & Drop operations */
62 typedef struct
64 HWND hwnd;
65 HIMAGELIST himl;
66 /* position of the drag image relative to the window */
67 INT x;
68 INT y;
69 /* offset of the hotspot relative to the origin of the image */
70 INT dxHotspot;
71 INT dyHotspot;
72 /* is the drag image visible */
73 BOOL bShow;
74 /* saved background */
75 HBITMAP hbmBg;
76 } INTERNALDRAG;
78 static INTERNALDRAG InternalDrag = { 0, 0, 0, 0, 0, 0, FALSE, 0 };
80 static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT width, UINT height);
82 static inline BOOL is_valid(HIMAGELIST himl)
84 return himl && himl->magic == IMAGELIST_MAGIC;
88 /*************************************************************************
89 * IMAGELIST_InternalExpandBitmaps [Internal]
91 * Expands the bitmaps of an image list by the given number of images.
93 * PARAMS
94 * himl [I] handle to image list
95 * nImageCount [I] number of images to add
97 * RETURNS
98 * nothing
100 * NOTES
101 * This function CANNOT be used to reduce the number of images.
103 static void
104 IMAGELIST_InternalExpandBitmaps (HIMAGELIST himl, INT nImageCount, INT cx, INT cy)
106 HDC hdcBitmap;
107 HBITMAP hbmNewBitmap, hbmNull;
108 INT nNewWidth, nNewCount;
110 if ((himl->cCurImage + nImageCount <= himl->cMaxImage)
111 && (himl->cy >= cy))
112 return;
114 if (cy == 0) cy = himl->cy;
115 nNewCount = himl->cCurImage + nImageCount + himl->cGrow;
116 nNewWidth = nNewCount * himl->cx;
118 TRACE("Create expanded bitmaps : himl=%p x=%d y=%d count=%d\n", himl, nNewWidth, cy, nNewCount);
119 hdcBitmap = CreateCompatibleDC (0);
121 hbmNewBitmap = ImageList_CreateImage(hdcBitmap, himl, nNewWidth, cy);
123 if (hbmNewBitmap == 0)
124 ERR("creating new image bitmap (x=%d y=%d)!\n", nNewWidth, cy);
126 if(himl->cCurImage)
128 hbmNull = SelectObject (hdcBitmap, hbmNewBitmap);
129 BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy,
130 himl->hdcImage, 0, 0, SRCCOPY);
131 SelectObject (hdcBitmap, hbmNull);
133 SelectObject (himl->hdcImage, hbmNewBitmap);
134 DeleteObject (himl->hbmImage);
135 himl->hbmImage = hbmNewBitmap;
137 if (himl->flags & ILC_MASK)
139 hbmNewBitmap = CreateBitmap (nNewWidth, cy, 1, 1, NULL);
141 if (hbmNewBitmap == 0)
142 ERR("creating new mask bitmap!\n");
144 if(himl->cCurImage)
146 hbmNull = SelectObject (hdcBitmap, hbmNewBitmap);
147 BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy,
148 himl->hdcMask, 0, 0, SRCCOPY);
149 SelectObject (hdcBitmap, hbmNull);
151 SelectObject (himl->hdcMask, hbmNewBitmap);
152 DeleteObject (himl->hbmMask);
153 himl->hbmMask = hbmNewBitmap;
156 himl->cMaxImage = nNewCount;
158 DeleteDC (hdcBitmap);
162 /*************************************************************************
163 * ImageList_Add [COMCTL32.@]
165 * Add an image or images to an image list.
167 * PARAMS
168 * himl [I] handle to image list
169 * hbmImage [I] handle to image bitmap
170 * hbmMask [I] handle to mask bitmap
172 * RETURNS
173 * Success: Index of the first new image.
174 * Failure: -1
177 INT WINAPI
178 ImageList_Add (HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
180 HDC hdcBitmap;
181 INT nFirstIndex, nImageCount;
182 INT nStartX;
183 BITMAP bmp;
184 HBITMAP hOldBitmap;
186 TRACE("himl=%p hbmimage=%p hbmmask=%p\n", himl, hbmImage, hbmMask);
187 if (!is_valid(himl))
188 return -1;
190 GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
191 nImageCount = bmp.bmWidth / himl->cx;
193 IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight);
195 nStartX = himl->cCurImage * himl->cx;
197 hdcBitmap = CreateCompatibleDC(0);
199 hOldBitmap = SelectObject(hdcBitmap, hbmImage);
201 /* Copy result to the imagelist
203 BitBlt (himl->hdcImage, nStartX, 0, bmp.bmWidth, bmp.bmHeight,
204 hdcBitmap, 0, 0, SRCCOPY);
206 if(himl->hbmMask)
208 HDC hdcTemp;
209 HBITMAP hOldBitmapTemp;
211 hdcTemp = CreateCompatibleDC(0);
212 hOldBitmapTemp = SelectObject(hdcTemp, hbmMask);
214 BitBlt (himl->hdcMask,
215 nStartX, 0, bmp.bmWidth, bmp.bmHeight,
216 hdcTemp,
217 0, 0,
218 SRCCOPY);
220 SelectObject(hdcTemp, hOldBitmapTemp);
221 DeleteDC(hdcTemp);
223 /* Remove the background from the image
225 BitBlt (himl->hdcImage,
226 nStartX, 0, bmp.bmWidth, bmp.bmHeight,
227 himl->hdcMask,
228 nStartX, 0,
229 0x220326); /* NOTSRCAND */
232 SelectObject(hdcBitmap, hOldBitmap);
233 DeleteDC(hdcBitmap);
235 nFirstIndex = himl->cCurImage;
236 himl->cCurImage += nImageCount;
238 return nFirstIndex;
242 /*************************************************************************
243 * ImageList_AddIcon [COMCTL32.@]
245 * Adds an icon to an image list.
247 * PARAMS
248 * himl [I] handle to image list
249 * hIcon [I] handle to icon
251 * RETURNS
252 * Success: index of the new image
253 * Failure: -1
255 #undef ImageList_AddIcon
256 INT WINAPI ImageList_AddIcon (HIMAGELIST himl, HICON hIcon)
258 return ImageList_ReplaceIcon (himl, -1, hIcon);
262 /*************************************************************************
263 * ImageList_AddMasked [COMCTL32.@]
265 * Adds an image or images to an image list and creates a mask from the
266 * specified bitmap using the mask color.
268 * PARAMS
269 * himl [I] handle to image list.
270 * hBitmap [I] handle to bitmap
271 * clrMask [I] mask color.
273 * RETURNS
274 * Success: Index of the first new image.
275 * Failure: -1
278 INT WINAPI
279 ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
281 HDC hdcMask, hdcBitmap;
282 INT nIndex, nImageCount, nMaskXOffset=0;
283 BITMAP bmp;
284 HBITMAP hOldBitmap;
285 HBITMAP hMaskBitmap=0;
286 COLORREF bkColor;
288 TRACE("himl=%p hbitmap=%p clrmask=%lx\n", himl, hBitmap, clrMask);
289 if (!is_valid(himl))
290 return -1;
292 if (!GetObjectA (hBitmap, sizeof(BITMAP), &bmp))
293 return -1;
295 if (himl->cx > 0)
296 nImageCount = bmp.bmWidth / himl->cx;
297 else
298 nImageCount = 0;
300 IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight);
302 nIndex = himl->cCurImage;
303 himl->cCurImage += nImageCount;
305 hdcBitmap = CreateCompatibleDC(0);
308 hOldBitmap = SelectObject(hdcBitmap, hBitmap);
309 if(himl->hbmMask)
311 hdcMask = himl->hdcMask;
312 nMaskXOffset = nIndex * himl->cx;
314 else
317 Create a temp Mask so we can remove the background of
318 the Image (Windows does this even if there is no mask)
320 hdcMask = CreateCompatibleDC(0);
321 hMaskBitmap = CreateBitmap(bmp.bmWidth, bmp.bmHeight, 1, 1, NULL);
322 SelectObject(hdcMask, hMaskBitmap);
323 nMaskXOffset = 0;
325 /* create monochrome image to the mask bitmap */
326 bkColor = (clrMask != CLR_DEFAULT) ? clrMask :
327 GetPixel (hdcBitmap, 0, 0);
328 SetBkColor (hdcBitmap, bkColor);
329 BitBlt (hdcMask,
330 nMaskXOffset, 0, bmp.bmWidth, bmp.bmHeight,
331 hdcBitmap, 0, 0,
332 SRCCOPY);
334 SetBkColor(hdcBitmap, RGB(255,255,255));
335 /*Remove the background from the image
338 WINDOWS BUG ALERT!!!!!!
339 The statement below should not be done in common practice
340 but this is how ImageList_AddMasked works in Windows.
341 It overwrites the original bitmap passed, this was discovered
342 by using the same bitmap to iterate the different styles
343 on windows where it failed (BUT ImageList_Add is OK)
344 This is here in case some apps rely on this bug
346 BitBlt(hdcBitmap,
347 0, 0, bmp.bmWidth, bmp.bmHeight,
348 hdcMask,
349 nMaskXOffset, 0,
350 0x220326); /* NOTSRCAND */
351 /* Copy result to the imagelist
353 BitBlt (himl->hdcImage,
354 nIndex * himl->cx, 0, bmp.bmWidth, bmp.bmHeight,
355 hdcBitmap,
356 0, 0,
357 SRCCOPY);
358 /* Clean up
360 SelectObject(hdcBitmap, hOldBitmap);
361 DeleteDC(hdcBitmap);
362 if(!himl->hbmMask)
364 DeleteObject(hMaskBitmap);
365 DeleteDC(hdcMask);
368 return nIndex;
372 /*************************************************************************
373 * ImageList_BeginDrag [COMCTL32.@]
375 * Creates a temporary image list that contains one image. It will be used
376 * as a drag image.
378 * PARAMS
379 * himlTrack [I] handle to the source image list
380 * iTrack [I] index of the drag image in the source image list
381 * dxHotspot [I] X position of the hot spot of the drag image
382 * dyHotspot [I] Y position of the hot spot of the drag image
384 * RETURNS
385 * Success: TRUE
386 * Failure: FALSE
389 BOOL WINAPI
390 ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
391 INT dxHotspot, INT dyHotspot)
393 INT cx, cy;
395 TRACE("(himlTrack=%p iTrack=%d dx=%d dy=%d)\n", himlTrack, iTrack,
396 dxHotspot, dyHotspot);
398 if (!is_valid(himlTrack))
399 return FALSE;
401 if (InternalDrag.himl)
402 ImageList_EndDrag ();
404 cx = himlTrack->cx;
405 cy = himlTrack->cy;
407 InternalDrag.himl = ImageList_Create (cx, cy, himlTrack->flags, 1, 1);
408 if (InternalDrag.himl == NULL) {
409 WARN("Error creating drag image list!\n");
410 return FALSE;
413 InternalDrag.dxHotspot = dxHotspot;
414 InternalDrag.dyHotspot = dyHotspot;
416 /* copy image */
417 BitBlt (InternalDrag.himl->hdcImage, 0, 0, cx, cy, himlTrack->hdcImage, iTrack * cx, 0, SRCCOPY);
419 /* copy mask */
420 BitBlt (InternalDrag.himl->hdcMask, 0, 0, cx, cy, himlTrack->hdcMask, iTrack * cx, 0, SRCCOPY);
422 InternalDrag.himl->cCurImage = 1;
424 return TRUE;
428 /*************************************************************************
429 * ImageList_Copy [COMCTL32.@]
431 * Copies an image of the source image list to an image of the
432 * destination image list. Images can be copied or swapped.
434 * PARAMS
435 * himlDst [I] handle to the destination image list
436 * iDst [I] destination image index.
437 * himlSrc [I] handle to the source image list
438 * iSrc [I] source image index
439 * uFlags [I] flags for the copy operation
441 * RETURNS
442 * Success: TRUE
443 * Failure: FALSE
445 * NOTES
446 * Copying from one image list to another is possible. The original
447 * implementation just copies or swaps within one image list.
448 * Could this feature become a bug??? ;-)
451 BOOL WINAPI
452 ImageList_Copy (HIMAGELIST himlDst, INT iDst, HIMAGELIST himlSrc,
453 INT iSrc, UINT uFlags)
455 TRACE("himlDst=%p iDst=%d himlSrc=%p iSrc=%d\n", himlDst, iDst, himlSrc, iSrc);
457 if (!is_valid(himlSrc) || !is_valid(himlDst))
458 return FALSE;
459 if ((iDst < 0) || (iDst >= himlDst->cCurImage))
460 return FALSE;
461 if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage))
462 return FALSE;
464 if (uFlags & ILCF_SWAP) {
465 /* swap */
466 HDC hdcBmp;
467 HBITMAP hbmTempImage, hbmTempMask;
469 hdcBmp = CreateCompatibleDC (0);
471 /* create temporary bitmaps */
472 hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
473 himlSrc->uBitsPixel, NULL);
474 hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
475 1, NULL);
477 /* copy (and stretch) destination to temporary bitmaps.(save) */
478 /* image */
479 SelectObject (hdcBmp, hbmTempImage);
480 StretchBlt (hdcBmp, 0, 0, himlSrc->cx, himlSrc->cy,
481 himlDst->hdcImage, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
482 SRCCOPY);
483 /* mask */
484 SelectObject (hdcBmp, hbmTempMask);
485 StretchBlt (hdcBmp, 0, 0, himlSrc->cx, himlSrc->cy,
486 himlDst->hdcMask, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
487 SRCCOPY);
489 /* copy (and stretch) source to destination */
490 /* image */
491 StretchBlt (himlDst->hdcImage, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
492 himlSrc->hdcImage, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
493 SRCCOPY);
494 /* mask */
495 StretchBlt (himlDst->hdcMask, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
496 himlSrc->hdcMask, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
497 SRCCOPY);
499 /* copy (without stretching) temporary bitmaps to source (restore) */
500 /* mask */
501 BitBlt (himlSrc->hdcMask, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
502 hdcBmp, 0, 0, SRCCOPY);
504 /* image */
505 BitBlt (himlSrc->hdcImage, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
506 hdcBmp, 0, 0, SRCCOPY);
507 /* delete temporary bitmaps */
508 DeleteObject (hbmTempMask);
509 DeleteObject (hbmTempImage);
510 DeleteDC(hdcBmp);
512 else {
513 /* copy image */
514 StretchBlt (himlDst->hdcImage, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
515 himlSrc->hdcImage, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
516 SRCCOPY);
518 /* copy mask */
519 StretchBlt (himlDst->hdcMask, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
520 himlSrc->hdcMask, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
521 SRCCOPY);
524 return TRUE;
528 /*************************************************************************
529 * ImageList_Create [COMCTL32.@]
531 * Creates a new image list.
533 * PARAMS
534 * cx [I] image height
535 * cy [I] image width
536 * flags [I] creation flags
537 * cInitial [I] initial number of images in the image list
538 * cGrow [I] number of images by which image list grows
540 * RETURNS
541 * Success: Handle to the created image list
542 * Failure: NULL
544 HIMAGELIST WINAPI
545 ImageList_Create (INT cx, INT cy, UINT flags,
546 INT cInitial, INT cGrow)
548 HIMAGELIST himl;
549 INT nCount;
550 HBITMAP hbmTemp;
551 UINT ilc = (flags & 0xFE);
552 static const WORD aBitBlend25[] =
553 {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00};
555 static const WORD aBitBlend50[] =
556 {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
558 TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow);
560 himl = (HIMAGELIST)Alloc (sizeof(struct _IMAGELIST));
561 if (!himl)
562 return NULL;
564 cGrow = (cGrow < 4) ? 4 : (cGrow + 3) & ~3;
566 himl->magic = IMAGELIST_MAGIC;
567 himl->cx = cx;
568 himl->cy = cy;
569 himl->flags = flags;
570 himl->cMaxImage = cInitial + cGrow;
571 himl->cInitial = cInitial;
572 himl->cGrow = cGrow;
573 himl->clrFg = CLR_DEFAULT;
574 himl->clrBk = CLR_NONE;
576 /* initialize overlay mask indices */
577 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
578 himl->nOvlIdx[nCount] = -1;
580 /* Create Image & Mask DCs */
581 himl->hdcImage = CreateCompatibleDC (0);
582 if (!himl->hdcImage)
583 goto cleanup;
584 if (himl->flags & ILC_MASK){
585 himl->hdcMask = CreateCompatibleDC(0);
586 if (!himl->hdcMask)
587 goto cleanup;
590 /* Default to ILC_COLOR4 if none of the ILC_COLOR* flags are specified */
591 if (ilc == ILC_COLOR)
592 ilc = ILC_COLOR4;
594 if (ilc >= ILC_COLOR4 && ilc <= ILC_COLOR32)
595 himl->uBitsPixel = ilc;
596 else
597 himl->uBitsPixel = (UINT)GetDeviceCaps (himl->hdcImage, BITSPIXEL);
599 if (himl->cMaxImage > 0) {
600 himl->hbmImage = ImageList_CreateImage(himl->hdcImage, himl, cx * himl->cMaxImage, cy);
601 SelectObject(himl->hdcImage, himl->hbmImage);
602 } else
603 himl->hbmImage = 0;
605 if ((himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) {
606 himl->hbmMask =
607 CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
608 1, 1, NULL);
609 if (himl->hbmMask == 0) {
610 ERR("Error creating mask bitmap!\n");
611 goto cleanup;
613 SelectObject(himl->hdcMask, himl->hbmMask);
615 else
616 himl->hbmMask = 0;
618 /* create blending brushes */
619 hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend25);
620 himl->hbrBlend25 = CreatePatternBrush (hbmTemp);
621 DeleteObject (hbmTemp);
623 hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend50);
624 himl->hbrBlend50 = CreatePatternBrush (hbmTemp);
625 DeleteObject (hbmTemp);
627 TRACE("created imagelist %p\n", himl);
628 return himl;
630 cleanup:
631 if (himl) ImageList_Destroy(himl);
632 return NULL;
636 /*************************************************************************
637 * ImageList_Destroy [COMCTL32.@]
639 * Destroys an image list.
641 * PARAMS
642 * himl [I] handle to image list
644 * RETURNS
645 * Success: TRUE
646 * Failure: FALSE
649 BOOL WINAPI
650 ImageList_Destroy (HIMAGELIST himl)
652 if (!is_valid(himl))
653 return FALSE;
655 /* delete image bitmaps */
656 if (himl->hbmImage)
657 DeleteObject (himl->hbmImage);
658 if (himl->hbmMask)
659 DeleteObject (himl->hbmMask);
661 /* delete image & mask DCs */
662 if (himl->hdcImage)
663 DeleteDC(himl->hdcImage);
664 if (himl->hdcMask)
665 DeleteDC(himl->hdcMask);
667 /* delete blending brushes */
668 if (himl->hbrBlend25)
669 DeleteObject (himl->hbrBlend25);
670 if (himl->hbrBlend50)
671 DeleteObject (himl->hbrBlend50);
673 ZeroMemory(himl, sizeof(*himl));
674 Free (himl);
676 return TRUE;
680 /*************************************************************************
681 * ImageList_DragEnter [COMCTL32.@]
683 * Locks window update and displays the drag image at the given position.
685 * PARAMS
686 * hwndLock [I] handle of the window that owns the drag image.
687 * x [I] X position of the drag image.
688 * y [I] Y position of the drag image.
690 * RETURNS
691 * Success: TRUE
692 * Failure: FALSE
694 * NOTES
695 * The position of the drag image is relative to the window, not
696 * the client area.
699 BOOL WINAPI
700 ImageList_DragEnter (HWND hwndLock, INT x, INT y)
702 TRACE("(hwnd=%p x=%d y=%d)\n", hwndLock, x, y);
704 if (!is_valid(InternalDrag.himl))
705 return FALSE;
707 if (hwndLock)
708 InternalDrag.hwnd = hwndLock;
709 else
710 InternalDrag.hwnd = GetDesktopWindow ();
712 InternalDrag.x = x;
713 InternalDrag.y = y;
715 /* draw the drag image and save the background */
716 if (!ImageList_DragShowNolock(TRUE)) {
717 return FALSE;
720 return TRUE;
724 /*************************************************************************
725 * ImageList_DragLeave [COMCTL32.@]
727 * Unlocks window update and hides the drag image.
729 * PARAMS
730 * hwndLock [I] handle of the window that owns the drag image.
732 * RETURNS
733 * Success: TRUE
734 * Failure: FALSE
737 BOOL WINAPI
738 ImageList_DragLeave (HWND hwndLock)
740 /* As we don't save drag info in the window this can lead to problems if
741 an app does not supply the same window as DragEnter */
742 /* if (hwndLock)
743 InternalDrag.hwnd = hwndLock;
744 else
745 InternalDrag.hwnd = GetDesktopWindow (); */
746 if(!hwndLock)
747 hwndLock = GetDesktopWindow();
748 if(InternalDrag.hwnd != hwndLock)
749 FIXME("DragLeave hWnd != DragEnter hWnd\n");
751 ImageList_DragShowNolock (FALSE);
753 return TRUE;
757 /*************************************************************************
758 * ImageList_InternalDragDraw [Internal]
760 * Draws the drag image.
762 * PARAMS
763 * hdc [I] device context to draw into.
764 * x [I] X position of the drag image.
765 * y [I] Y position of the drag image.
767 * RETURNS
768 * Success: TRUE
769 * Failure: FALSE
771 * NOTES
772 * The position of the drag image is relative to the window, not
773 * the client area.
777 static inline void
778 ImageList_InternalDragDraw (HDC hdc, INT x, INT y)
780 IMAGELISTDRAWPARAMS imldp;
782 ZeroMemory (&imldp, sizeof(imldp));
783 imldp.cbSize = sizeof(imldp);
784 imldp.himl = InternalDrag.himl;
785 imldp.i = 0;
786 imldp.hdcDst = hdc,
787 imldp.x = x;
788 imldp.y = y;
789 imldp.rgbBk = CLR_DEFAULT;
790 imldp.rgbFg = CLR_DEFAULT;
791 imldp.fStyle = ILD_NORMAL;
792 imldp.fState = ILS_ALPHA;
793 imldp.Frame = 128;
795 /* FIXME: instead of using the alpha blending, we should
796 * create a 50% mask, and draw it semitransparantly that way */
797 ImageList_DrawIndirect (&imldp);
800 /*************************************************************************
801 * ImageList_DragMove [COMCTL32.@]
803 * Moves the drag image.
805 * PARAMS
806 * x [I] X position of the drag image.
807 * y [I] Y position of the drag image.
809 * RETURNS
810 * Success: TRUE
811 * Failure: FALSE
813 * NOTES
814 * The position of the drag image is relative to the window, not
815 * the client area.
817 * BUGS
818 * The drag image should be drawn semitransparent.
821 BOOL WINAPI
822 ImageList_DragMove (INT x, INT y)
824 TRACE("(x=%d y=%d)\n", x, y);
826 if (!is_valid(InternalDrag.himl))
827 return FALSE;
829 /* draw/update the drag image */
830 if (InternalDrag.bShow) {
831 HDC hdcDrag;
832 HDC hdcOffScreen;
833 HDC hdcBg;
834 HBITMAP hbmOffScreen;
835 INT origNewX, origNewY;
836 INT origOldX, origOldY;
837 INT origRegX, origRegY;
838 INT sizeRegX, sizeRegY;
841 /* calculate the update region */
842 origNewX = x - InternalDrag.dxHotspot;
843 origNewY = y - InternalDrag.dyHotspot;
844 origOldX = InternalDrag.x - InternalDrag.dxHotspot;
845 origOldY = InternalDrag.y - InternalDrag.dyHotspot;
846 origRegX = min(origNewX, origOldX);
847 origRegY = min(origNewY, origOldY);
848 sizeRegX = InternalDrag.himl->cx + abs(x - InternalDrag.x);
849 sizeRegY = InternalDrag.himl->cy + abs(y - InternalDrag.y);
851 hdcDrag = GetDCEx(InternalDrag.hwnd, 0,
852 DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
853 hdcOffScreen = CreateCompatibleDC(hdcDrag);
854 hdcBg = CreateCompatibleDC(hdcDrag);
856 hbmOffScreen = CreateCompatibleBitmap(hdcDrag, sizeRegX, sizeRegY);
857 SelectObject(hdcOffScreen, hbmOffScreen);
858 SelectObject(hdcBg, InternalDrag.hbmBg);
860 /* get the actual background of the update region */
861 BitBlt(hdcOffScreen, 0, 0, sizeRegX, sizeRegY, hdcDrag,
862 origRegX, origRegY, SRCCOPY);
863 /* erase the old image */
864 BitBlt(hdcOffScreen, origOldX - origRegX, origOldY - origRegY,
865 InternalDrag.himl->cx, InternalDrag.himl->cy, hdcBg, 0, 0,
866 SRCCOPY);
867 /* save the background */
868 BitBlt(hdcBg, 0, 0, InternalDrag.himl->cx, InternalDrag.himl->cy,
869 hdcOffScreen, origNewX - origRegX, origNewY - origRegY, SRCCOPY);
870 /* draw the image */
871 ImageList_InternalDragDraw(hdcOffScreen, origNewX - origRegX,
872 origNewY - origRegY);
873 /* draw the update region to the screen */
874 BitBlt(hdcDrag, origRegX, origRegY, sizeRegX, sizeRegY,
875 hdcOffScreen, 0, 0, SRCCOPY);
877 DeleteDC(hdcBg);
878 DeleteDC(hdcOffScreen);
879 DeleteObject(hbmOffScreen);
880 ReleaseDC(InternalDrag.hwnd, hdcDrag);
883 /* update the image position */
884 InternalDrag.x = x;
885 InternalDrag.y = y;
887 return TRUE;
891 /*************************************************************************
892 * ImageList_DragShowNolock [COMCTL32.@]
894 * Shows or hides the drag image.
896 * PARAMS
897 * bShow [I] TRUE shows the drag image, FALSE hides it.
899 * RETURNS
900 * Success: TRUE
901 * Failure: FALSE
903 * BUGS
904 * The drag image should be drawn semitransparent.
907 BOOL WINAPI
908 ImageList_DragShowNolock (BOOL bShow)
910 HDC hdcDrag;
911 HDC hdcBg;
912 INT x, y;
914 if (!is_valid(InternalDrag.himl))
915 return FALSE;
917 TRACE("bShow=0x%X!\n", bShow);
919 /* DragImage is already visible/hidden */
920 if ((InternalDrag.bShow && bShow) || (!InternalDrag.bShow && !bShow)) {
921 return FALSE;
924 /* position of the origin of the DragImage */
925 x = InternalDrag.x - InternalDrag.dxHotspot;
926 y = InternalDrag.y - InternalDrag.dyHotspot;
928 hdcDrag = GetDCEx (InternalDrag.hwnd, 0,
929 DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
930 if (!hdcDrag) {
931 return FALSE;
934 hdcBg = CreateCompatibleDC(hdcDrag);
935 if (!InternalDrag.hbmBg) {
936 InternalDrag.hbmBg = CreateCompatibleBitmap(hdcDrag,
937 InternalDrag.himl->cx, InternalDrag.himl->cy);
939 SelectObject(hdcBg, InternalDrag.hbmBg);
941 if (bShow) {
942 /* save the background */
943 BitBlt(hdcBg, 0, 0, InternalDrag.himl->cx, InternalDrag.himl->cy,
944 hdcDrag, x, y, SRCCOPY);
945 /* show the image */
946 ImageList_InternalDragDraw(hdcDrag, x, y);
947 } else {
948 /* hide the image */
949 BitBlt(hdcDrag, x, y, InternalDrag.himl->cx, InternalDrag.himl->cy,
950 hdcBg, 0, 0, SRCCOPY);
953 InternalDrag.bShow = !InternalDrag.bShow;
955 DeleteDC(hdcBg);
956 ReleaseDC (InternalDrag.hwnd, hdcDrag);
957 return TRUE;
961 /*************************************************************************
962 * ImageList_Draw [COMCTL32.@]
964 * Draws an image.
966 * PARAMS
967 * himl [I] handle to image list
968 * i [I] image index
969 * hdc [I] handle to device context
970 * x [I] x position
971 * y [I] y position
972 * fStyle [I] drawing flags
974 * RETURNS
975 * Success: TRUE
976 * Failure: FALSE
978 * SEE
979 * ImageList_DrawEx.
982 BOOL WINAPI
983 ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y, UINT fStyle)
985 return ImageList_DrawEx (himl, i, hdc, x, y, 0, 0,
986 CLR_DEFAULT, CLR_DEFAULT, fStyle);
990 /*************************************************************************
991 * ImageList_DrawEx [COMCTL32.@]
993 * Draws an image and allows to use extended drawing features.
995 * PARAMS
996 * himl [I] handle to image list
997 * i [I] image index
998 * hdc [I] handle to device context
999 * x [I] X position
1000 * y [I] Y position
1001 * dx [I] X offset
1002 * dy [I] Y offset
1003 * rgbBk [I] background color
1004 * rgbFg [I] foreground color
1005 * fStyle [I] drawing flags
1007 * RETURNS
1008 * Success: TRUE
1009 * Failure: FALSE
1011 * NOTES
1012 * Calls ImageList_DrawIndirect.
1014 * SEE
1015 * ImageList_DrawIndirect.
1018 BOOL WINAPI
1019 ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y,
1020 INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg,
1021 UINT fStyle)
1023 IMAGELISTDRAWPARAMS imldp;
1025 ZeroMemory (&imldp, sizeof(imldp));
1026 imldp.cbSize = sizeof(imldp);
1027 imldp.himl = himl;
1028 imldp.i = i;
1029 imldp.hdcDst = hdc,
1030 imldp.x = x;
1031 imldp.y = y;
1032 imldp.cx = dx;
1033 imldp.cy = dy;
1034 imldp.rgbBk = rgbBk;
1035 imldp.rgbFg = rgbFg;
1036 imldp.fStyle = fStyle;
1038 return ImageList_DrawIndirect (&imldp);
1042 /*************************************************************************
1043 * ImageList_DrawIndirect [COMCTL32.@]
1045 * Draws an image using various parameters specified in pimldp.
1047 * PARAMS
1048 * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
1050 * RETURNS
1051 * Success: TRUE
1052 * Failure: FALSE
1055 BOOL WINAPI
1056 ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
1058 INT cx, cy, lx, ly, nOvlIdx;
1059 DWORD fState, dwRop;
1060 UINT fStyle;
1061 COLORREF oldImageBk, oldImageFg;
1062 HDC hImageDC, hImageListDC, hMaskListDC;
1063 HBITMAP hImageBmp, hOldImageBmp, hBlendMaskBmp;
1064 BOOL bIsTransparent, bBlend, bResult = FALSE, bMask;
1065 HIMAGELIST himl;
1067 if (!pimldp || !(himl = pimldp->himl)) return FALSE;
1068 if (!is_valid(himl)) return FALSE;
1069 if ((pimldp->i < 0) || (pimldp->i >= himl->cCurImage)) return FALSE;
1071 lx = himl->cx * pimldp->i + pimldp->xBitmap;
1072 ly = pimldp->yBitmap;
1074 fState = pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS) ? ILS_NORMAL : pimldp->fState;
1075 fStyle = pimldp->fStyle & ~ILD_OVERLAYMASK;
1076 cx = (pimldp->cx == 0) ? himl->cx : pimldp->cx;
1077 cy = (pimldp->cy == 0) ? himl->cy : pimldp->cy;
1079 bIsTransparent = (fStyle & ILD_TRANSPARENT);
1080 if( pimldp->rgbBk == CLR_NONE )
1081 bIsTransparent = TRUE;
1082 if( ( pimldp->rgbBk == CLR_DEFAULT ) && ( himl->clrBk == CLR_NONE ) )
1083 bIsTransparent = TRUE;
1084 bMask = (himl->flags & ILC_MASK) && (fStyle & ILD_MASK) ;
1085 bBlend = (fStyle & (ILD_BLEND25 | ILD_BLEND50) ) && !bMask;
1087 TRACE("himl(0x%lx) hbmMask(%p) iImage(%d) x(%d) y(%d) cx(%d) cy(%d)\n",
1088 (DWORD)himl, himl->hbmMask, pimldp->i, pimldp->x, pimldp->y, cx, cy);
1090 /* we will use these DCs to access the images and masks in the ImageList */
1091 hImageListDC = himl->hdcImage;
1092 hMaskListDC = himl->hdcMask;
1094 /* these will accumulate the image and mask for the image we're drawing */
1095 hImageDC = CreateCompatibleDC( pimldp->hdcDst );
1096 hImageBmp = CreateCompatibleBitmap( pimldp->hdcDst, cx, cy );
1097 hBlendMaskBmp = bBlend ? CreateBitmap(cx, cy, 1, 1, NULL) : 0;
1099 /* Create a compatible DC. */
1100 if (!hImageListDC || !hImageDC || !hImageBmp ||
1101 (bBlend && !hBlendMaskBmp) || (himl->hbmMask && !hMaskListDC))
1102 goto cleanup;
1104 hOldImageBmp = SelectObject(hImageDC, hImageBmp);
1107 * To obtain a transparent look, background color should be set
1108 * to white and foreground color to black when blting the
1109 * monochrome mask.
1111 oldImageFg = SetTextColor( hImageDC, RGB( 0, 0, 0 ) );
1112 oldImageBk = SetBkColor( hImageDC, RGB( 0xff, 0xff, 0xff ) );
1115 * Draw the initial image
1117 if( bMask ) {
1118 if (himl->hbmMask) {
1119 HBRUSH hOldBrush;
1120 hOldBrush = SelectObject (hImageDC, CreateSolidBrush (GetTextColor(pimldp->hdcDst)));
1121 PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY );
1122 BitBlt(hImageDC, 0, 0, cx, cy, hMaskListDC, lx, ly, SRCPAINT);
1123 DeleteObject (SelectObject (hImageDC, hOldBrush));
1124 if( bIsTransparent )
1126 BitBlt ( pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hImageDC, 0, 0, SRCAND);
1127 bResult = TRUE;
1128 goto end;
1130 } else {
1131 HBRUSH hOldBrush = SelectObject (hImageDC, GetStockObject(BLACK_BRUSH));
1132 PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY);
1133 SelectObject(hImageDC, hOldBrush);
1135 } else {
1136 /* blend the image with the needed solid background */
1137 COLORREF colour = RGB(0,0,0);
1138 HBRUSH hOldBrush;
1140 if( !bIsTransparent )
1142 colour = pimldp->rgbBk;
1143 if( colour == CLR_DEFAULT )
1144 colour = himl->clrBk;
1145 if( colour == CLR_NONE )
1146 colour = GetBkColor(pimldp->hdcDst);
1149 hOldBrush = SelectObject (hImageDC, CreateSolidBrush (colour));
1150 PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY );
1151 BitBlt( hImageDC, 0, 0, cx, cy, hMaskListDC, lx, ly, SRCAND );
1152 BitBlt( hImageDC, 0, 0, cx, cy, hImageListDC, lx, ly, SRCPAINT );
1153 DeleteObject (SelectObject (hImageDC, hOldBrush));
1156 /* Time for blending, if required */
1157 if (bBlend) {
1158 HBRUSH hBlendBrush, hOldBrush;
1159 COLORREF clrBlend = pimldp->rgbFg;
1160 HDC hBlendMaskDC = hImageListDC;
1161 HBITMAP hOldBitmap;
1163 /* Create the blend Mask */
1164 hOldBitmap = SelectObject(hBlendMaskDC, hBlendMaskBmp);
1165 hBlendBrush = fStyle & ILD_BLEND50 ? himl->hbrBlend50 : himl->hbrBlend25;
1166 hOldBrush = (HBRUSH) SelectObject(hBlendMaskDC, hBlendBrush);
1167 PatBlt(hBlendMaskDC, 0, 0, cx, cy, PATCOPY);
1168 SelectObject(hBlendMaskDC, hOldBrush);
1170 /* Modify the blend mask if an Image Mask exist */
1171 if(himl->hbmMask) {
1172 BitBlt(hBlendMaskDC, 0, 0, cx, cy, hMaskListDC, lx, ly, 0x220326); /* NOTSRCAND */
1173 BitBlt(hBlendMaskDC, 0, 0, cx, cy, hBlendMaskDC, 0, 0, NOTSRCCOPY);
1176 /* now apply blend to the current image given the BlendMask */
1177 if (clrBlend == CLR_DEFAULT) clrBlend = GetSysColor (COLOR_HIGHLIGHT);
1178 else if (clrBlend == CLR_NONE) clrBlend = GetTextColor (pimldp->hdcDst);
1179 hOldBrush = (HBRUSH) SelectObject (hImageDC, CreateSolidBrush(clrBlend));
1180 BitBlt (hImageDC, 0, 0, cx, cy, hBlendMaskDC, 0, 0, 0xB8074A); /* PSDPxax */
1181 DeleteObject(SelectObject(hImageDC, hOldBrush));
1182 SelectObject(hBlendMaskDC, hOldBitmap);
1185 /* Now do the overlay image, if any */
1186 nOvlIdx = (pimldp->fStyle & ILD_OVERLAYMASK) >> 8;
1187 if ( (nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE)) {
1188 nOvlIdx = himl->nOvlIdx[nOvlIdx - 1];
1189 if ((nOvlIdx >= 0) && (nOvlIdx < himl->cCurImage)) {
1190 const INT ox = himl->cx * nOvlIdx + pimldp->xBitmap;
1191 if (himl->hbmMask && !(fStyle & ILD_IMAGE))
1192 BitBlt (hImageDC, 0, 0, cx, cy, hMaskListDC, ox, ly, SRCAND);
1193 BitBlt (hImageDC, 0, 0, cx, cy, hImageListDC, ox, ly, SRCPAINT);
1197 if (fState & ILS_SATURATE) FIXME("ILS_SATURATE: unimplemented!\n");
1198 if (fState & ILS_GLOW) FIXME("ILS_GLOW: unimplemented!\n");
1199 if (fState & ILS_SHADOW) FIXME("ILS_SHADOW: unimplemented!\n");
1200 if (fState & ILS_ALPHA) FIXME("ILS_ALPHA: unimplemented!\n");
1202 if (fStyle & ILD_PRESERVEALPHA) FIXME("ILD_PRESERVEALPHA: unimplemented!\n");
1203 if (fStyle & ILD_SCALE) FIXME("ILD_SCALE: unimplemented!\n");
1204 if (fStyle & ILD_DPISCALE) FIXME("ILD_DPISCALE: unimplemented!\n");
1206 /* now copy the image to the screen */
1207 dwRop = SRCCOPY;
1208 if (himl->hbmMask && bIsTransparent ) {
1209 COLORREF oldDstFg = SetTextColor(pimldp->hdcDst, RGB( 0, 0, 0 ) );
1210 COLORREF oldDstBk = SetBkColor(pimldp->hdcDst, RGB( 0xff, 0xff, 0xff ));
1211 BitBlt (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hMaskListDC, lx, ly, SRCAND);
1212 SetBkColor(pimldp->hdcDst, oldDstBk);
1213 SetTextColor(pimldp->hdcDst, oldDstFg);
1214 dwRop = SRCPAINT;
1216 if (fStyle & ILD_ROP) dwRop = pimldp->dwRop;
1217 BitBlt (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hImageDC, 0, 0, dwRop);
1219 bResult = TRUE;
1220 end:
1221 /* cleanup the mess */
1222 SetBkColor(hImageDC, oldImageBk);
1223 SetTextColor(hImageDC, oldImageFg);
1224 SelectObject(hImageDC, hOldImageBmp);
1225 cleanup:
1226 DeleteObject(hBlendMaskBmp);
1227 DeleteObject(hImageBmp);
1228 DeleteDC(hImageDC);
1230 return bResult;
1234 /*************************************************************************
1235 * ImageList_Duplicate [COMCTL32.@]
1237 * Duplicates an image list.
1239 * PARAMS
1240 * himlSrc [I] source image list handle
1242 * RETURNS
1243 * Success: Handle of duplicated image list.
1244 * Failure: NULL
1247 HIMAGELIST WINAPI
1248 ImageList_Duplicate (HIMAGELIST himlSrc)
1250 HIMAGELIST himlDst;
1252 if (!is_valid(himlSrc)) {
1253 ERR("Invalid image list handle!\n");
1254 return NULL;
1257 himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
1258 himlSrc->cInitial, himlSrc->cGrow);
1260 if (himlDst)
1262 BitBlt (himlDst->hdcImage, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy,
1263 himlSrc->hdcImage, 0, 0, SRCCOPY);
1265 if (himlDst->hbmMask)
1266 BitBlt (himlDst->hdcMask, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy,
1267 himlSrc->hdcMask, 0, 0, SRCCOPY);
1269 himlDst->cCurImage = himlSrc->cCurImage;
1270 himlDst->cMaxImage = himlSrc->cMaxImage;
1272 return himlDst;
1276 /*************************************************************************
1277 * ImageList_EndDrag [COMCTL32.@]
1279 * Finishes a drag operation.
1281 * PARAMS
1282 * no Parameters
1284 * RETURNS
1285 * Success: TRUE
1286 * Failure: FALSE
1289 VOID WINAPI
1290 ImageList_EndDrag (void)
1292 /* cleanup the InternalDrag struct */
1293 InternalDrag.hwnd = 0;
1294 ImageList_Destroy (InternalDrag.himl);
1295 InternalDrag.himl = 0;
1296 InternalDrag.x= 0;
1297 InternalDrag.y= 0;
1298 InternalDrag.dxHotspot = 0;
1299 InternalDrag.dyHotspot = 0;
1300 InternalDrag.bShow = FALSE;
1301 DeleteObject(InternalDrag.hbmBg);
1302 InternalDrag.hbmBg = 0;
1306 /*************************************************************************
1307 * ImageList_GetBkColor [COMCTL32.@]
1309 * Returns the background color of an image list.
1311 * PARAMS
1312 * himl [I] Image list handle.
1314 * RETURNS
1315 * Success: background color
1316 * Failure: CLR_NONE
1319 COLORREF WINAPI
1320 ImageList_GetBkColor (HIMAGELIST himl)
1322 return himl ? himl->clrBk : CLR_NONE;
1326 /*************************************************************************
1327 * ImageList_GetDragImage [COMCTL32.@]
1329 * Returns the handle to the internal drag image list.
1331 * PARAMS
1332 * ppt [O] Pointer to the drag position. Can be NULL.
1333 * pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
1335 * RETURNS
1336 * Success: Handle of the drag image list.
1337 * Failure: NULL.
1340 HIMAGELIST WINAPI
1341 ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot)
1343 if (is_valid(InternalDrag.himl)) {
1344 if (ppt) {
1345 ppt->x = InternalDrag.x;
1346 ppt->y = InternalDrag.y;
1348 if (pptHotspot) {
1349 pptHotspot->x = InternalDrag.dxHotspot;
1350 pptHotspot->y = InternalDrag.dyHotspot;
1352 return (InternalDrag.himl);
1355 return NULL;
1359 /*************************************************************************
1360 * ImageList_GetFlags [COMCTL32.@]
1362 * Gets the flags of the specified image list.
1364 * PARAMS
1365 * himl [I] Handle to image list
1367 * RETURNS
1368 * Image list flags.
1370 * BUGS
1371 * Stub.
1374 DWORD WINAPI
1375 ImageList_GetFlags(HIMAGELIST himl)
1377 FIXME("(%p):empty stub\n", himl);
1378 return 0;
1382 /*************************************************************************
1383 * ImageList_GetIcon [COMCTL32.@]
1385 * Creates an icon from a masked image of an image list.
1387 * PARAMS
1388 * himl [I] handle to image list
1389 * i [I] image index
1390 * flags [I] drawing style flags
1392 * RETURNS
1393 * Success: icon handle
1394 * Failure: NULL
1397 HICON WINAPI
1398 ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle)
1400 ICONINFO ii;
1401 HICON hIcon;
1402 HBITMAP hOldDstBitmap;
1403 HDC hdcDst;
1405 TRACE("%p %d %d\n", himl, i, fStyle);
1406 if (!is_valid(himl) || (i < 0) || (i >= himl->cCurImage)) return NULL;
1408 ii.fIcon = TRUE;
1409 ii.xHotspot = 0;
1410 ii.yHotspot = 0;
1412 /* create colour bitmap */
1413 hdcDst = GetDC(0);
1414 ii.hbmColor = CreateCompatibleBitmap(hdcDst, himl->cx, himl->cy);
1415 ReleaseDC(0, hdcDst);
1417 hdcDst = CreateCompatibleDC(0);
1419 /* draw mask*/
1420 ii.hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
1421 hOldDstBitmap = SelectObject (hdcDst, ii.hbmMask);
1422 if (himl->hbmMask) {
1423 BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1424 himl->hdcMask, i * himl->cx, 0, SRCCOPY);
1426 else
1427 PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS);
1429 /* draw image*/
1430 SelectObject (hdcDst, ii.hbmColor);
1431 BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1432 himl->hdcImage, i * himl->cx, 0, SRCCOPY);
1435 * CreateIconIndirect requires us to deselect the bitmaps from
1436 * the DCs before calling
1438 SelectObject(hdcDst, hOldDstBitmap);
1440 hIcon = CreateIconIndirect (&ii);
1442 DeleteObject (ii.hbmMask);
1443 DeleteObject (ii.hbmColor);
1444 DeleteDC (hdcDst);
1446 return hIcon;
1450 /*************************************************************************
1451 * ImageList_GetIconSize [COMCTL32.@]
1453 * Retrieves the size of an image in an image list.
1455 * PARAMS
1456 * himl [I] handle to image list
1457 * cx [O] pointer to the image width.
1458 * cy [O] pointer to the image height.
1460 * RETURNS
1461 * Success: TRUE
1462 * Failure: FALSE
1464 * NOTES
1465 * All images in an image list have the same size.
1468 BOOL WINAPI
1469 ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy)
1471 if (!is_valid(himl))
1472 return FALSE;
1473 if ((himl->cx <= 0) || (himl->cy <= 0))
1474 return FALSE;
1476 if (cx)
1477 *cx = himl->cx;
1478 if (cy)
1479 *cy = himl->cy;
1481 return TRUE;
1485 /*************************************************************************
1486 * ImageList_GetImageCount [COMCTL32.@]
1488 * Returns the number of images in an image list.
1490 * PARAMS
1491 * himl [I] handle to image list
1493 * RETURNS
1494 * Success: Number of images.
1495 * Failure: 0
1498 INT WINAPI
1499 ImageList_GetImageCount (HIMAGELIST himl)
1501 if (!is_valid(himl))
1502 return 0;
1504 return himl->cCurImage;
1508 /*************************************************************************
1509 * ImageList_GetImageInfo [COMCTL32.@]
1511 * Returns information about an image in an image list.
1513 * PARAMS
1514 * himl [I] handle to image list
1515 * i [I] image index
1516 * pImageInfo [O] pointer to the image information
1518 * RETURNS
1519 * Success: TRUE
1520 * Failure: FALSE
1523 BOOL WINAPI
1524 ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
1526 if (!is_valid(himl) || (pImageInfo == NULL))
1527 return FALSE;
1528 if ((i < 0) || (i >= himl->cCurImage))
1529 return FALSE;
1531 pImageInfo->hbmImage = himl->hbmImage;
1532 pImageInfo->hbmMask = himl->hbmMask;
1534 pImageInfo->rcImage.top = 0;
1535 pImageInfo->rcImage.bottom = himl->cy;
1536 pImageInfo->rcImage.left = i * himl->cx;
1537 pImageInfo->rcImage.right = (i+1) * himl->cx;
1539 return TRUE;
1543 /*************************************************************************
1544 * ImageList_GetImageRect [COMCTL32.@]
1546 * Retrieves the rectangle of the specified image in an image list.
1548 * PARAMS
1549 * himl [I] handle to image list
1550 * i [I] image index
1551 * lpRect [O] pointer to the image rectangle
1553 * RETURNS
1554 * Success: TRUE
1555 * Failure: FALSE
1557 * NOTES
1558 * This is an UNDOCUMENTED function!!!
1561 BOOL WINAPI
1562 ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect)
1564 if (!is_valid(himl) || (lpRect == NULL))
1565 return FALSE;
1566 if ((i < 0) || (i >= himl->cCurImage))
1567 return FALSE;
1569 lpRect->left = i * himl->cx;
1570 lpRect->top = 0;
1571 lpRect->right = lpRect->left + himl->cx;
1572 lpRect->bottom = himl->cy;
1574 return TRUE;
1578 /*************************************************************************
1579 * ImageList_LoadImage [COMCTL32.@]
1580 * ImageList_LoadImageA [COMCTL32.@]
1582 * Creates an image list from a bitmap, icon or cursor.
1584 * SEE
1585 * ImageList_LoadImageW ()
1588 HIMAGELIST WINAPI
1589 ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx, INT cGrow,
1590 COLORREF clrMask, UINT uType, UINT uFlags)
1592 HIMAGELIST himl;
1593 LPWSTR lpbmpW;
1594 DWORD len;
1596 if (!HIWORD(lpbmp))
1597 return ImageList_LoadImageW(hi, (LPCWSTR)lpbmp, cx, cGrow, clrMask,
1598 uType, uFlags);
1600 len = MultiByteToWideChar(CP_ACP, 0, lpbmp, -1, NULL, 0);
1601 lpbmpW = Alloc(len * sizeof(WCHAR));
1602 MultiByteToWideChar(CP_ACP, 0, lpbmp, -1, lpbmpW, len);
1604 himl = ImageList_LoadImageW(hi, lpbmpW, cx, cGrow, clrMask, uType, uFlags);
1605 Free (lpbmpW);
1606 return himl;
1610 /*************************************************************************
1611 * ImageList_LoadImageW [COMCTL32.@]
1613 * Creates an image list from a bitmap, icon or cursor.
1615 * PARAMS
1616 * hi [I] instance handle
1617 * lpbmp [I] name or id of the image
1618 * cx [I] width of each image
1619 * cGrow [I] number of images to expand
1620 * clrMask [I] mask color
1621 * uType [I] type of image to load
1622 * uFlags [I] loading flags
1624 * RETURNS
1625 * Success: handle to the loaded image list
1626 * Failure: NULL
1628 * SEE
1629 * LoadImage ()
1632 HIMAGELIST WINAPI
1633 ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow,
1634 COLORREF clrMask, UINT uType, UINT uFlags)
1636 HIMAGELIST himl = NULL;
1637 HANDLE handle;
1638 INT nImageCount;
1640 handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags);
1641 if (!handle) {
1642 ERR("Error loading image!\n");
1643 return NULL;
1646 if (uType == IMAGE_BITMAP) {
1647 BITMAP bmp;
1648 GetObjectW (handle, sizeof(BITMAP), &bmp);
1650 /* To match windows behavior, if cx is set to zero and
1651 the flag DI_DEFAULTSIZE is specified, cx becomes the
1652 system metric value for icons. If the flag is not specified
1653 the function sets the size to the height of the bitmap */
1654 if (cx == 0)
1656 if (uFlags & DI_DEFAULTSIZE)
1657 cx = GetSystemMetrics (SM_CXICON);
1658 else
1659 cx = bmp.bmHeight;
1662 nImageCount = bmp.bmWidth / cx;
1664 himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1665 nImageCount, cGrow);
1666 if (!himl) {
1667 DeleteObject (handle);
1668 return NULL;
1670 ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1672 else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1673 ICONINFO ii;
1674 BITMAP bmp;
1676 GetIconInfo (handle, &ii);
1677 GetObjectW (ii.hbmColor, sizeof(BITMAP), (LPVOID)&bmp);
1678 himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1679 ILC_MASK | ILC_COLOR, 1, cGrow);
1680 if (!himl) {
1681 DeleteObject (ii.hbmColor);
1682 DeleteObject (ii.hbmMask);
1683 DeleteObject (handle);
1684 return NULL;
1686 ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1687 DeleteObject (ii.hbmColor);
1688 DeleteObject (ii.hbmMask);
1691 DeleteObject (handle);
1693 return himl;
1697 /*************************************************************************
1698 * ImageList_Merge [COMCTL32.@]
1700 * Create an image list containing a merged image from two image lists.
1702 * PARAMS
1703 * himl1 [I] handle to first image list
1704 * i1 [I] first image index
1705 * himl2 [I] handle to second image list
1706 * i2 [I] second image index
1707 * dx [I] X offset of the second image relative to the first.
1708 * dy [I] Y offset of the second image relative to the first.
1710 * RETURNS
1711 * Success: The newly created image list. It contains a single image
1712 * consisting of the second image merged with the first.
1713 * Failure: NULL, if either himl1 or himl2 are invalid.
1715 * NOTES
1716 * - The returned image list should be deleted by the caller using
1717 * ImageList_Destroy() when it is no longer required.
1718 * - If either i1 or i2 are not valid image indices they will be treated
1719 * as a blank image.
1721 HIMAGELIST WINAPI
1722 ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
1723 INT dx, INT dy)
1725 HIMAGELIST himlDst = NULL;
1726 INT cxDst, cyDst;
1727 INT xOff1, yOff1, xOff2, yOff2;
1728 INT nX1, nX2;
1730 TRACE("(himl1=%p i1=%d himl2=%p i2=%d dx=%d dy=%d)\n", himl1, i1, himl2,
1731 i2, dx, dy);
1733 if (!is_valid(himl1) || !is_valid(himl2))
1734 return NULL;
1736 if (dx > 0) {
1737 cxDst = max (himl1->cx, dx + himl2->cx);
1738 xOff1 = 0;
1739 xOff2 = dx;
1741 else if (dx < 0) {
1742 cxDst = max (himl2->cx, himl1->cx - dx);
1743 xOff1 = -dx;
1744 xOff2 = 0;
1746 else {
1747 cxDst = max (himl1->cx, himl2->cx);
1748 xOff1 = 0;
1749 xOff2 = 0;
1752 if (dy > 0) {
1753 cyDst = max (himl1->cy, dy + himl2->cy);
1754 yOff1 = 0;
1755 yOff2 = dy;
1757 else if (dy < 0) {
1758 cyDst = max (himl2->cy, himl1->cy - dy);
1759 yOff1 = -dy;
1760 yOff2 = 0;
1762 else {
1763 cyDst = max (himl1->cy, himl2->cy);
1764 yOff1 = 0;
1765 yOff2 = 0;
1768 himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
1770 if (himlDst)
1772 nX1 = i1 * himl1->cx;
1773 nX2 = i2 * himl2->cx;
1775 /* copy image */
1776 BitBlt (himlDst->hdcImage, 0, 0, cxDst, cyDst, himl1->hdcImage, 0, 0, BLACKNESS);
1777 if (i1 >= 0 && i1 < himl1->cCurImage)
1778 BitBlt (himlDst->hdcImage, xOff1, yOff1, himl1->cx, himl1->cy, himl1->hdcImage, nX1, 0, SRCCOPY);
1779 if (i2 >= 0 && i2 < himl2->cCurImage)
1781 BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcMask , nX2, 0, SRCAND);
1782 BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcImage, nX2, 0, SRCPAINT);
1785 /* copy mask */
1786 BitBlt (himlDst->hdcMask, 0, 0, cxDst, cyDst, himl1->hdcMask, 0, 0, WHITENESS);
1787 if (i1 >= 0 && i1 < himl1->cCurImage)
1788 BitBlt (himlDst->hdcMask, xOff1, yOff1, himl1->cx, himl1->cy, himl1->hdcMask, nX1, 0, SRCCOPY);
1789 if (i2 >= 0 && i2 < himl2->cCurImage)
1790 BitBlt (himlDst->hdcMask, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcMask, nX2, 0, SRCAND);
1792 himlDst->cCurImage = 1;
1795 return himlDst;
1799 /* helper for _read_bitmap currently unused */
1800 #if 0
1801 static int may_use_dibsection(HDC hdc) {
1802 int bitspixel = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES);
1803 if (bitspixel>8)
1804 return TRUE;
1805 if (bitspixel<=4)
1806 return FALSE;
1807 return GetDeviceCaps(hdc,CAPS1) & C1_DIBENGINE;
1809 #endif
1811 /* helper for ImageList_Read, see comments below */
1812 static HBITMAP _read_bitmap(LPSTREAM pstm,int ilcFlag,int cx,int cy) {
1813 HDC xdc = 0, hBitmapDC =0;
1814 BITMAPFILEHEADER bmfh;
1815 BITMAPINFOHEADER bmih;
1816 int bitsperpixel,palspace,longsperline,width,height;
1817 LPBITMAPINFOHEADER bmihc = NULL;
1818 int result = 0;
1819 HBITMAP hbitmap = 0, hDIB = 0;
1820 LPBYTE bits = NULL;
1822 if (!SUCCEEDED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL)) ||
1823 (bmfh.bfType != (('M'<<8)|'B')) ||
1824 !SUCCEEDED(IStream_Read ( pstm, &bmih, sizeof(bmih), NULL)) ||
1825 (bmih.biSize != sizeof(bmih))
1827 return 0;
1829 bitsperpixel = bmih.biPlanes * bmih.biBitCount;
1830 if (bitsperpixel<=8)
1831 palspace = (1<<bitsperpixel)*sizeof(RGBQUAD);
1832 else
1833 palspace = 0;
1834 width = bmih.biWidth;
1835 height = bmih.biHeight;
1836 bmihc = (LPBITMAPINFOHEADER)LocalAlloc(LMEM_ZEROINIT,sizeof(bmih)+palspace);
1837 memcpy(bmihc,&bmih,sizeof(bmih));
1838 longsperline = ((width*bitsperpixel+31)&~0x1f)>>5;
1839 bmihc->biSizeImage = (longsperline*height)<<2;
1841 /* read the palette right after the end of the bitmapinfoheader */
1842 if (palspace)
1843 if (!SUCCEEDED(IStream_Read ( pstm, bmihc+1, palspace, NULL)))
1844 goto ret1;
1846 xdc = GetDC(0);
1847 #if 0 /* Magic for NxM -> 1x(N*M) not implemented for DIB Sections */
1848 if ((bitsperpixel>1) &&
1849 ((ilcFlag!=ILC_COLORDDB) && (!ilcFlag || may_use_dibsection(xdc)))
1851 hbitmap = CreateDIBSection(xdc,(BITMAPINFO*)bmihc,0,(LPVOID*)&bits,0,0);
1852 if (!hbitmap)
1853 goto ret1;
1854 if (!SUCCEEDED(IStream_Read( pstm, bits, bmihc->biSizeImage, NULL)))
1855 goto ret1;
1856 result = 1;
1857 } else
1858 #endif
1860 int i,nwidth,nheight,nRows;
1862 nwidth = width*(height/cy);
1863 nheight = cy;
1864 nRows = (height/cy);
1866 if (bitsperpixel==1)
1867 hbitmap = CreateBitmap(nwidth,nheight,1,1,NULL);
1868 else
1869 hbitmap = CreateCompatibleBitmap(xdc,nwidth,nheight);
1871 hDIB = CreateDIBSection(xdc,(BITMAPINFO*)bmihc,0,(LPVOID*)&bits,0,0);
1872 if (!hDIB)
1873 goto ret1;
1874 if (!SUCCEEDED(IStream_Read( pstm, bits, bmihc->biSizeImage, NULL)))
1875 goto ret1;
1877 hBitmapDC = CreateCompatibleDC(0);
1878 SelectObject(hBitmapDC, hbitmap);
1880 /* Copy the NxM bitmap into a 1x(N*M) bitmap we need, linewise */
1881 /* Do not forget that windows bitmaps are bottom->top */
1882 TRACE("nRows=%d\n", nRows);
1883 for (i=0; i < nRows; i++){
1884 StretchDIBits(hBitmapDC, width*i, 0, width, cy, 0, cy*(nRows-1-i), width, cy, bits,
1885 (BITMAPINFO*)bmihc, DIB_RGB_COLORS, SRCCOPY);
1888 result = 1;
1890 ret1:
1891 if (xdc) ReleaseDC(0,xdc);
1892 if (bmihc) LocalFree((HLOCAL)bmihc);
1893 if (hDIB) DeleteObject(hDIB);
1894 if (hBitmapDC) DeleteDC(hBitmapDC);
1895 if (!result) {
1896 if (hbitmap) {
1897 DeleteObject(hbitmap);
1898 hbitmap = 0;
1901 return hbitmap;
1904 /*************************************************************************
1905 * ImageList_Read [COMCTL32.@]
1907 * Reads an image list from a stream.
1909 * PARAMS
1910 * pstm [I] pointer to a stream
1912 * RETURNS
1913 * Success: handle to image list
1914 * Failure: NULL
1916 * The format is like this:
1917 * ILHEAD ilheadstruct;
1919 * for the color image part:
1920 * BITMAPFILEHEADER bmfh;
1921 * BITMAPINFOHEADER bmih;
1922 * only if it has a palette:
1923 * RGBQUAD rgbs[nr_of_paletted_colors];
1925 * BYTE colorbits[imagesize];
1927 * the following only if the ILC_MASK bit is set in ILHEAD.ilFlags:
1928 * BITMAPFILEHEADER bmfh_mask;
1929 * BITMAPINFOHEADER bmih_mask;
1930 * only if it has a palette (it usually does not):
1931 * RGBQUAD rgbs[nr_of_paletted_colors];
1933 * BYTE maskbits[imagesize];
1935 * CAVEAT: Those images are within a NxM bitmap, not the 1xN we expect.
1936 * _read_bitmap needs to convert them.
1938 HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
1940 ILHEAD ilHead;
1941 HIMAGELIST himl;
1942 HBITMAP hbmColor=0,hbmMask=0;
1943 int i;
1945 if (!SUCCEEDED(IStream_Read (pstm, &ilHead, sizeof(ILHEAD), NULL)))
1946 return NULL;
1947 if (ilHead.usMagic != (('L' << 8) | 'I'))
1948 return NULL;
1949 if (ilHead.usVersion != 0x101) /* probably version? */
1950 return NULL;
1952 #if 0
1953 FIXME(" ilHead.cCurImage = %d\n",ilHead.cCurImage);
1954 FIXME(" ilHead.cMaxImage = %d\n",ilHead.cMaxImage);
1955 FIXME(" ilHead.cGrow = %d\n",ilHead.cGrow);
1956 FIXME(" ilHead.cx = %d\n",ilHead.cx);
1957 FIXME(" ilHead.cy = %d\n",ilHead.cy);
1958 FIXME(" ilHead.flags = %x\n",ilHead.flags);
1959 FIXME(" ilHead.ovls[0] = %d\n",ilHead.ovls[0]);
1960 FIXME(" ilHead.ovls[1] = %d\n",ilHead.ovls[1]);
1961 FIXME(" ilHead.ovls[2] = %d\n",ilHead.ovls[2]);
1962 FIXME(" ilHead.ovls[3] = %d\n",ilHead.ovls[3]);
1963 #endif
1965 hbmColor = _read_bitmap(pstm,ilHead.flags & ~ILC_MASK,ilHead.cx,ilHead.cy);
1966 if (!hbmColor)
1967 return NULL;
1968 if (ilHead.flags & ILC_MASK) {
1969 hbmMask = _read_bitmap(pstm,0,ilHead.cx,ilHead.cy);
1970 if (!hbmMask) {
1971 DeleteObject(hbmColor);
1972 return NULL;
1976 himl = ImageList_Create (
1977 ilHead.cx,
1978 ilHead.cy,
1979 ilHead.flags,
1980 1, /* initial */
1981 ilHead.cGrow
1983 if (!himl) {
1984 DeleteObject(hbmColor);
1985 DeleteObject(hbmMask);
1986 return NULL;
1988 SelectObject(himl->hdcImage, hbmColor);
1989 DeleteObject(himl->hbmImage);
1990 himl->hbmImage = hbmColor;
1991 if (hbmMask){
1992 SelectObject(himl->hdcMask, hbmMask);
1993 DeleteObject(himl->hbmMask);
1994 himl->hbmMask = hbmMask;
1996 himl->cCurImage = ilHead.cCurImage;
1997 himl->cMaxImage = ilHead.cMaxImage;
1999 ImageList_SetBkColor(himl,ilHead.bkcolor);
2000 for (i=0;i<4;i++)
2001 ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1);
2002 return himl;
2006 /*************************************************************************
2007 * ImageList_Remove [COMCTL32.@]
2009 * Removes an image from an image list
2011 * PARAMS
2012 * himl [I] image list handle
2013 * i [I] image index
2015 * RETURNS
2016 * Success: TRUE
2017 * Failure: FALSE
2020 BOOL WINAPI
2021 ImageList_Remove (HIMAGELIST himl, INT i)
2023 HBITMAP hbmNewImage, hbmNewMask;
2024 HDC hdcBmp;
2025 INT cxNew, nCount;
2027 TRACE("(himl=%p i=%d)\n", himl, i);
2029 if (!is_valid(himl)) {
2030 ERR("Invalid image list handle!\n");
2031 return FALSE;
2034 if ((i < -1) || (i >= himl->cCurImage)) {
2035 TRACE("index out of range! %d\n", i);
2036 return FALSE;
2039 if (i == -1) {
2040 /* remove all */
2041 if (himl->cCurImage == 0) {
2042 /* remove all on empty ImageList is allowed */
2043 TRACE("remove all on empty ImageList!\n");
2044 return TRUE;
2047 himl->cMaxImage = himl->cInitial + himl->cGrow;
2048 himl->cCurImage = 0;
2049 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2050 himl->nOvlIdx[nCount] = -1;
2052 hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage * himl->cx, himl->cy);
2053 SelectObject (himl->hdcImage, hbmNewImage);
2054 DeleteObject (himl->hbmImage);
2055 himl->hbmImage = hbmNewImage;
2057 if (himl->hbmMask) {
2058 hbmNewMask = CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2059 1, 1, NULL);
2060 SelectObject (himl->hdcMask, hbmNewMask);
2061 DeleteObject (himl->hbmMask);
2062 himl->hbmMask = hbmNewMask;
2065 else {
2066 /* delete one image */
2067 TRACE("Remove single image! %d\n", i);
2069 /* create new bitmap(s) */
2070 nCount = (himl->cCurImage + himl->cGrow - 1);
2071 cxNew = nCount * himl->cx;
2073 TRACE(" - Number of images: %d / %d (Old/New)\n",
2074 himl->cCurImage, himl->cCurImage - 1);
2075 TRACE(" - Max. number of images: %d / %d (Old/New)\n",
2076 himl->cMaxImage, himl->cCurImage + himl->cGrow - 1);
2078 hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, cxNew, himl->cy);
2080 if (himl->hbmMask)
2081 hbmNewMask = CreateBitmap (cxNew, himl->cy, 1, 1, NULL);
2082 else
2083 hbmNewMask = 0; /* Just to keep compiler happy! */
2085 hdcBmp = CreateCompatibleDC (0);
2087 /* copy all images and masks prior to the "removed" image */
2088 if (i > 0) {
2089 TRACE("Pre image copy: Copy %d images\n", i);
2091 SelectObject (hdcBmp, hbmNewImage);
2092 BitBlt (hdcBmp, 0, 0, i * himl->cx, himl->cy,
2093 himl->hdcImage, 0, 0, SRCCOPY);
2095 if (himl->hbmMask) {
2096 SelectObject (hdcBmp, hbmNewMask);
2097 BitBlt (hdcBmp, 0, 0, i * himl->cx, himl->cy,
2098 himl->hdcMask, 0, 0, SRCCOPY);
2102 /* copy all images and masks behind the removed image */
2103 if (i < himl->cCurImage - 1) {
2104 TRACE("Post image copy!\n");
2105 SelectObject (hdcBmp, hbmNewImage);
2106 BitBlt (hdcBmp, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx,
2107 himl->cy, himl->hdcImage, (i + 1) * himl->cx, 0, SRCCOPY);
2109 if (himl->hbmMask) {
2110 SelectObject (hdcBmp, hbmNewMask);
2111 BitBlt (hdcBmp, i * himl->cx, 0,
2112 (himl->cCurImage - i - 1) * himl->cx,
2113 himl->cy, himl->hdcMask, (i + 1) * himl->cx, 0, SRCCOPY);
2117 DeleteDC (hdcBmp);
2119 /* delete old images and insert new ones */
2120 SelectObject (himl->hdcImage, hbmNewImage);
2121 DeleteObject (himl->hbmImage);
2122 himl->hbmImage = hbmNewImage;
2123 if (himl->hbmMask) {
2124 SelectObject (himl->hdcMask, hbmNewMask);
2125 DeleteObject (himl->hbmMask);
2126 himl->hbmMask = hbmNewMask;
2129 himl->cCurImage--;
2130 himl->cMaxImage = himl->cCurImage + himl->cGrow;
2133 return TRUE;
2137 /*************************************************************************
2138 * ImageList_Replace [COMCTL32.@]
2140 * Replaces an image in an image list with a new image.
2142 * PARAMS
2143 * himl [I] handle to image list
2144 * i [I] image index
2145 * hbmImage [I] handle to image bitmap
2146 * hbmMask [I] handle to mask bitmap. Can be NULL.
2148 * RETURNS
2149 * Success: TRUE
2150 * Failure: FALSE
2153 BOOL WINAPI
2154 ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage,
2155 HBITMAP hbmMask)
2157 HDC hdcImage;
2158 BITMAP bmp;
2160 TRACE("%p %d %p %p\n", himl, i, hbmImage, hbmMask);
2162 if (!is_valid(himl)) {
2163 ERR("Invalid image list handle!\n");
2164 return FALSE;
2167 if ((i >= himl->cMaxImage) || (i < 0)) {
2168 ERR("Invalid image index!\n");
2169 return FALSE;
2172 hdcImage = CreateCompatibleDC (0);
2173 GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
2175 /* Replace Image */
2176 SelectObject (hdcImage, hbmImage);
2178 StretchBlt (himl->hdcImage, i * himl->cx, 0, himl->cx, himl->cy,
2179 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2181 if (himl->hbmMask)
2183 /* Replace Mask */
2184 SelectObject (hdcImage, hbmMask);
2186 StretchBlt (himl->hdcMask, i * himl->cx, 0, himl->cx, himl->cy,
2187 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2190 /* Remove the background from the image
2192 StretchBlt (himl->hdcImage,
2193 i*himl->cx, 0, himl->cx, himl->cy,
2194 hdcImage,
2195 0, 0, bmp.bmWidth, bmp.bmHeight,
2196 0x220326); /* NOTSRCAND */
2199 DeleteDC (hdcImage);
2201 return TRUE;
2205 /*************************************************************************
2206 * ImageList_ReplaceIcon [COMCTL32.@]
2208 * Replaces an image in an image list using an icon.
2210 * PARAMS
2211 * himl [I] handle to image list
2212 * i [I] image index
2213 * hIcon [I] handle to icon
2215 * RETURNS
2216 * Success: index of the replaced image
2217 * Failure: -1
2220 INT WINAPI
2221 ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon)
2223 HDC hdcImage;
2224 INT nIndex;
2225 HICON hBestFitIcon;
2226 HBITMAP hbmOldSrc;
2227 ICONINFO ii;
2228 BITMAP bmp;
2229 BOOL ret;
2231 TRACE("(%p %d %p)\n", himl, i, hIcon);
2233 if (!is_valid(himl)) {
2234 ERR("invalid image list\n");
2235 return -1;
2237 if ((i >= himl->cMaxImage) || (i < -1)) {
2238 ERR("invalid image index %d / %d\n", i, himl->cMaxImage);
2239 return -1;
2242 hBestFitIcon = CopyImage(
2243 hIcon, IMAGE_ICON,
2244 himl->cx, himl->cy,
2245 LR_COPYFROMRESOURCE);
2246 /* the above will fail if the icon wasn't loaded from a resource, so try
2247 * again without LR_COPYFROMRESOURCE flag */
2248 if (!hBestFitIcon)
2249 hBestFitIcon = CopyImage(
2250 hIcon, IMAGE_ICON,
2251 himl->cx, himl->cy,
2253 if (!hBestFitIcon)
2254 return -1;
2256 ret = GetIconInfo (hBestFitIcon, &ii);
2257 if (!ret) {
2258 DestroyIcon(hBestFitIcon);
2259 return -1;
2262 if (ii.hbmColor == 0)
2263 ERR("no color!\n");
2264 ret = GetObjectW (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
2265 if (!ret) {
2266 ERR("couldn't get mask bitmap info\n");
2267 if (ii.hbmColor)
2268 DeleteObject (ii.hbmColor);
2269 if (ii.hbmMask)
2270 DeleteObject (ii.hbmMask);
2271 DestroyIcon(hBestFitIcon);
2272 return -1;
2275 if (i == -1) {
2276 if (himl->cCurImage + 1 > himl->cMaxImage)
2277 IMAGELIST_InternalExpandBitmaps (himl, 1, 0, 0);
2279 nIndex = himl->cCurImage;
2280 himl->cCurImage++;
2282 else
2283 nIndex = i;
2285 hdcImage = CreateCompatibleDC (0);
2286 TRACE("hdcImage=%p\n", hdcImage);
2287 if (hdcImage == 0)
2288 ERR("invalid hdcImage!\n");
2290 SetTextColor(himl->hdcImage, RGB(0,0,0));
2291 SetBkColor (himl->hdcImage, RGB(255,255,255));
2292 hbmOldSrc = SelectObject (hdcImage, ii.hbmColor);
2294 StretchBlt (himl->hdcImage, nIndex * himl->cx, 0, himl->cx, himl->cy,
2295 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2297 if (himl->hbmMask) {
2298 SelectObject (hdcImage, ii.hbmMask);
2299 StretchBlt (himl->hdcMask, nIndex * himl->cx, 0, himl->cx, himl->cy,
2300 hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2303 SelectObject (hdcImage, hbmOldSrc);
2305 DestroyIcon(hBestFitIcon);
2306 if (hdcImage)
2307 DeleteDC (hdcImage);
2308 if (ii.hbmColor)
2309 DeleteObject (ii.hbmColor);
2310 if (ii.hbmMask)
2311 DeleteObject (ii.hbmMask);
2313 TRACE("Insert index = %d, himl->cCurImage = %d\n", nIndex, himl->cCurImage);
2314 return nIndex;
2318 /*************************************************************************
2319 * ImageList_SetBkColor [COMCTL32.@]
2321 * Sets the background color of an image list.
2323 * PARAMS
2324 * himl [I] handle to image list
2325 * clrBk [I] background color
2327 * RETURNS
2328 * Success: previous background color
2329 * Failure: CLR_NONE
2332 COLORREF WINAPI
2333 ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
2335 COLORREF clrOldBk;
2337 if (!is_valid(himl))
2338 return CLR_NONE;
2340 clrOldBk = himl->clrBk;
2341 himl->clrBk = clrBk;
2342 return clrOldBk;
2346 /*************************************************************************
2347 * ImageList_SetDragCursorImage [COMCTL32.@]
2349 * Combines the specified image with the current drag image
2351 * PARAMS
2352 * himlDrag [I] handle to drag image list
2353 * iDrag [I] drag image index
2354 * dxHotspot [I] X position of the hot spot
2355 * dyHotspot [I] Y position of the hot spot
2357 * RETURNS
2358 * Success: TRUE
2359 * Failure: FALSE
2361 * NOTES
2362 * - The names dxHotspot, dyHotspot are misleading because they have nothing
2363 * to do with a hotspot but are only the offset of the origin of the new
2364 * image relative to the origin of the old image.
2366 * - When this function is called and the drag image is visible, a
2367 * short flickering occurs but this matches the Win9x behavior. It is
2368 * possible to fix the flickering using code like in ImageList_DragMove.
2371 BOOL WINAPI
2372 ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag,
2373 INT dxHotspot, INT dyHotspot)
2375 HIMAGELIST himlTemp;
2376 BOOL visible;
2378 if (!is_valid(InternalDrag.himl) || !is_valid(himlDrag))
2379 return FALSE;
2381 TRACE(" dxH=%d dyH=%d nX=%d nY=%d\n",
2382 dxHotspot, dyHotspot, InternalDrag.dxHotspot, InternalDrag.dyHotspot);
2384 visible = InternalDrag.bShow;
2386 himlTemp = ImageList_Merge (InternalDrag.himl, 0, himlDrag, iDrag,
2387 dxHotspot, dyHotspot);
2389 if (visible) {
2390 /* hide the drag image */
2391 ImageList_DragShowNolock(FALSE);
2393 if ((InternalDrag.himl->cx != himlTemp->cx) ||
2394 (InternalDrag.himl->cy != himlTemp->cy)) {
2395 /* the size of the drag image changed, invalidate the buffer */
2396 DeleteObject(InternalDrag.hbmBg);
2397 InternalDrag.hbmBg = 0;
2400 ImageList_Destroy (InternalDrag.himl);
2401 InternalDrag.himl = himlTemp;
2403 if (visible) {
2404 /* show the drag image */
2405 ImageList_DragShowNolock(TRUE);
2408 return TRUE;
2412 /*************************************************************************
2413 * ImageList_SetFilter [COMCTL32.@]
2415 * Sets a filter (or does something completely different)!!???
2416 * It removes 12 Bytes from the stack (3 Parameters).
2418 * PARAMS
2419 * himl [I] SHOULD be a handle to image list
2420 * i [I] COULD be an index?
2421 * dwFilter [I] ???
2423 * RETURNS
2424 * Success: TRUE ???
2425 * Failure: FALSE ???
2427 * BUGS
2428 * This is an UNDOCUMENTED function!!!!
2429 * empty stub.
2432 BOOL WINAPI
2433 ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter)
2435 FIXME("(%p 0x%x 0x%lx):empty stub!\n", himl, i, dwFilter);
2437 return FALSE;
2441 /*************************************************************************
2442 * ImageList_SetFlags [COMCTL32.@]
2444 * Sets the image list flags.
2446 * PARAMS
2447 * himl [I] Handle to image list
2448 * flags [I] Flags to set
2450 * RETURNS
2451 * Old flags?
2453 * BUGS
2454 * Stub.
2457 DWORD WINAPI
2458 ImageList_SetFlags(HIMAGELIST himl, DWORD flags)
2460 FIXME("(%p %08lx):empty stub\n", himl, flags);
2461 return 0;
2465 /*************************************************************************
2466 * ImageList_SetIconSize [COMCTL32.@]
2468 * Sets the image size of the bitmap and deletes all images.
2470 * PARAMS
2471 * himl [I] handle to image list
2472 * cx [I] image width
2473 * cy [I] image height
2475 * RETURNS
2476 * Success: TRUE
2477 * Failure: FALSE
2480 BOOL WINAPI
2481 ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy)
2483 INT nCount;
2484 HBITMAP hbmNew;
2486 if (!is_valid(himl))
2487 return FALSE;
2489 /* remove all images */
2490 himl->cMaxImage = himl->cInitial + himl->cGrow;
2491 himl->cCurImage = 0;
2492 himl->cx = cx;
2493 himl->cy = cy;
2495 /* initialize overlay mask indices */
2496 for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2497 himl->nOvlIdx[nCount] = -1;
2499 hbmNew = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage * himl->cx, himl->cy);
2500 SelectObject (himl->hdcImage, hbmNew);
2501 DeleteObject (himl->hbmImage);
2502 himl->hbmImage = hbmNew;
2504 if (himl->hbmMask) {
2505 hbmNew = CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2506 1, 1, NULL);
2507 SelectObject (himl->hdcMask, hbmNew);
2508 DeleteObject (himl->hbmMask);
2509 himl->hbmMask = hbmNew;
2512 return TRUE;
2516 /*************************************************************************
2517 * ImageList_SetImageCount [COMCTL32.@]
2519 * Resizes an image list to the specified number of images.
2521 * PARAMS
2522 * himl [I] handle to image list
2523 * iImageCount [I] number of images in the image list
2525 * RETURNS
2526 * Success: TRUE
2527 * Failure: FALSE
2530 BOOL WINAPI
2531 ImageList_SetImageCount (HIMAGELIST himl, UINT iImageCount)
2533 HDC hdcBitmap;
2534 HBITMAP hbmNewBitmap;
2535 INT nNewCount, nCopyCount;
2537 TRACE("%p %d\n",himl,iImageCount);
2539 if (!is_valid(himl))
2540 return FALSE;
2541 if (himl->cCurImage >= iImageCount)
2542 return FALSE;
2543 if (himl->cMaxImage > iImageCount)
2545 himl->cCurImage = iImageCount;
2546 return TRUE;
2549 nNewCount = iImageCount + himl->cGrow;
2550 nCopyCount = min(himl->cCurImage, iImageCount);
2552 hdcBitmap = CreateCompatibleDC (0);
2554 hbmNewBitmap = ImageList_CreateImage(hdcBitmap, himl, nNewCount * himl->cx, himl->cy);
2556 if (hbmNewBitmap != 0)
2558 SelectObject (hdcBitmap, hbmNewBitmap);
2560 /* copy images */
2561 BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2562 himl->hdcImage, 0, 0, SRCCOPY);
2563 #if 0
2564 /* delete 'empty' image space */
2565 SetBkColor (hdcBitmap, RGB(255, 255, 255));
2566 SetTextColor (hdcBitmap, RGB(0, 0, 0));
2567 PatBlt (hdcBitmap, nCopyCount * himl->cx, 0,
2568 (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2569 #endif
2570 SelectObject (himl->hdcImage, hbmNewBitmap);
2571 DeleteObject (himl->hbmImage);
2572 himl->hbmImage = hbmNewBitmap;
2574 else
2575 ERR("Could not create new image bitmap !\n");
2577 if (himl->hbmMask)
2579 hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2580 1, 1, NULL);
2581 if (hbmNewBitmap != 0)
2583 SelectObject (hdcBitmap, hbmNewBitmap);
2585 /* copy images */
2586 BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2587 himl->hdcMask, 0, 0, SRCCOPY);
2588 #if 0
2589 /* delete 'empty' image space */
2590 SetBkColor (hdcBitmap, RGB(255, 255, 255));
2591 SetTextColor (hdcBitmap, RGB(0, 0, 0));
2592 PatBlt (hdcBitmap, nCopyCount * himl->cx, 0,
2593 (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2594 #endif
2595 SelectObject (himl->hdcMask, hbmNewBitmap);
2596 DeleteObject (himl->hbmMask);
2597 himl->hbmMask = hbmNewBitmap;
2599 else
2600 ERR("Could not create new mask bitmap!\n");
2603 DeleteDC (hdcBitmap);
2605 /* Update max image count and current image count */
2606 himl->cMaxImage = nNewCount;
2607 himl->cCurImage = iImageCount;
2609 return TRUE;
2613 /*************************************************************************
2614 * ImageList_SetOverlayImage [COMCTL32.@]
2616 * Assigns an overlay mask index to an existing image in an image list.
2618 * PARAMS
2619 * himl [I] handle to image list
2620 * iImage [I] image index
2621 * iOverlay [I] overlay mask index
2623 * RETURNS
2624 * Success: TRUE
2625 * Failure: FALSE
2628 BOOL WINAPI
2629 ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay)
2631 if (!is_valid(himl))
2632 return FALSE;
2633 if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
2634 return FALSE;
2635 if ((iImage!=-1) && ((iImage < 0) || (iImage > himl->cCurImage)))
2636 return FALSE;
2637 himl->nOvlIdx[iOverlay - 1] = iImage;
2638 return TRUE;
2643 /* helper for ImageList_Write - write bitmap to pstm
2644 * currently everything is written as 24 bit RGB, except masks
2646 static BOOL
2647 _write_bitmap(HBITMAP hBitmap, LPSTREAM pstm, int cx, int cy)
2649 LPBITMAPFILEHEADER bmfh;
2650 LPBITMAPINFOHEADER bmih;
2651 LPBYTE data, lpBits, lpBitsOrg;
2652 BITMAP bm;
2653 INT bitCount, sizeImage, offBits, totalSize;
2654 INT nwidth, nheight, nsizeImage, icount;
2655 HDC xdc;
2656 BOOL result = FALSE;
2659 xdc = GetDC(0);
2660 GetObjectA(hBitmap, sizeof(BITMAP), (LPVOID)&bm);
2662 /* XXX is this always correct? */
2663 icount = bm.bmWidth / cx;
2664 nwidth = cx;
2665 nheight = cy * icount;
2667 bitCount = bm.bmBitsPixel == 1 ? 1 : 24;
2668 sizeImage = ((((bm.bmWidth * bitCount)+31) & ~31) >> 3) * bm.bmHeight;
2669 nsizeImage = ((((nwidth * bitCount)+31) & ~31) >> 3) * nheight;
2671 totalSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
2672 if(bitCount != 24)
2673 totalSize += (1 << bitCount) * sizeof(RGBQUAD);
2674 offBits = totalSize;
2675 totalSize += nsizeImage;
2677 data = (LPBYTE)LocalAlloc(LMEM_ZEROINIT, totalSize);
2678 bmfh = (LPBITMAPFILEHEADER)data;
2679 bmih = (LPBITMAPINFOHEADER)(data + sizeof(BITMAPFILEHEADER));
2680 lpBits = data + offBits;
2682 /* setup BITMAPFILEHEADER */
2683 bmfh->bfType = (('M' << 8) | 'B');
2684 bmfh->bfSize = 0;
2685 bmfh->bfReserved1 = 0;
2686 bmfh->bfReserved2 = 0;
2687 bmfh->bfOffBits = offBits;
2689 /* setup BITMAPINFOHEADER */
2690 bmih->biSize = sizeof(BITMAPINFOHEADER);
2691 bmih->biWidth = bm.bmWidth;
2692 bmih->biHeight = bm.bmHeight;
2693 bmih->biPlanes = 1;
2694 bmih->biBitCount = bitCount;
2695 bmih->biCompression = BI_RGB;
2696 bmih->biSizeImage = sizeImage;
2697 bmih->biXPelsPerMeter = 0;
2698 bmih->biYPelsPerMeter = 0;
2699 bmih->biClrUsed = 0;
2700 bmih->biClrImportant = 0;
2702 lpBitsOrg = (LPBYTE)LocalAlloc(LMEM_ZEROINIT, sizeImage);
2703 if(!GetDIBits(xdc, hBitmap, 0, bm.bmHeight, lpBitsOrg,
2704 (BITMAPINFO *)bmih, DIB_RGB_COLORS))
2705 goto failed;
2706 else {
2707 int i;
2708 int obpl = (((bm.bmWidth*bitCount+31) & ~31)>>3);
2709 int nbpl = (((nwidth*bitCount+31) & ~31)>>3);
2711 for(i = 0; i < nheight; i++) {
2712 int ooff = ((nheight-1-i)%cy) * obpl + ((i/cy) * nbpl);
2713 int noff = (nbpl * (nheight-1-i));
2714 memcpy(lpBits + noff, lpBitsOrg + ooff, nbpl);
2718 bmih->biWidth = nwidth;
2719 bmih->biHeight = nheight;
2720 bmih->biSizeImage = nsizeImage;
2722 if(bitCount == 1) {
2723 /* Hack. */
2724 LPBITMAPINFO inf = (LPBITMAPINFO)bmih;
2725 inf->bmiColors[0].rgbRed = inf->bmiColors[0].rgbGreen = inf->bmiColors[0].rgbBlue = 0;
2726 inf->bmiColors[1].rgbRed = inf->bmiColors[1].rgbGreen = inf->bmiColors[1].rgbBlue = 0xff;
2729 if(!SUCCEEDED(IStream_Write(pstm, data, totalSize, NULL)))
2730 goto failed;
2732 result = TRUE;
2734 failed:
2735 ReleaseDC(0, xdc);
2736 LocalFree((HLOCAL)lpBitsOrg);
2737 LocalFree((HLOCAL)data);
2739 return result;
2743 /*************************************************************************
2744 * ImageList_Write [COMCTL32.@]
2746 * Writes an image list to a stream.
2748 * PARAMS
2749 * himl [I] handle to image list
2750 * pstm [O] Pointer to a stream.
2752 * RETURNS
2753 * Success: TRUE
2754 * Failure: FALSE
2756 * BUGS
2757 * probably.
2760 BOOL WINAPI
2761 ImageList_Write (HIMAGELIST himl, LPSTREAM pstm)
2763 ILHEAD ilHead;
2764 int i;
2766 if (!is_valid(himl))
2767 return FALSE;
2769 ilHead.usMagic = (('L' << 8) | 'I');
2770 ilHead.usVersion = 0x101;
2771 ilHead.cCurImage = himl->cCurImage;
2772 ilHead.cMaxImage = himl->cMaxImage;
2773 ilHead.cGrow = himl->cGrow;
2774 ilHead.cx = himl->cx;
2775 ilHead.cy = himl->cy;
2776 ilHead.bkcolor = himl->clrBk;
2777 ilHead.flags = himl->flags;
2778 for(i = 0; i < 4; i++) {
2779 ilHead.ovls[i] = himl->nOvlIdx[i];
2782 if(!SUCCEEDED(IStream_Write(pstm, &ilHead, sizeof(ILHEAD), NULL)))
2783 return FALSE;
2785 /* write the bitmap */
2786 if(!_write_bitmap(himl->hbmImage, pstm, himl->cx, himl->cy))
2787 return FALSE;
2789 /* write the mask if we have one */
2790 if(himl->flags & ILC_MASK) {
2791 if(!_write_bitmap(himl->hbmMask, pstm, himl->cx, himl->cy))
2792 return FALSE;
2795 return TRUE;
2799 static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT width, UINT height)
2801 HBITMAP hbmNewBitmap;
2802 UINT ilc = (himl->flags & 0xFE);
2804 if ((ilc >= ILC_COLOR4 && ilc <= ILC_COLOR32) || ilc == ILC_COLOR)
2806 VOID* bits;
2807 BITMAPINFO *bmi;
2809 TRACE("Creating DIBSection: %d Bits per Pixel\n", himl->uBitsPixel);
2811 if (himl->uBitsPixel <= ILC_COLOR8)
2813 LPPALETTEENTRY pal;
2814 ULONG i, colors;
2815 BYTE temp;
2817 colors = 1 << himl->uBitsPixel;
2818 bmi = Alloc(sizeof(BITMAPINFOHEADER) +
2819 sizeof(PALETTEENTRY) * colors);
2821 pal = (LPPALETTEENTRY)bmi->bmiColors;
2822 GetPaletteEntries(GetStockObject(DEFAULT_PALETTE), 0, colors, pal);
2824 /* Swap colors returned by GetPaletteEntries so we can use them for
2825 * CreateDIBSection call. */
2826 for (i = 0; i < colors; i++)
2828 temp = pal[i].peBlue;
2829 bmi->bmiColors[i].rgbRed = pal[i].peRed;
2830 bmi->bmiColors[i].rgbBlue = temp;
2833 else
2835 bmi = Alloc(sizeof(BITMAPINFOHEADER));
2838 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2839 bmi->bmiHeader.biWidth = width;
2840 bmi->bmiHeader.biHeight = height;
2841 bmi->bmiHeader.biPlanes = 1;
2842 bmi->bmiHeader.biBitCount = himl->uBitsPixel;
2843 bmi->bmiHeader.biCompression = BI_RGB;
2844 bmi->bmiHeader.biSizeImage = 0;
2845 bmi->bmiHeader.biXPelsPerMeter = 0;
2846 bmi->bmiHeader.biYPelsPerMeter = 0;
2847 bmi->bmiHeader.biClrUsed = 0;
2848 bmi->bmiHeader.biClrImportant = 0;
2850 hbmNewBitmap = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, &bits, 0, 0);
2852 Free (bmi);
2854 else /*if (ilc == ILC_COLORDDB)*/
2856 TRACE("Creating Bitmap: %d Bits per Pixel\n", himl->uBitsPixel);
2858 hbmNewBitmap = CreateBitmap (width, height, 1, himl->uBitsPixel, NULL);
2860 TRACE("returning %p\n", hbmNewBitmap);
2861 return hbmNewBitmap;
2864 /*************************************************************************
2865 * ImageList_SetColorTable [COMCTL32.@]
2867 * Sets the color table of an image list.
2869 * PARAMS
2870 * himl [I] Handle to the image list.
2871 * uStartIndex [I] The first index to set.
2872 * cEntries [I] Number of entries to set.
2873 * prgb [I] New color information for color table for the image list.
2875 * RETURNS
2876 * Success: Number of entries in the table that were set.
2877 * Failure: Zero.
2879 * SEE
2880 * ImageList_Create(), SetDIBColorTable()
2883 UINT WINAPI
2884 ImageList_SetColorTable (HIMAGELIST himl, UINT uStartIndex, UINT cEntries, CONST RGBQUAD * prgb)
2886 return SetDIBColorTable(himl->hdcImage, uStartIndex, cEntries, prgb);