Authors: Chris Morgan <cmorgan@wpi.edu>, James Abbatiello <abbeyj@wpi.edu>
[wine] / dlls / comctl32 / imagelist.c
1 /*
2  *  ImageList implementation
3  *
4  *  Copyright 1998 Eric Kohl
5  *
6  *  TODO:
7  *    - Fix ImageList_DrawIndirect (xBitmap, yBitmap, rgbFg, rgbBk, dwRop).
8  *    - Fix ImageList_GetIcon.
9  *    - Fix drag functions.
10  *    - Fix ImageList_Read and ImageList_Write.
11  *    - Fix ImageList_SetFilter (undocumented).
12  *      BTW does anybody know anything about this function???
13  *        - It removes 12 Bytes from the stack (3 Parameters).
14  *        - First parameter SHOULD be a HIMAGELIST.
15  *        - Second parameter COULD be an index?????
16  *        - Third parameter.... ?????????????????????
17  *
18  *  Comments:
19  *    - ImageList_Draw, ImageList_DrawEx and ImageList_GetIcon use
20  *      ImageList_DrawIndirect. Since ImageList_DrawIndirect is still
21  *      partially imlemented, the functions mentioned above will be 
22  *      limited in functionality too.
23  */
24
25 /* This must be defined because the HIMAGELIST type is just a pointer
26  * to the _IMAGELIST data structure. But M$ does not want us to know
27  * anything about its contents. Applications just see a pointer to
28  * an empty structure. It's just to keep compatibility.
29  */
30 #define __WINE_IMAGELIST_C
31
32  
33 #include "wine/obj_base.h"
34 #include "wine/obj_storage.h"
35 #include "imagelist.h"
36 #include "commctrl.h"
37 #include "debug.h"
38
39 DEFAULT_DEBUG_CHANNEL(imagelist)
40
41
42 #define _MAX(a,b) (((a)>(b))?(a):(b))
43 #define _MIN(a,b) (((a)>(b))?(b):(a))
44
45 #define MAX_OVERLAYIMAGE 15
46
47
48 /* internal image list data used for Drag & Drop operations */
49
50 static HIMAGELIST himlInternalDrag = NULL;
51 static INT      nInternalDragHotspotX = 0;
52 static INT      nInternalDragHotspotY = 0;
53
54 static HWND     hwndInternalDrag = 0;
55 static INT      xInternalPos = 0;
56 static INT      yInternalPos = 0;
57
58 static HDC      hdcBackBuffer = 0;
59 static HBITMAP  hbmBackBuffer = 0;
60
61
62 /*************************************************************************
63  * IMAGELIST_InternalExpandBitmaps [Internal] 
64  *
65  * Expands the bitmaps of an image list by the given number of images.
66  *
67  * PARAMS
68  *     himl        [I] handle to image list
69  *     nImageCount [I] number of images to add
70  *
71  * RETURNS
72  *     nothing
73  *
74  * NOTES
75  *     This function can NOT be used to reduce the number of images.
76  */
77
78 static VOID
79 IMAGELIST_InternalExpandBitmaps (HIMAGELIST himl, INT nImageCount)
80 {
81     HDC     hdcImageList, hdcBitmap;
82     HBITMAP hbmNewBitmap;
83     INT     nNewWidth, nNewCount;
84
85     TRACE(imagelist, "Create expanded bitmaps!\n");
86
87     nNewCount = himl->cCurImage + nImageCount + himl->cGrow;
88     nNewWidth = nNewCount * himl->cx;
89
90     hdcImageList = CreateCompatibleDC (0);
91     hdcBitmap = CreateCompatibleDC (0);
92
93     hbmNewBitmap =
94         CreateBitmap (nNewWidth, himl->cy, 1, himl->uBitsPixel, NULL);
95     if (hbmNewBitmap == 0)
96         ERR (imagelist, "creating new image bitmap!\n");
97
98     SelectObject (hdcImageList, himl->hbmImage);
99     SelectObject (hdcBitmap, hbmNewBitmap);
100     BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, himl->cy,
101               hdcImageList, 0, 0, SRCCOPY);
102
103     DeleteObject (himl->hbmImage);
104     himl->hbmImage = hbmNewBitmap;
105
106     if (himl->hbmMask) {
107         hbmNewBitmap = 
108             CreateBitmap (nNewWidth, himl->cy, 1, 1, NULL);
109
110         if (hbmNewBitmap == 0)
111             ERR (imagelist, "creating new mask bitmap!");
112
113         SelectObject (hdcImageList, himl->hbmMask);
114         SelectObject (hdcBitmap, hbmNewBitmap);
115         BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, himl->cy,
116                   hdcImageList, 0, 0, SRCCOPY);
117         DeleteObject (himl->hbmMask);
118         himl->hbmMask = hbmNewBitmap;
119     }
120
121     himl->cMaxImage = nNewCount;
122
123     DeleteDC (hdcImageList);
124     DeleteDC (hdcBitmap);
125 }
126
127
128 /*************************************************************************
129  * ImageList_Add [COMCTL32.39]
130  *
131  * Add an image or images to an image list.
132  *
133  * PARAMS
134  *     himl     [I] handle to image list
135  *     hbmImage [I] handle to image bitmap
136  *     hbmMask  [I] handle to mask bitmap
137  *
138  * RETURNS
139  *     Success: Index of the first new image.
140  *     Failure: -1
141  */
142
143 INT WINAPI
144 ImageList_Add (HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
145 {
146     HDC    hdcSrc, hdcDst;
147     INT    nFirstIndex, nImageCount;
148     INT    nStartX;
149     BITMAP bmp;
150
151     if (!himl || !hbmImage)
152         return -1;
153
154     GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
155     nImageCount = bmp.bmWidth / himl->cx;
156
157     if (himl->cCurImage + nImageCount >= himl->cMaxImage)
158         IMAGELIST_InternalExpandBitmaps (himl, nImageCount);
159
160     nStartX = himl->cCurImage * himl->cx;
161
162     hdcSrc = CreateCompatibleDC (0);
163     hdcDst = CreateCompatibleDC (0);
164
165     /* copy image bitmap */
166     SelectObject (hdcDst, himl->hbmImage);
167     SelectObject (hdcSrc, hbmImage);
168     BitBlt (hdcDst, himl->cCurImage * himl->cx, 0,
169               bmp.bmWidth, himl->cy, hdcSrc, 0, 0, SRCCOPY);
170           
171     if (himl->hbmMask) {
172         if (hbmMask) {
173             /* copy mask bitmap */
174             SelectObject (hdcDst, himl->hbmMask);
175             SelectObject (hdcSrc, hbmMask);
176             BitBlt (hdcDst, nStartX, 0, bmp.bmWidth, himl->cy,
177                       hdcSrc, 0, 0, SRCCOPY);
178         }
179         else {
180             /* copy monochrome image to the mask bitmap */
181             SelectObject (hdcDst, himl->hbmMask);
182             SelectObject (hdcSrc, hbmImage);
183             SetBkColor (hdcSrc, GetNearestColor (hdcSrc,
184                           GetPixel (hdcSrc, 0, 0)));
185             BitBlt (hdcDst, nStartX, 0, bmp.bmWidth, himl->cy,
186                       hdcSrc, nStartX, 0, SRCCOPY);
187         }
188     }
189
190     DeleteDC (hdcSrc);
191     DeleteDC (hdcDst);
192
193     nFirstIndex = himl->cCurImage;
194     himl->cCurImage += nImageCount;
195
196     return nFirstIndex;
197 }
198
199
200 /*************************************************************************
201  * ImageList_AddIcon [COMCTL32.40]
202  *
203  * Adds an icon to an image list.
204  *
205  * PARAMS
206  *     himl  [I] handle to image list
207  *     hIcon [I] handle to icon
208  *
209  * RETURNS
210  *     Success: index of the new image
211  *     Failure: -1
212  */
213
214 INT WINAPI
215 ImageList_AddIcon (HIMAGELIST himl, HICON hIcon)
216 {
217     return ImageList_ReplaceIcon (himl, -1, hIcon);
218 }
219
220
221 /*************************************************************************
222  * ImageList_AddMasked [COMCTL32.41] 
223  *
224  * Adds an image or images to an image list and creates a mask from the
225  * specified bitmap using the mask color.
226  *
227  * PARAMS
228  *     himl    [I] handle to image list.
229  *     hBitmap [I] handle to bitmap
230  *     clrMask [I] mask color.
231  *
232  * RETURNS
233  *     Success: Index of the first new image.
234  *     Failure: -1
235  */
236
237 INT WINAPI
238 ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
239 {
240     HDC    hdcImage, hdcMask, hdcBitmap;
241     INT    nIndex, nImageCount;
242     BITMAP bmp;
243
244     if (himl == NULL)
245         return -1;
246
247     if (!GetObjectA (hBitmap, sizeof(BITMAP), &bmp))
248         return -1;
249
250     nImageCount = bmp.bmWidth / himl->cx;
251
252     if (himl->cCurImage + nImageCount >= himl->cMaxImage)
253         IMAGELIST_InternalExpandBitmaps (himl, nImageCount);
254
255     nIndex = himl->cCurImage;
256     himl->cCurImage += nImageCount;
257
258     hdcImage  = CreateCompatibleDC (0);
259     hdcBitmap = CreateCompatibleDC (0);
260
261     SelectObject (hdcBitmap, hBitmap);
262     SelectObject (hdcImage, himl->hbmImage);
263     BitBlt (hdcImage, nIndex * himl->cx, 0, bmp.bmWidth, himl->cy,
264               hdcBitmap, 0, 0, SRCCOPY);
265
266     if (himl->hbmMask) {
267         COLORREF bkColor = (clrMask != CLR_DEFAULT) ? clrMask :
268             GetNearestColor (hdcBitmap, GetPixel (hdcBitmap, 0, 0));
269
270         /* create mask from image */
271         hdcMask = CreateCompatibleDC (0);
272         SelectObject (hdcMask, himl->hbmMask);
273
274         /* create monochrome image to the mask bitmap */
275         SetBkColor (hdcBitmap, bkColor);
276         BitBlt (hdcMask, nIndex * himl->cx, 0, bmp.bmWidth, himl->cy,
277                   hdcBitmap, 0, 0, SRCCOPY);
278
279         DeleteDC (hdcMask);
280     }
281
282     DeleteDC (hdcImage);
283     DeleteDC (hdcBitmap);
284   
285     return nIndex;
286 }
287
288
289 /*************************************************************************
290  * ImageList_BeginDrag [COMCTL32.42] 
291  *
292  * Creates a temporary image list that contains one image. It will be used
293  * as a drag image.
294  *
295  * PARAMS
296  *     himlTrack [I] handle to the source image list
297  *     iTrack    [I] index of the drag image in the source image list
298  *     dxHotspot [I] X position of the hot spot of the drag image
299  *     dyHotspot [I] Y position of the hot spot of the drag image
300  *
301  * RETURNS
302  *     Success: TRUE
303  *     Failure: FALSE
304  */
305
306 BOOL WINAPI
307 ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
308                      INT dxHotspot, INT dyHotspot)
309 {
310     HDC hdcSrc, hdcDst;
311
312     FIXME(imagelist, "partially implemented!\n");
313
314     if (himlTrack == NULL)
315         return FALSE;
316
317     if (himlInternalDrag)
318         ImageList_EndDrag ();
319
320     himlInternalDrag =
321         ImageList_Create (himlTrack->cx, himlTrack->cy,
322                           himlTrack->flags, 1, 1);
323     if (himlInternalDrag == NULL) {
324         ERR(imagelist, "Error creating drag image list!\n");
325         return FALSE;
326     }
327
328     nInternalDragHotspotX = dxHotspot;
329     nInternalDragHotspotY = dyHotspot;
330
331     hdcSrc = CreateCompatibleDC (0);
332     hdcDst = CreateCompatibleDC (0);
333
334     /* copy image */
335     SelectObject (hdcSrc, himlTrack->hbmImage);
336     SelectObject (hdcDst, himlInternalDrag->hbmImage);
337     StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
338                   iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
339
340     /* copy mask */
341     SelectObject (hdcSrc, himlTrack->hbmMask);
342     SelectObject (hdcDst, himlInternalDrag->hbmMask);
343     StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc,
344                   iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY);
345
346     DeleteDC (hdcSrc);
347     DeleteDC (hdcDst);
348
349     himlInternalDrag->cCurImage = 1;
350
351     return TRUE;
352 }
353
354
355 /*************************************************************************
356  * ImageList_Copy [COMCTL32.43] 
357  *
358  *  Copies an image of the source image list to an image of the 
359  *  destination image list. Images can be copied or swapped.
360  *
361  * PARAMS
362  *     himlDst [I] handle to the destination image list
363  *     iDst    [I] destination image index.
364  *     himlSrc [I] handle to the source image list
365  *     iSrc    [I] source image index
366  *     uFlags  [I] flags for the copy operation
367  *
368  * RETURNS
369  *     Success: TRUE
370  *     Failure: FALSE
371  *
372  * NOTES
373  *     Copying from one image list to another is possible. The original
374  *     implementation just copies or swapps within one image list.
375  *     Could this feature become a bug??? ;-)
376  */
377
378 BOOL WINAPI
379 ImageList_Copy (HIMAGELIST himlDst, INT iDst,   HIMAGELIST himlSrc,
380                 INT iSrc, INT uFlags)
381 {
382     HDC hdcSrc, hdcDst;    
383
384     TRACE(imagelist, "iDst=%d  iSrc=%d\n", iDst, iSrc);
385
386     if ((himlSrc == NULL) || (himlDst == NULL))
387         return FALSE;
388     if ((iDst < 0) || (iDst >= himlDst->cCurImage))
389         return FALSE;
390     if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage))
391         return FALSE;
392
393     hdcSrc = CreateCompatibleDC (0);
394     if (himlDst == himlSrc)
395         hdcDst = hdcSrc;
396     else
397         hdcDst = CreateCompatibleDC (0);
398
399     if (uFlags & ILCF_SWAP) {
400         /* swap */
401         HBITMAP hbmTempImage, hbmTempMask;
402
403         /* create temporary bitmaps */
404         hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
405                                        himlSrc->uBitsPixel, NULL);
406         hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
407                                       1, NULL);
408
409         /* copy (and stretch) destination to temporary bitmaps.(save) */
410         /* image */
411         SelectObject (hdcSrc, himlDst->hbmImage);
412         SelectObject (hdcDst, hbmTempImage);
413         StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
414                       hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
415                       SRCCOPY);
416         /* mask */
417         SelectObject (hdcSrc, himlDst->hbmMask);
418         SelectObject (hdcDst, hbmTempMask);
419         StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
420                       hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
421                       SRCCOPY);
422
423         /* copy (and stretch) source to destination */
424         /* image */
425         SelectObject (hdcSrc, himlSrc->hbmImage);
426         SelectObject (hdcDst, himlDst->hbmImage);
427         StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
428                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
429                       SRCCOPY);
430         /* mask */
431         SelectObject (hdcSrc, himlSrc->hbmMask);
432         SelectObject (hdcDst, himlDst->hbmMask);
433         StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
434                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
435                       SRCCOPY);
436
437         /* copy (without stretching) temporary bitmaps to source (restore) */
438         /* image */
439         SelectObject (hdcSrc, hbmTempImage);
440         SelectObject (hdcDst, himlSrc->hbmImage);
441         BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
442                   hdcSrc, 0, 0, SRCCOPY);
443         /* mask */
444         SelectObject (hdcSrc, hbmTempMask);
445         SelectObject (hdcDst, himlSrc->hbmMask);
446         BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
447                   hdcSrc, 0, 0, SRCCOPY);
448
449         /* delete temporary bitmaps */
450         DeleteObject (hbmTempMask);
451         DeleteObject (hbmTempImage);
452     }
453     else {
454         /* copy image */
455         SelectObject (hdcSrc, himlSrc->hbmImage);
456         if (himlSrc == himlDst)
457             hdcDst = hdcSrc;
458         else
459             SelectObject (hdcDst, himlDst->hbmImage);
460         StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
461                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
462                       SRCCOPY);
463
464         /* copy mask */
465         SelectObject (hdcSrc, himlSrc->hbmMask);
466         if (himlSrc == himlDst)
467             hdcDst = hdcSrc;
468         else
469             SelectObject (hdcDst, himlDst->hbmMask);
470         StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
471                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
472                       SRCCOPY);
473     }
474
475     DeleteDC (hdcSrc);
476     if (himlSrc != himlDst)
477         DeleteDC (hdcDst);
478
479     return TRUE;
480 }
481
482
483 /*************************************************************************
484  * ImageList_Create [COMCTL32.44]  Creates a new image list.
485  *
486  * PARAMS
487  *     cx       [I] image height
488  *     cy       [I] image width
489  *     flags    [I] creation flags
490  *     cInitial [I] initial number of images in the image list
491  *     cGrow    [I] number of images by which image list grows
492  *
493  * RETURNS
494  *     Success: Handle to the created image list
495  *     Failure: NULL
496  */
497
498 HIMAGELIST WINAPI
499 ImageList_Create (INT cx, INT cy, UINT flags,
500                   INT cInitial, INT cGrow)
501 {
502     HIMAGELIST himl;
503     HDC      hdc;
504     INT      nCount;
505     HBITMAP  hbmTemp;
506     static WORD aBitBlend25[] = 
507         {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00};
508
509     static WORD aBitBlend50[] =
510         {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
511
512     TRACE (imagelist, "(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow);
513
514     himl = (HIMAGELIST)COMCTL32_Alloc (sizeof(struct _IMAGELIST));
515     if (!himl)
516         return NULL;
517
518     himl->cx        = cx;
519     himl->cy        = cy;
520     himl->flags     = flags;
521     himl->cMaxImage = cInitial + cGrow;
522     himl->cInitial  = cInitial;
523     himl->cGrow     = cGrow;
524     himl->cCurImage = 0;
525     himl->clrFg     = CLR_DEFAULT;
526     himl->clrBk     = CLR_NONE;
527
528     /* initialize overlay mask indices */
529     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
530         himl->nOvlIdx[nCount] = -1;
531
532     hdc = CreateCompatibleDC (0);
533     himl->uBitsPixel = (UINT)GetDeviceCaps (hdc, BITSPIXEL);
534     DeleteDC (hdc);
535
536     TRACE(imagelist, "Image: %d Bits per Pixel\n", himl->uBitsPixel);
537
538     himl->hbmImage =
539         CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
540                         1, himl->uBitsPixel, NULL);
541     if (himl->hbmImage == 0) {
542         ERR(imagelist, "Error creating image bitmap!\n");
543         return NULL;
544     }
545
546     if (himl->flags & ILC_MASK) {
547         himl->hbmMask = CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
548                                         1, 1, NULL);
549         if (himl->hbmMask == 0) {
550             ERR(imagelist, "Error creating mask bitmap!\n");
551             if (himl->hbmImage)
552                 DeleteObject (himl->hbmImage);
553             return NULL;
554         }
555     }
556     else
557         himl->hbmMask = 0;
558
559     /* create blending brushes */
560     hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend25);
561     himl->hbrBlend25 = CreatePatternBrush (hbmTemp);
562     DeleteObject (hbmTemp);
563
564     hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend50);
565     himl->hbrBlend50 = CreatePatternBrush (hbmTemp);
566     DeleteObject (hbmTemp);
567
568     return himl;
569 }
570
571
572 /*************************************************************************
573  * ImageList_Destroy [COMCTL32.45] 
574  *
575  * Destroys an image list.
576  *
577  * PARAMS
578  *     himl [I] handle to image list
579  *
580  * RETURNS
581  *     Success: TRUE
582  *     Failure: FALSE
583  */
584
585 BOOL WINAPI
586 ImageList_Destroy (HIMAGELIST himl)
587
588     if (!himl)
589         return FALSE;
590
591     /* delete image bitmaps */
592     if (himl->hbmImage)
593         DeleteObject (himl->hbmImage);
594     if (himl->hbmMask)
595         DeleteObject (himl->hbmMask);
596
597     /* delete blending brushes */
598     if (himl->hbrBlend25)
599         DeleteObject (himl->hbrBlend25);
600     if (himl->hbrBlend50)
601         DeleteObject (himl->hbrBlend50);
602         
603     COMCTL32_Free (himl);
604
605     return TRUE;
606 }
607
608
609 /*************************************************************************
610  * ImageList_DragEnter [COMCTL32.46] 
611  *
612  * Locks window update and displays the drag image at the given position.
613  *
614  * PARAMS
615  *     hwndLock [I] handle of the window that owns the drag image.
616  *     x        [I] X position of the drag image.
617  *     y        [I] Y position of the drag image.
618  *
619  * RETURNS
620  *     Success: TRUE
621  *     Failure: FALSE
622  *
623  * NOTES
624  *     The position of the drag image is relative to the window, not
625  *     the client area.
626  */
627
628 BOOL WINAPI
629 ImageList_DragEnter (HWND hwndLock, INT x, INT y)
630 {
631     if (himlInternalDrag == NULL)
632         return FALSE;
633
634     if (hwndLock)
635         hwndInternalDrag = hwndLock;
636     else
637         hwndInternalDrag = GetDesktopWindow ();
638
639     xInternalPos = x;
640     yInternalPos = y;
641
642     hdcBackBuffer = CreateCompatibleDC (0);
643     hbmBackBuffer = CreateCompatibleBitmap (hdcBackBuffer,
644                 himlInternalDrag->cx, himlInternalDrag->cy);
645
646     ImageList_DragShowNolock (TRUE);
647
648     return FALSE;
649 }
650
651
652 /*************************************************************************
653  * ImageList_DragLeave [COMCTL32.47] 
654  *
655  * Unlocks window update and hides the drag image.
656  *
657  * PARAMS
658  *     hwndLock [I] handle of the window that owns the drag image.
659  *
660  * RETURNS
661  *     Success: TRUE
662  *     Failure: FALSE
663  */
664
665 BOOL WINAPI
666 ImageList_DragLeave (HWND hwndLock)
667 {
668     if (hwndLock)
669         hwndInternalDrag = hwndLock;
670     else
671         hwndInternalDrag = GetDesktopWindow ();
672
673     ImageList_DragShowNolock (FALSE);
674
675     DeleteDC (hdcBackBuffer);
676     DeleteObject (hbmBackBuffer);
677
678     return TRUE;
679 }
680
681
682 /*************************************************************************
683  * ImageList_DragMove [COMCTL32.48] 
684  *
685  * Moves the drag image.
686  *
687  * PARAMS
688  *     x [I] X position of the drag image.
689  *     y [I] Y position of the drag image.
690  *
691  * RETURNS
692  *     Success: TRUE
693  *     Failure: FALSE
694  *
695  * NOTES
696  *     The position of the drag image is relative to the window, not
697  *     the client area.
698  */
699
700 BOOL WINAPI
701 ImageList_DragMove (INT x, INT y)
702 {
703     ImageList_DragShowNolock (FALSE);
704
705     xInternalPos = x;
706     yInternalPos = y;
707
708     ImageList_DragShowNolock (TRUE);
709
710     return FALSE;
711 }
712
713
714 /*************************************************************************
715  * ImageList_DragShowNolock [COMCTL32.49] 
716  *
717  * Shows or hides the drag image.
718  *
719  * PARAMS
720  *     bShow [I] TRUE shows the drag image, FALSE hides it.
721  *
722  * RETURNS
723  *     Success: TRUE
724  *     Failure: FALSE
725  *
726  * FIXME
727  *     semi-stub.
728  */
729
730 BOOL WINAPI
731 ImageList_DragShowNolock (BOOL bShow)
732 {
733     HDC hdcDrag;
734
735     FIXME (imagelist, "semi-stub!\n");
736     TRACE (imagelist, "bShow=0x%X!\n", bShow);
737
738     hdcDrag = GetDCEx (hwndInternalDrag, 0,
739                          DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
740
741     if (bShow) {
742         /* show drag image */
743
744         /* save background */
745
746         /* draw drag image */
747
748     }
749     else {
750         /* hide drag image */
751
752         /* restore background */
753
754     }
755
756     ReleaseDC (hwndInternalDrag, hdcDrag);
757
758     return FALSE;
759 }
760
761
762 /*************************************************************************
763  * ImageList_Draw [COMCTL32.50] Draws an image.
764  *
765  * PARAMS
766  *     himl   [I] handle to image list
767  *     i      [I] image index
768  *     hdc    [I] handle to device context
769  *     x      [I] x position
770  *     y      [I] y position
771  *     fStyle [I] drawing flags
772  *
773  * RETURNS
774  *     Success: TRUE
775  *     Failure: FALSE
776  *
777  * NOTES
778  *     Calls ImageList_DrawIndirect.
779  *
780  * SEE
781  *     ImageList_DrawIndirect.
782  */
783
784 BOOL WINAPI
785 ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc,
786                 INT x, INT y, UINT fStyle)
787 {
788     IMAGELISTDRAWPARAMS imldp;
789
790     imldp.cbSize  = sizeof(IMAGELISTDRAWPARAMS);
791     imldp.himl    = himl;
792     imldp.i       = i;
793     imldp.hdcDst  = hdc,
794     imldp.x       = x;
795     imldp.y       = y;
796     imldp.cx      = 0;
797     imldp.cy      = 0;
798     imldp.xBitmap = 0;
799     imldp.yBitmap = 0;
800     imldp.rgbBk   = CLR_DEFAULT;
801     imldp.rgbFg   = CLR_DEFAULT;
802     imldp.fStyle  = fStyle;
803     imldp.dwRop   = 0;
804
805     return ImageList_DrawIndirect (&imldp);
806 }
807
808
809 /*************************************************************************
810  * ImageList_DrawEx [COMCTL32.51]
811  *
812  * Draws an image and allows to use extended drawing features.
813  *
814  * PARAMS
815  *     himl   [I] handle to image list
816  *     i      [I] image index
817  *     hdc    [I] handle to device context
818  *     x      [I] X position
819  *     y      [I] Y position
820  *     xOffs  [I] X offset
821  *     yOffs  [I] Y offset
822  *     rgbBk  [I] background color
823  *     rgbFg  [I] foreground color
824  *     fStyle [I] drawing flags
825  *
826  * RETURNS
827  *     Success: TRUE
828  *     Failure: FALSE
829  *
830  * NOTES
831  *     Calls ImageList_DrawIndirect.
832  *
833  * SEE
834  *     ImageList_DrawIndirect.
835  */
836
837 BOOL WINAPI
838 ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y,
839                   INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg,
840                   UINT fStyle)
841 {
842     IMAGELISTDRAWPARAMS imldp;
843
844     imldp.cbSize  = sizeof(IMAGELISTDRAWPARAMS);
845     imldp.himl    = himl;
846     imldp.i       = i;
847     imldp.hdcDst  = hdc,
848     imldp.x       = x;
849     imldp.y       = y;
850     imldp.cx      = dx;
851     imldp.cy      = dy;
852     imldp.xBitmap = 0;
853     imldp.yBitmap = 0;
854     imldp.rgbBk   = rgbBk;
855     imldp.rgbFg   = rgbFg;
856     imldp.fStyle  = fStyle;
857     imldp.dwRop   = 0;
858
859     return ImageList_DrawIndirect (&imldp);
860 }
861
862
863 /*************************************************************************
864  * ImageList_DrawIndirect [COMCTL32.52] 
865  *
866  * Draws an image using ...
867  *
868  * PARAMS
869  *     pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
870  *
871  * RETURNS
872  *     Success: TRUE
873  *     Failure: FALSE
874  */
875
876 BOOL WINAPI
877 ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
878 {
879     HIMAGELIST himlLocal;
880     HDC      hdcImageList, hdcTempImage;
881     HBITMAP  hbmTempImage;
882     HBRUSH   hBrush, hOldBrush;
883     INT      cx, cy;
884     INT      nOvlIdx;
885     COLORREF   clrBlend;
886     BOOL     bImage;       /* draw image ? */
887     BOOL     bImageTrans;  /* draw image transparent ? */
888     BOOL     bMask;        /* draw mask ? */
889     BOOL     bMaskTrans;   /* draw mask transparent ? */
890     BOOL     bBlend25;
891     BOOL     bBlend50;
892
893     if (pimldp == NULL)
894         return FALSE;
895     if (pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS))
896         return FALSE;
897     if (pimldp->himl == NULL)
898         return FALSE;
899     if ((pimldp->i < 0) || (pimldp->i > pimldp->himl->cCurImage))
900         return FALSE;
901
902     himlLocal = pimldp->himl;
903
904     cx = (pimldp->cx == 0) ? himlLocal->cx : pimldp->cx;
905     cy = (pimldp->cy == 0) ? himlLocal->cy : pimldp->cy;
906
907     /* ILD_NORMAL state */
908     bImage      = TRUE;
909     bImageTrans = FALSE;
910     bMask       = FALSE;
911     bMaskTrans  = FALSE;
912     bBlend25    = FALSE;
913     bBlend50    = FALSE;
914     if ((himlLocal->clrBk == CLR_NONE) && (himlLocal->hbmMask))
915     {
916         bImageTrans = TRUE;
917         bMask = TRUE;
918         bMaskTrans = TRUE;
919     }
920     
921     /* ILD_IMAGE state (changes) */
922     if (pimldp->fStyle & ILD_IMAGE)
923     {
924         bMask = FALSE;
925         bImage = TRUE;
926         bImageTrans = FALSE;
927     }
928     
929     /* ILD_MASK state (changes) */
930     if ((pimldp->fStyle & ILD_MASK) && (himlLocal->hbmMask))
931     {
932         bMask  = TRUE;
933         bMaskTrans = FALSE;
934         bImage = FALSE;
935     }
936     if ((pimldp->fStyle & ILD_TRANSPARENT) && (himlLocal->hbmMask))
937     {
938         bMaskTrans = TRUE;
939         bImageTrans = TRUE;
940     }
941     if ((himlLocal->clrBk == CLR_NONE) && (himlLocal->hbmMask))
942         bMaskTrans = TRUE;
943
944     if (pimldp->fStyle & ILD_BLEND50)
945         bBlend50 = TRUE;
946     else if (pimldp->fStyle & ILD_BLEND25)
947         bBlend25 = TRUE;
948
949     hdcImageList = CreateCompatibleDC (0);
950
951     if (bMask)
952     {
953         /* draw the mask */
954         SelectObject (hdcImageList, himlLocal->hbmMask);
955         SetBkColor (hdcImageList, RGB(255, 255, 255));
956         SetTextColor (hdcImageList, RGB(0, 0, 0));
957         BitBlt (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
958                   hdcImageList, himlLocal->cx * pimldp->i, 0,
959                   bMaskTrans ? SRCAND : SRCCOPY);
960     }
961
962     if (bImage)
963     {
964         /* draw the image */
965         SelectObject (hdcImageList, himlLocal->hbmImage);
966
967         if (!bImageTrans)
968         {
969             hBrush = CreateSolidBrush (himlLocal->clrBk);
970             hOldBrush = SelectObject (pimldp->hdcDst, hBrush);
971             PatBlt (pimldp->hdcDst, pimldp->x, pimldp->y,
972                       cx, cy, PATCOPY);
973             DeleteObject (SelectObject (pimldp->hdcDst, hOldBrush));
974         }
975
976         BitBlt (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
977                   hdcImageList, himlLocal->cx * pimldp->i, 0, SRCPAINT);
978
979         if (bBlend25 || bBlend50)
980         {
981             if (pimldp->rgbFg == CLR_DEFAULT)
982                 clrBlend = GetSysColor (COLOR_HIGHLIGHT);
983             else
984                 clrBlend = pimldp->rgbFg;
985
986             hdcTempImage = CreateCompatibleDC (0);
987             hbmTempImage = CreateBitmap (himlLocal->cx, himlLocal->cy,
988                                            1, himlLocal->uBitsPixel, NULL);
989             SelectObject (hdcTempImage, hbmTempImage);
990
991
992             /* mask */
993             SelectObject (hdcTempImage,
994                             bBlend50 ? himlLocal->hbrBlend50 : himlLocal->hbrBlend25);
995             PatBlt (hdcTempImage, 0, 0, himlLocal->cx, himlLocal->cy, PATCOPY);
996
997             SelectObject (hdcImageList, himlLocal->hbmMask);
998             BitBlt (hdcTempImage, 0, 0, himlLocal->cx,
999                       himlLocal->cy, hdcImageList, 
1000                       pimldp->i * himlLocal->cx, 0, SRCPAINT);
1001
1002             BitBlt (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
1003                       hdcTempImage, 0, 0, SRCAND);
1004
1005             /* fill */
1006             hBrush = CreateSolidBrush (clrBlend);
1007             SelectObject (hdcTempImage, hBrush);
1008             PatBlt (hdcTempImage, 0, 0, himlLocal->cx, himlLocal->cy, PATCOPY);
1009             DeleteObject (hBrush);
1010
1011             SelectObject (hdcTempImage,
1012                             bBlend50 ? himlLocal->hbrBlend50 : himlLocal->hbrBlend25);
1013             PatBlt (hdcTempImage, 0, 0, himlLocal->cx, himlLocal->cy, 0x0A0329);
1014
1015             SelectObject (hdcImageList, himlLocal->hbmMask);
1016             BitBlt (hdcTempImage, 0, 0, himlLocal->cx,
1017                       himlLocal->cy, hdcImageList, 
1018                       pimldp->i * himlLocal->cx, 0, SRCPAINT);
1019
1020             BitBlt (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
1021                       hdcTempImage, 0, 0, SRCPAINT);
1022
1023             DeleteObject (hbmTempImage);
1024             DeleteDC (hdcTempImage);
1025         }
1026     }   
1027
1028     /* Draw overlay image */
1029     if (pimldp->fStyle & 0x0700) {
1030         nOvlIdx = (pimldp->fStyle & 0x0700) >> 8;
1031         if ((nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE)) {
1032             nOvlIdx = pimldp->himl->nOvlIdx[nOvlIdx - 1];
1033             if ((nOvlIdx >= 0) && (nOvlIdx <= pimldp->himl->cCurImage)) {
1034                 if (pimldp->himl->hbmMask) {  
1035                     SelectObject (hdcImageList, pimldp->himl->hbmMask);
1036                     BitBlt (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
1037                               hdcImageList, pimldp->himl->cx * nOvlIdx, 0,
1038                               SRCAND);
1039                 }  
1040                 SelectObject (hdcImageList, pimldp->himl->hbmImage);
1041                 BitBlt (pimldp->hdcDst, pimldp->x, pimldp->y,
1042                           cx, cy, hdcImageList,
1043                           pimldp->himl->cx * nOvlIdx, 0, SRCPAINT);
1044             }
1045         }
1046     }
1047
1048     DeleteDC (hdcImageList);
1049   
1050     return TRUE;
1051 }
1052
1053
1054 /*************************************************************************
1055  * ImageList_Duplicate [COMCTL32.53] Duplicates an image list.
1056  *
1057  * PARAMS
1058  *     himlSrc [I] source image list handle
1059  *
1060  * RETURNS
1061  *     Success: Handle of duplicated image list.
1062  *     Failure: NULL
1063  */
1064
1065 HIMAGELIST WINAPI
1066 ImageList_Duplicate (HIMAGELIST himlSrc)
1067 {
1068     HIMAGELIST himlDst;
1069     HDC hdcSrc, hdcDst;
1070
1071     if (himlSrc == NULL) {
1072         ERR (imagelist, "Invalid image list handle!\n");
1073         return NULL;
1074     }
1075
1076     himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
1077                                 himlSrc->cInitial, himlSrc->cGrow);
1078
1079     if (himlDst)
1080     {
1081         hdcSrc = CreateCompatibleDC (0);
1082         hdcDst = CreateCompatibleDC (0);
1083         SelectObject (hdcSrc, himlSrc->hbmImage);
1084         SelectObject (hdcDst, himlDst->hbmImage);
1085         BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy,
1086                   hdcSrc, 0, 0, SRCCOPY);
1087
1088         if (himlDst->hbmMask)
1089         {
1090             SelectObject (hdcSrc, himlSrc->hbmMask);
1091             SelectObject (hdcDst, himlDst->hbmMask);
1092             BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx,
1093                       himlSrc->cy, hdcSrc, 0, 0, SRCCOPY);
1094         }
1095
1096         DeleteDC (hdcDst);
1097         DeleteDC (hdcSrc);
1098     }
1099
1100     return himlDst;
1101 }
1102
1103
1104 /*************************************************************************
1105  * ImageList_EndDrag [COMCTL32.54] Finishes a drag operation.
1106  *
1107  * Finishes a drag operation.
1108  *
1109  * PARAMS
1110  *     no Parameters
1111  *
1112  * RETURNS
1113  *     Success: TRUE
1114  *     Failure: FALSE
1115  *
1116  * BUGS
1117  *     semi-stub.
1118  */
1119
1120 BOOL WINAPI
1121 ImageList_EndDrag (VOID)
1122 {
1123     FIXME (imagelist, "semi-stub!\n");
1124
1125     if (himlInternalDrag)
1126     {
1127
1128         ImageList_Destroy (himlInternalDrag);
1129         himlInternalDrag = NULL;
1130
1131         nInternalDragHotspotX = 0;
1132         nInternalDragHotspotY = 0;
1133
1134     }
1135
1136     return TRUE;
1137 }
1138
1139
1140 /*************************************************************************
1141  * ImageList_GetBkColor [COMCTL32.55]
1142  *
1143  * Returns the background color of an image list.
1144  *
1145  * PARAMS
1146  *     himl [I] Image list handle.
1147  *
1148  * RETURNS
1149  *     Success: background color
1150  *     Failure: CLR_NONE
1151  */
1152
1153 COLORREF WINAPI
1154 ImageList_GetBkColor (HIMAGELIST himl)
1155 {
1156     if (himl == NULL)
1157         return CLR_NONE;
1158
1159     return himl->clrBk;
1160 }
1161
1162
1163 /*************************************************************************
1164  * ImageList_GetDragImage [COMCTL32.56]
1165  *
1166  * Returns the handle to the internal drag image list.
1167  *
1168  * PARAMS
1169  *     ppt        [O] Pointer to the drag position. Can be NULL.
1170  *     pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
1171  *
1172  * RETURNS
1173  *     Success: Handle of the drag image list.
1174  *     Failure: NULL.
1175  *
1176  * BUGS
1177  *     semi-stub.
1178  */
1179
1180 HIMAGELIST WINAPI
1181 ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot)
1182 {
1183     FIXME (imagelist, "semi-stub!\n");
1184
1185     if (himlInternalDrag)
1186         return (himlInternalDrag);
1187
1188     return NULL;
1189 }
1190
1191
1192 /*************************************************************************
1193  * ImageList_GetIcon [COMCTL32.57] 
1194  *
1195  * Creates an icon from a masked image of an image list.
1196  *
1197  * PARAMS
1198  *     himl  [I] handle to image list
1199  *     i     [I] image index
1200  *     flags [I] drawing style flags
1201  *
1202  * RETURNS
1203  *     Success: icon handle
1204  *     Failure: NULL
1205  */
1206
1207 HICON WINAPI
1208 ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle)
1209 {
1210     ICONINFO ii;
1211     HICON  hIcon;
1212     HDC    hdcSrc, hdcDst;
1213     INT    nWidth, nHeight;
1214
1215     if ((himl == NULL) || (i < 0) || (i >= himl->cCurImage))
1216         return 0;
1217
1218     nWidth = GetSystemMetrics (SM_CXICON);
1219     nHeight = GetSystemMetrics (SM_CYICON);
1220
1221     hdcSrc = CreateCompatibleDC(0);
1222     hdcDst = CreateCompatibleDC(0);
1223
1224     ii.fIcon = TRUE;
1225     ii.xHotspot = nWidth / 2;
1226     ii.yHotspot = nHeight / 2;
1227     ii.hbmMask  = CreateCompatibleBitmap (hdcDst, nWidth, nHeight);
1228     ii.hbmColor = CreateCompatibleBitmap (hdcDst, nWidth, nHeight);
1229
1230
1231     /* draw mask*/
1232     SelectObject (hdcDst, ii.hbmMask);
1233     if (himl->hbmMask) {
1234         SelectObject (hdcSrc, himl->hbmMask);
1235         BitBlt (hdcDst, 0, 0, nWidth, nHeight,
1236                   hdcSrc, i * himl->cx, 0, SRCCOPY);
1237     }
1238     else
1239         PatBlt (hdcDst, 0, 0, nWidth, nHeight, BLACKNESS);
1240
1241     /* draw image*/
1242     SelectObject (hdcDst, ii.hbmColor);
1243     SelectObject (hdcSrc, himl->hbmImage);
1244     BitBlt (hdcDst, 0, 0, nWidth, nHeight,
1245               hdcSrc, i * himl->cx, 0, SRCCOPY);
1246
1247     hIcon = CreateIconIndirect (&ii);    
1248
1249     DeleteDC (hdcSrc);
1250     DeleteDC (hdcDst);
1251     DeleteObject (ii.hbmMask);
1252     DeleteObject (ii.hbmColor);
1253
1254     return hIcon;
1255 }
1256
1257
1258 /*************************************************************************
1259  * ImageList_GetIconSize [COMCTL32.58]
1260  *
1261  * Retrieves the size of an image in an image list.
1262  *
1263  * PARAMS
1264  *     himl [I] handle to image list
1265  *     cx   [O] pointer to the image width.
1266  *     cy   [O] pointer to the image height.
1267  *
1268  * RETURNS
1269  *     Success: TRUE
1270  *     Failure: FALSE
1271  *
1272  * NOTES
1273  *     All images in an image list have the same size.
1274  */
1275
1276 BOOL WINAPI
1277 ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy)
1278 {
1279     if (himl == NULL)
1280         return FALSE;
1281     if ((himl->cx <= 0) || (himl->cy <= 0))
1282         return FALSE;
1283
1284     if (cx)
1285         *cx = himl->cx;
1286     if (cy)
1287         *cy = himl->cy;
1288
1289     return TRUE;
1290 }
1291
1292
1293 /*************************************************************************
1294  * ImageList_GetImageCount [COMCTL32.59]
1295  *
1296  * Returns the number of images in an image list.
1297  *
1298  * PARAMS
1299  *     himl [I] handle to image list
1300  *
1301  * RETURNS
1302  *     Success: Number of images.
1303  *     Failure: 0
1304  */
1305
1306 INT WINAPI
1307 ImageList_GetImageCount (HIMAGELIST himl)
1308 {
1309     if (himl == NULL)
1310         return 0;
1311
1312     return himl->cCurImage;
1313 }
1314
1315
1316 /*************************************************************************
1317  * ImageList_GetImageInfo [COMCTL32.60]
1318  *
1319  * Returns information about an image in an image list.
1320  *
1321  * PARAMS
1322  *     himl       [I] handle to image list
1323  *     i          [I] image index
1324  *     pImageInfo [O] pointer to the image information
1325  *
1326  * RETURNS
1327  *     Success: TRUE
1328  *     Failure: FALSE
1329  */
1330
1331 BOOL WINAPI
1332 ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
1333 {
1334     if ((himl == NULL) || (pImageInfo == NULL))
1335         return FALSE;
1336     if ((i < 0) || (i >= himl->cCurImage))
1337         return FALSE;
1338
1339     pImageInfo->hbmImage = himl->hbmImage;
1340     pImageInfo->hbmMask  = himl->hbmMask;
1341     
1342     pImageInfo->rcImage.top    = 0;
1343     pImageInfo->rcImage.bottom = himl->cy;
1344     pImageInfo->rcImage.left   = i * himl->cx;
1345     pImageInfo->rcImage.right  = (i+1) * himl->cx;
1346     
1347     return TRUE;
1348 }
1349
1350
1351 /*************************************************************************
1352  * ImageList_GetImageRect [COMCTL32.61] 
1353  *
1354  * Retrieves the rectangle of the specified image in an image list.
1355  *
1356  * PARAMS
1357  *     himl   [I] handle to image list
1358  *     i      [I] image index
1359  *     lpRect [O] pointer to the image rectangle
1360  *
1361  * RETURNS
1362  *    Success: TRUE
1363  *    Failure: FALSE
1364  *
1365  * NOTES
1366  *    This is an UNDOCUMENTED function!!!
1367  */
1368
1369 BOOL WINAPI
1370 ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect)
1371 {
1372     if ((himl == NULL) || (lpRect == NULL))
1373         return FALSE;
1374     if ((i < 0) || (i >= himl->cCurImage))
1375         return FALSE;
1376
1377     lpRect->left   = i * himl->cx;
1378     lpRect->top    = 0;
1379     lpRect->right  = lpRect->left + himl->cx;
1380     lpRect->bottom = himl->cy;
1381
1382     return TRUE;
1383 }
1384
1385
1386 /*************************************************************************
1387  * ImageList_LoadImage32A [COMCTL32.63][COMCTL32.62]
1388  *
1389  * Creates an image list from a bitmap, icon or cursor.
1390  *
1391  * PARAMS
1392  *     hi      [I] instance handle
1393  *     lpbmp   [I] name or id of the image
1394  *     cx      [I] width of each image
1395  *     cGrow   [I] number of images to expand
1396  *     clrMask [I] mask color
1397  *     uType   [I] type of image to load
1398  *     uFlags  [I] loading flags
1399  *
1400  * RETURNS
1401  *     Success: handle to the loaded image list
1402  *     Failure: NULL
1403  *
1404  * SEE
1405  *     LoadImage ()
1406  */
1407
1408 HIMAGELIST WINAPI
1409 ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx,       INT cGrow,
1410                         COLORREF clrMask, UINT uType,   UINT uFlags)
1411 {
1412     HIMAGELIST himl = NULL;
1413     HANDLE   handle;
1414     INT      nImageCount;
1415
1416     handle = LoadImageA (hi, lpbmp, uType, 0, 0, uFlags);
1417     if (!handle) {
1418         ERR (imagelist, "Error loading image!\n");
1419         return NULL;
1420     }
1421
1422     if (uType == IMAGE_BITMAP) {
1423         BITMAP bmp;
1424         GetObjectA (handle, sizeof(BITMAP), &bmp);
1425         nImageCount = bmp.bmWidth / cx;
1426
1427         himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1428                                  nImageCount, cGrow);
1429         ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1430     }
1431     else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1432         ICONINFO ii;
1433         BITMAP bmp;
1434
1435         GetIconInfo (handle, &ii);
1436         GetObjectA (ii.hbmColor, sizeof(BITMAP), (LPVOID)&bmp);
1437         himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight, 
1438                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1439         ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1440         DeleteObject (ii.hbmColor);
1441         DeleteObject (ii.hbmMask);
1442     }
1443
1444     DeleteObject (handle);
1445     
1446     return himl;
1447 }
1448
1449
1450 /*************************************************************************
1451  * ImageList_LoadImage32W [COMCTL32.64]
1452  *
1453  * Creates an image list from a bitmap, icon or cursor.
1454  *
1455  * PARAMS
1456  *     hi      [I] instance handle
1457  *     lpbmp   [I] name or id of the image
1458  *     cx      [I] width of each image
1459  *     cGrow   [I] number of images to expand
1460  *     clrMask [I] mask color
1461  *     uType   [I] type of image to load
1462  *     uFlags  [I] loading flags
1463  *
1464  * RETURNS
1465  *     Success: handle to the loaded image list
1466  *     Failure: NULL
1467  *
1468  * SEE
1469  *     LoadImage ()
1470  */
1471
1472 HIMAGELIST WINAPI
1473 ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow,
1474                         COLORREF clrMask, UINT uType,   UINT uFlags)
1475 {
1476     HIMAGELIST himl = NULL;
1477     HANDLE   handle;
1478     INT      nImageCount;
1479
1480     handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags);
1481     if (!handle) {
1482         ERR (imagelist, "Error loading image!\n");
1483         return NULL;
1484     }
1485
1486     if (uType == IMAGE_BITMAP) {
1487         BITMAP bmp;
1488         GetObjectA (handle, sizeof(BITMAP), &bmp);
1489         nImageCount = bmp.bmWidth / cx;
1490
1491         himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1492                                  nImageCount, cGrow);
1493         ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1494     }
1495     else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1496         ICONINFO ii;
1497         BITMAP bmp;
1498
1499         GetIconInfo (handle, &ii);
1500         GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
1501         himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight, 
1502                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1503         ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1504         DeleteObject (ii.hbmColor);
1505         DeleteObject (ii.hbmMask);
1506     }
1507
1508     DeleteObject (handle);
1509     
1510     return himl;
1511 }
1512
1513
1514 /*************************************************************************
1515  * ImageList_Merge [COMCTL32.65] 
1516  *
1517  * Creates a new image list that contains a merged image from the specified
1518  * images of both source image lists.
1519  *
1520  * PARAMS
1521  *     himl1 [I] handle to first image list
1522  *     i1    [I] first image index
1523  *     himl2 [I] handle to second image list
1524  *     i2    [I] second image index
1525  *     dx    [I] X offset of the second image relative to the first.
1526  *     dy    [I] Y offset of the second image relative to the first.
1527  *
1528  * RETURNS
1529  *     Success: handle of the merged image list.
1530  *     Failure: NULL
1531  */
1532
1533 HIMAGELIST WINAPI
1534 ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
1535                  INT dx, INT dy)
1536 {
1537     HIMAGELIST himlDst = NULL;
1538     HDC      hdcSrcImage, hdcDstImage;
1539     INT      cxDst, cyDst;
1540     INT      xOff1, yOff1, xOff2, yOff2;
1541     INT      nX1, nX2;
1542
1543     if ((himl1 == NULL) || (himl2 == NULL))
1544         return NULL;
1545
1546     /* check indices */
1547     if ((i1 < 0) || (i1 >= himl1->cCurImage)) {
1548         ERR (imagelist, "Index 1 out of range! %d\n", i1);
1549         return NULL;
1550     }
1551
1552     if ((i2 < 0) || (i2 >= himl2->cCurImage)) {
1553         ERR (imagelist, "Index 2 out of range! %d\n", i2);
1554         return NULL;
1555     }
1556
1557     if (dx > 0) {
1558         cxDst = _MAX (himl1->cx, dx + himl2->cx);
1559         xOff1 = 0;
1560         xOff2 = dx;
1561     }
1562     else if (dx < 0) {
1563         cxDst = _MAX (himl2->cx, himl1->cx - dx);
1564         xOff1 = -dx;
1565         xOff2 = 0;
1566     }
1567     else {
1568         cxDst = _MAX (himl1->cx, himl2->cx);
1569         xOff1 = 0;
1570         xOff2 = 0;
1571     }
1572
1573     if (dy > 0) {
1574         cyDst = _MAX (himl1->cy, dy + himl2->cy);
1575         yOff1 = 0;
1576         yOff2 = dy;
1577     }
1578     else if (dy < 0) {
1579         cyDst = _MAX (himl2->cy, himl1->cy - dy);
1580         yOff1 = -dy;
1581         yOff2 = 0;
1582     }
1583     else {
1584         cyDst = _MAX (himl1->cy, himl2->cy);
1585         yOff1 = 0;
1586         yOff2 = 0;
1587     }
1588
1589     himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
1590
1591     if (himlDst) {
1592         hdcSrcImage = CreateCompatibleDC (0);
1593         hdcDstImage = CreateCompatibleDC (0);
1594         nX1 = i1 * himl1->cx;
1595         nX2 = i2 * himl2->cx;
1596         
1597         /* copy image */
1598         SelectObject (hdcSrcImage, himl1->hbmImage);
1599         SelectObject (hdcDstImage, himlDst->hbmImage);
1600         BitBlt (hdcDstImage, 0, 0, cxDst, cyDst, 
1601                   hdcSrcImage, 0, 0, BLACKNESS);
1602         BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy, 
1603                   hdcSrcImage, nX1, 0, SRCCOPY);
1604
1605         SelectObject (hdcSrcImage, himl2->hbmMask);
1606         BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1607                   hdcSrcImage, nX2, 0, SRCAND);
1608
1609         SelectObject (hdcSrcImage, himl2->hbmImage);
1610         BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1611                   hdcSrcImage, nX2, 0, SRCPAINT);
1612
1613         /* copy mask */
1614         SelectObject (hdcSrcImage, himl1->hbmMask);
1615         SelectObject (hdcDstImage, himlDst->hbmMask);
1616         BitBlt (hdcDstImage, 0, 0, cxDst, cyDst, 
1617                   hdcSrcImage, 0, 0, WHITENESS);
1618         BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy, 
1619                   hdcSrcImage, nX1, 0, SRCCOPY);
1620
1621         SelectObject (hdcSrcImage, himl2->hbmMask);
1622         BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1623                   hdcSrcImage, nX2, 0, SRCAND);
1624
1625         DeleteDC (hdcSrcImage);
1626         DeleteDC (hdcDstImage);
1627     }
1628    
1629     return himlDst;
1630 }
1631
1632
1633 /*************************************************************************
1634  * ImageList_Read [COMCTL32.66]
1635  *
1636  * Reads an image list from a stream.
1637  *
1638  * PARAMS
1639  *     pstm [I] pointer to a stream
1640  *
1641  * RETURNS
1642  *     Success: handle to image list
1643  *     Failure: NULL
1644  *
1645  * NOTES
1646  *     This function can not be implemented yet, because
1647  *     IStream32::Read is not implemented yet.
1648  *
1649  * BUGS
1650  *     empty stub.
1651  */
1652
1653 HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
1654 {
1655     FIXME (imagelist, "empty stub!\n");
1656
1657
1658     return NULL;
1659 }
1660
1661
1662 /*************************************************************************
1663  * ImageList_Remove [COMCTL32.67] Removes an image from an image list
1664  *
1665  * PARAMS
1666  *     himl [I] image list handle
1667  *     i    [I] image index
1668  *
1669  * RETURNS
1670  *     Success: TRUE
1671  *     Failure: FALSE
1672  */
1673
1674 BOOL WINAPI
1675 ImageList_Remove (HIMAGELIST himl, INT i)
1676 {
1677     HBITMAP hbmNewImage, hbmNewMask;
1678     HDC     hdcSrc, hdcDst;
1679     INT     cxNew, nCount;
1680
1681     if ((i < -1) || (i >= himl->cCurImage)) {
1682         ERR (imagelist, "index out of range! %d\n", i);
1683         return FALSE;
1684     }
1685
1686     if (himl->cCurImage == 0) {
1687         ERR (imagelist, "image list is already empty!\n");
1688         return FALSE;
1689     }
1690
1691     if (i == -1) {
1692         /* remove all */
1693         TRACE (imagelist, "remove all!\n");
1694
1695         himl->cMaxImage = himl->cInitial + himl->cGrow;
1696         himl->cCurImage = 0;
1697         for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
1698              himl->nOvlIdx[nCount] = -1;
1699
1700         DeleteObject (himl->hbmImage);
1701         himl->hbmImage =
1702             CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
1703                             1, himl->uBitsPixel, NULL);
1704
1705         if (himl->hbmMask) {
1706             DeleteObject (himl->hbmMask);
1707             himl->hbmMask =
1708                 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
1709                                 1, 1, NULL);
1710         }
1711     }
1712     else {
1713         /* delete one image */
1714         TRACE (imagelist, "Remove single image! %d\n", i);
1715
1716         /* create new bitmap(s) */
1717         cxNew = (himl->cCurImage + himl->cGrow - 1) * himl->cx;
1718
1719         TRACE(imagelist, " - Number of images: %d / %d (Old/New)\n",
1720                  himl->cCurImage, himl->cCurImage - 1);
1721         TRACE(imagelist, " - Max. number of images: %d / %d (Old/New)\n",
1722                  himl->cMaxImage, himl->cCurImage + himl->cGrow - 1);
1723         
1724         hbmNewImage =
1725             CreateBitmap (cxNew, himl->cy, 1, himl->uBitsPixel, NULL);
1726
1727         if (himl->hbmMask)
1728             hbmNewMask = CreateBitmap (cxNew, himl->cy, 1, 1, NULL);
1729         else
1730             hbmNewMask = 0;  /* Just to keep compiler happy! */
1731
1732         hdcSrc = CreateCompatibleDC (0);
1733         hdcDst = CreateCompatibleDC (0);
1734
1735         /* copy all images and masks prior to the "removed" image */
1736         if (i > 0) {
1737             TRACE (imagelist, "Pre image copy: Copy %d images\n", i);
1738        
1739             SelectObject (hdcSrc, himl->hbmImage);
1740             SelectObject (hdcDst, hbmNewImage);
1741             BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
1742                       hdcSrc, 0, 0, SRCCOPY);
1743
1744             if (himl->hbmMask) {
1745                 SelectObject (hdcSrc, himl->hbmMask);
1746                 SelectObject (hdcDst, hbmNewMask);
1747                 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
1748                           hdcSrc, 0, 0, SRCCOPY);
1749             }
1750         }
1751
1752         /* copy all images and masks behind the removed image */
1753         if (i < himl->cCurImage - 1) {
1754             TRACE (imagelist, "Post image copy!\n");
1755             SelectObject (hdcSrc, himl->hbmImage);
1756             SelectObject (hdcDst, hbmNewImage);
1757             BitBlt (hdcDst, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx,
1758                       himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
1759
1760             if (himl->hbmMask) {
1761                 SelectObject (hdcSrc, himl->hbmMask);
1762                 SelectObject (hdcDst, hbmNewMask);
1763                 BitBlt (hdcDst, i * himl->cx, 0,
1764                           (himl->cCurImage - i - 1) * himl->cx,
1765                           himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
1766             }
1767         }
1768
1769         DeleteDC (hdcSrc);
1770         DeleteDC (hdcDst);
1771
1772         /* delete old images and insert new ones */
1773         DeleteObject (himl->hbmImage);
1774         himl->hbmImage = hbmNewImage;
1775         if (himl->hbmMask) {
1776             DeleteObject (himl->hbmMask);
1777             himl->hbmMask = hbmNewMask;
1778         }
1779
1780         himl->cCurImage--;
1781         himl->cMaxImage = himl->cCurImage + himl->cGrow;
1782     }
1783
1784     return TRUE;
1785 }
1786
1787
1788 /*************************************************************************
1789  * ImageList_Replace [COMCTL32.68] 
1790  *
1791  * Replaces an image in an image list with a new image.
1792  *
1793  * PARAMS
1794  *     himl     [I] handle to image list
1795  *     i        [I] image index
1796  *     hbmImage [I] handle to image bitmap
1797  *     hbmMask  [I] handle to mask bitmap. Can be NULL.
1798  *
1799  * RETURNS
1800  *     Success: TRUE
1801  *     Failure: FALSE
1802  */
1803
1804 BOOL WINAPI
1805 ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage,
1806                    HBITMAP hbmMask)
1807 {
1808     HDC hdcImageList, hdcImage;
1809     BITMAP bmp;
1810
1811     if (himl == NULL) {
1812         ERR (imagelist, "Invalid image list handle!\n");
1813         return FALSE;
1814     }
1815     
1816     if ((i >= himl->cCurImage) || (i < 0)) {
1817         ERR (imagelist, "Invalid image index!\n");
1818         return FALSE;
1819     }
1820
1821     hdcImageList = CreateCompatibleDC (0);
1822     hdcImage = CreateCompatibleDC (0);
1823     GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
1824
1825     /* Replace Image */
1826     SelectObject (hdcImageList, himl->hbmImage);
1827     SelectObject (hdcImage, hbmImage);
1828
1829     StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
1830                   hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
1831
1832     if (himl->hbmMask)
1833     {
1834         /* Replace Mask */
1835         SelectObject (hdcImageList, himl->hbmMask);
1836         SelectObject (hdcImage, hbmMask);
1837
1838         StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
1839                       hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
1840     }
1841
1842     DeleteDC (hdcImage);
1843     DeleteDC (hdcImageList);
1844
1845     return TRUE;
1846 }
1847
1848
1849 /*************************************************************************
1850  * ImageList_ReplaceIcon [COMCTL32.69]
1851  *
1852  * Replaces an image in an image list using an icon.
1853  *
1854  * PARAMS
1855  *     himl  [I] handle to image list
1856  *     i     [I] image index
1857  *     hIcon [I] handle to icon
1858  *
1859  * RETURNS
1860  *     Success: index of the replaced image
1861  *     Failure: -1
1862  */
1863
1864 INT WINAPI
1865 ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon)
1866 {
1867     HDC     hdcImageList, hdcImage;
1868     INT     nIndex;
1869     HBITMAP hbmOldSrc, hbmOldDst;
1870     ICONINFO  ii;
1871     BITMAP  bmp;
1872
1873     TRACE (imagelist, "(0x%lx 0x%x 0x%x)\n", (DWORD)himl, i, hIcon);
1874
1875     if (himl == NULL)
1876         return -1;
1877     if ((i >= himl->cCurImage) || (i < -1))
1878         return -1;
1879
1880     GetIconInfo (hIcon, &ii);
1881     if (ii.hbmMask == 0)
1882         ERR (imagelist, "no mask!\n");
1883     if (ii.hbmColor == 0)
1884         ERR (imagelist, "no color!\n");
1885     GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
1886
1887     if (i == -1) {
1888         if (himl->cCurImage + 1 >= himl->cMaxImage)
1889             IMAGELIST_InternalExpandBitmaps (himl, 1);
1890
1891         nIndex = himl->cCurImage;
1892         himl->cCurImage++;
1893     }
1894     else
1895         nIndex = i;
1896
1897     hdcImageList = CreateCompatibleDC (0);
1898     TRACE (imagelist, "hdcImageList=0x%x!\n", hdcImageList);
1899     if (hdcImageList == 0)
1900         ERR (imagelist, "invalid hdcImageList!\n");
1901
1902     hdcImage = CreateCompatibleDC (0);
1903     TRACE (imagelist, "hdcImage=0x%x!\n", hdcImage);
1904     if (hdcImage == 0)
1905         ERR (imagelist, "invalid hdcImage!\n");
1906
1907     hbmOldDst = SelectObject (hdcImageList, himl->hbmImage);
1908     SetTextColor( hdcImageList, RGB(0,0,0));
1909     SetBkColor( hdcImageList, RGB(255,255,255));
1910     hbmOldSrc = SelectObject (hdcImage, ii.hbmColor);
1911     StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
1912                   hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
1913
1914     if (himl->hbmMask) {
1915         SelectObject (hdcImageList, himl->hbmMask);
1916         SelectObject (hdcImage, ii.hbmMask);
1917         StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
1918                       hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
1919     }
1920
1921     SelectObject (hdcImage, hbmOldSrc);
1922     SelectObject (hdcImageList, hbmOldDst);
1923
1924     if (hdcImageList)
1925         DeleteDC (hdcImageList);
1926     if (hdcImage)
1927         DeleteDC (hdcImage);
1928     if (ii.hbmColor)
1929         DeleteObject (ii.hbmColor);
1930     if (ii.hbmMask)
1931         DeleteObject (ii.hbmMask);
1932
1933     return nIndex;
1934 }
1935
1936
1937 /*************************************************************************
1938  * ImageList_SetBkColor [COMCTL32.70] 
1939  *
1940  * Sets the background color of an image list.
1941  *
1942  * PARAMS
1943  *     himl  [I] handle to image list
1944  *     clrBk [I] background color
1945  *
1946  * RETURNS
1947  *     Success: previous background color
1948  *     Failure: CLR_NONE
1949  */
1950
1951 COLORREF WINAPI
1952 ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
1953 {
1954     COLORREF clrOldBk;
1955
1956     if (himl == NULL)
1957         return CLR_NONE;
1958
1959     clrOldBk = himl->clrBk;
1960     himl->clrBk = clrBk;
1961     return clrOldBk;
1962 }
1963
1964
1965 /*************************************************************************
1966  * ImageList_SetDragCursorImage [COMCTL32.75]
1967  *
1968  * Combines the specified image with the current drag image
1969  *
1970  * PARAMS
1971  *     himlDrag  [I] handle to drag image list
1972  *     iDrag     [I] drag image index
1973  *     dxHotspot [I] X position of the hot spot
1974  *     dyHotspot [I] Y position of the hot spot
1975  *
1976  * RETURNS
1977  *     Success: TRUE
1978  *     Failure: FALSE
1979  *
1980  * BUGS
1981  *     semi-stub.
1982  */
1983
1984 BOOL WINAPI
1985 ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag,
1986                               INT dxHotspot, INT dyHotspot)
1987 {
1988     HIMAGELIST himlTemp;
1989
1990     FIXME (imagelist, "semi-stub!\n");
1991
1992     if (himlInternalDrag == NULL)
1993         return FALSE;
1994
1995     TRACE (imagelist, " dxH=%d dyH=%d nX=%d nY=%d\n",
1996            dxHotspot, dyHotspot, nInternalDragHotspotX, nInternalDragHotspotY);
1997
1998     himlTemp = ImageList_Merge (himlInternalDrag, 0, himlDrag, iDrag,
1999                                 dxHotspot, dyHotspot);
2000
2001     ImageList_Destroy (himlInternalDrag);
2002     himlInternalDrag = himlTemp;
2003
2004     nInternalDragHotspotX = dxHotspot;
2005     nInternalDragHotspotY = dyHotspot;
2006
2007     return FALSE;
2008 }
2009
2010
2011 /*************************************************************************
2012  * ImageList_SetFilter [COMCTL32.76] 
2013  *
2014  * Sets a filter (or does something completely different)!!???
2015  *
2016  * PARAMS
2017  *     himl     [I] handle to image list
2018  *     i        [I] ???
2019  *     dwFilter [I] ???
2020  *
2021  * RETURNS
2022  *     Success: TRUE ???
2023  *     Failure: FALSE ???
2024  *
2025  * BUGS
2026  *     This is an UNDOCUMENTED function!!!!
2027  *     empty stub.
2028  */
2029
2030 BOOL WINAPI
2031 ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter)
2032 {
2033     FIXME (imagelist, "(%p 0x%x 0x%lx):empty stub!\n",
2034            himl, i, dwFilter);
2035
2036     return FALSE;
2037 }
2038
2039
2040 /*************************************************************************
2041  * ImageList_SetIconSize [COMCTL32.77]
2042  *
2043  * Sets the image size of the bitmap and deletes all images.
2044  *
2045  * PARAMS
2046  *     himl [I] handle to image list
2047  *     cx   [I] image width
2048  *     cy   [I] image height
2049  *
2050  * RETURNS
2051  *     Success: TRUE
2052  *     Failure: FALSE
2053  */
2054
2055 BOOL WINAPI
2056 ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy)
2057 {
2058     INT nCount;
2059
2060     if (!himl)
2061         return FALSE;
2062
2063     /* remove all images*/
2064     himl->cMaxImage = himl->cInitial + himl->cGrow;
2065     himl->cCurImage = 0;
2066     himl->cx        = cx;
2067     himl->cy        = cy;
2068
2069     /* initialize overlay mask indices */
2070     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2071         himl->nOvlIdx[nCount] = -1;
2072
2073     DeleteObject (himl->hbmImage);
2074     himl->hbmImage =
2075         CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2076                         1, himl->uBitsPixel, NULL);
2077
2078     if (himl->hbmMask) {
2079         DeleteObject (himl->hbmMask);
2080         himl->hbmMask =
2081             CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2082                             1, 1, NULL);
2083     }
2084
2085     return TRUE;
2086 }
2087
2088
2089 /*************************************************************************
2090  * ImageList_SetImageCount [COMCTL32.78]
2091  *
2092  * Resizes an image list to the specified number of images.
2093  *
2094  * PARAMS
2095  *     himl        [I] handle to image list
2096  *     iImageCount [I] number of images in the image list
2097  *
2098  * RETURNS
2099  *     Success: TRUE
2100  *     Failure: FALSE
2101  */
2102
2103 BOOL WINAPI
2104 ImageList_SetImageCount (HIMAGELIST himl, INT iImageCount)
2105 {
2106     HDC     hdcImageList, hdcBitmap;
2107     HBITMAP hbmNewBitmap;
2108     INT     nNewCount, nCopyCount;
2109
2110     if (!himl)
2111         return FALSE;
2112     if (himl->cCurImage >= iImageCount)
2113         return FALSE;
2114     if (himl->cMaxImage > iImageCount)
2115         return TRUE;
2116
2117     nNewCount = iImageCount + himl->cGrow;
2118     nCopyCount = _MIN(himl->cCurImage, iImageCount);
2119
2120     hdcImageList = CreateCompatibleDC (0);
2121     hdcBitmap = CreateCompatibleDC (0);
2122
2123     hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2124                                    1, himl->uBitsPixel, NULL);
2125     if (hbmNewBitmap != 0)
2126     {
2127         SelectObject (hdcImageList, himl->hbmImage);
2128         SelectObject (hdcBitmap, hbmNewBitmap);
2129
2130         /* copy images */
2131         BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2132                   hdcImageList, 0, 0, SRCCOPY);
2133
2134         /* delete 'empty' image space */
2135         SetBkColor (hdcBitmap, RGB(255, 255, 255));
2136         SetTextColor (hdcBitmap, RGB(0, 0, 0));
2137         PatBlt (hdcBitmap,  nCopyCount * himl->cx, 0, 
2138                   (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2139
2140         DeleteObject (himl->hbmImage);
2141         himl->hbmImage = hbmNewBitmap;
2142     }
2143     else
2144         ERR (imagelist, "Could not create new image bitmap !\n");
2145
2146     if (himl->hbmMask)
2147     {
2148         hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2149                                        1, 1, NULL);
2150         if (hbmNewBitmap != 0)
2151         {
2152             SelectObject (hdcImageList, himl->hbmMask);
2153             SelectObject (hdcBitmap, hbmNewBitmap);
2154
2155             /* copy images */
2156             BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2157                       hdcImageList, 0, 0, SRCCOPY);
2158
2159             /* delete 'empty' image space */
2160             SetBkColor (hdcBitmap, RGB(255, 255, 255));
2161             SetTextColor (hdcBitmap, RGB(0, 0, 0));
2162             PatBlt (hdcBitmap,  nCopyCount * himl->cx, 0, 
2163                       (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2164
2165             DeleteObject (himl->hbmMask);
2166             himl->hbmMask = hbmNewBitmap;
2167         }
2168         else
2169             ERR (imagelist, "Could not create new mask bitmap!\n");
2170     }
2171
2172     DeleteDC (hdcImageList);
2173     DeleteDC (hdcBitmap);
2174
2175     /* Update max image count and current image count */
2176     himl->cMaxImage = nNewCount;
2177     if (himl->cCurImage > nCopyCount)
2178         himl->cCurImage = nCopyCount;
2179
2180     return TRUE;
2181 }
2182
2183
2184 /*************************************************************************
2185  * ImageList_SetOverlayImage [COMCTL32.79]
2186  *
2187  * Assigns an overlay mask index to an existing image in an image list.
2188  *
2189  * PARAMS
2190  *     himl     [I] handle to image list
2191  *     iImage   [I] image index
2192  *     iOverlay [I] overlay mask index
2193  *
2194  * RETURNS
2195  *     Success: TRUE
2196  *     Failure: FALSE
2197  */
2198
2199 BOOL WINAPI
2200 ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay)
2201 {
2202     if (!himl)
2203         return FALSE;
2204     if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
2205         return FALSE;
2206     if ((iImage < 0) || (iImage > himl->cCurImage))
2207         return FALSE;
2208     
2209     himl->nOvlIdx[iOverlay - 1] = iImage;
2210     return TRUE;
2211 }
2212
2213
2214 /*************************************************************************
2215  * ImageList_Write [COMCTL32.80]
2216  *
2217  * Writes an image list to a stream.
2218  *
2219  * PARAMS
2220  *     himl [I] handle to image list
2221  *     pstm [O] Pointer to a stream.
2222  *
2223  * RETURNS
2224  *     Success: TRUE
2225  *     Failure: FALSE
2226  *
2227  * NOTES
2228  *     This function can not be implemented yet, because
2229  *     IStream32::Write is not implemented.
2230  *
2231  * BUGS
2232  *     empty stub.
2233  */
2234
2235 BOOL WINAPI
2236 ImageList_Write (HIMAGELIST himl, LPSTREAM pstm)
2237 {
2238     if (!himl)
2239         return FALSE;
2240
2241     FIXME (imagelist, "empty stub!\n");
2242
2243     return FALSE;
2244 }
2245