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