ReactOS  0.4.13-dev-257-gfabbd7c
imagelist.c
Go to the documentation of this file.
1 /*
2  * ImageList implementation
3  *
4  * Copyright 1998 Eric Kohl
5  * Copyright 2000 Jason Mawdsley
6  * Copyright 2001, 2004 Michael Stefaniuc
7  * Copyright 2001 Charles Loep for CodeWeavers
8  * Copyright 2002 Dimitrie O. Paun
9  * Copyright 2009 Owen Rudge for CodeWeavers
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24  *
25  * TODO:
26  * - Add support for ILD_PRESERVEALPHA, ILD_SCALE, ILD_DPISCALE
27  * - Add support for ILS_GLOW, ILS_SHADOW
28  * - Thread-safe locking
29  */
30 
31 #include <stdarg.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #define COBJMACROS
36 
37 #include "winerror.h"
38 #include "windef.h"
39 #include "winbase.h"
40 #include "objbase.h"
41 #include "wingdi.h"
42 #include "winuser.h"
43 #include "commctrl.h"
44 #include "comctl32.h"
45 #include "commoncontrols.h"
46 #include "wine/debug.h"
47 #include "wine/exception.h"
48 #include "wine/heap.h"
49 
51 
52 #define MAX_OVERLAYIMAGE 15
53 
54 struct _IMAGELIST
55 {
56  IImageList2 IImageList2_iface; /* 00: IImageList vtable */
57  INT cCurImage; /* 04: ImageCount */
58  INT cMaxImage; /* 08: maximages */
59  INT cGrow; /* 0C: cGrow */
60  INT cx; /* 10: cx */
61  INT cy; /* 14: cy */
63  UINT flags; /* 1C: flags */
64  COLORREF clrFg; /* 20: foreground color */
65  COLORREF clrBk; /* 24: background color */
66 
67 
68  HBITMAP hbmImage; /* 28: images Bitmap */
69  HBITMAP hbmMask; /* 2C: masks Bitmap */
70  HDC hdcImage; /* 30: images MemDC */
71  HDC hdcMask; /* 34: masks MemDC */
72  INT nOvlIdx[MAX_OVERLAYIMAGE]; /* 38: overlay images index */
73 
74  /* not yet found out */
75  HBRUSH hbrBlend25;
76  HBRUSH hbrBlend50;
79  char *has_alpha;
81 
82  LONG ref; /* reference count */
83 };
84 
85 #define IMAGELIST_MAGIC 0x53414D58
86 
87 /* Header used by ImageList_Read() and ImageList_Write() */
88 #include "pshpack2.h"
89 typedef struct _ILHEAD
90 {
101 } ILHEAD;
102 #include "poppack.h"
103 
104 /* internal image list data used for Drag & Drop operations */
105 typedef struct
106 {
110  /* position of the drag image relative to the window */
113  /* offset of the hotspot relative to the origin of the image */
116  /* is the drag image visible */
118  /* saved background */
120 } INTERNALDRAG;
121 
122 static INTERNALDRAG InternalDrag = { 0, 0, 0, 0, 0, 0, 0, FALSE, 0 };
123 
125 {
126  return CONTAINING_RECORD(iface, struct _IMAGELIST, IImageList2_iface);
127 }
128 
130 static HRESULT ImageListImpl_CreateInstance(const IUnknown *pUnkOuter, REFIID iid, void** ppv);
131 static BOOL is_valid(HIMAGELIST himl);
132 
133 /*
134  * An imagelist with N images is tiled like this:
135  *
136  * N/4 ->
137  *
138  * 4 048C..
139  * 159D..
140  * | 26AE.N
141  * V 37BF.
142  */
143 
144 #define TILE_COUNT 4
145 
146 static inline UINT imagelist_height( UINT count )
147 {
148  return ((count + TILE_COUNT - 1)/TILE_COUNT);
149 }
150 
152 {
153  pt->x = (index%TILE_COUNT) * himl->cx;
154  pt->y = (index/TILE_COUNT) * himl->cy;
155 }
156 
158 {
159  sz->cx = himl->cx * TILE_COUNT;
160  sz->cy = imagelist_height( count ) * himl->cy;
161 }
162 
163 static inline int get_dib_stride( int width, int bpp )
164 {
165  return ((width * bpp + 31) >> 3) & ~3;
166 }
167 
168 static inline int get_dib_image_size( const BITMAPINFO *info )
169 {
170  return get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount )
171  * abs( info->bmiHeader.biHeight );
172 }
173 
174 /*
175  * imagelist_copy_images()
176  *
177  * Copies a block of count images from offset src in the list to offset dest.
178  * Images are copied a row at at time. Assumes hdcSrc and hdcDest are different.
179  */
180 static inline void imagelist_copy_images( HIMAGELIST himl, HDC hdcSrc, HDC hdcDest,
181  UINT src, UINT count, UINT dest )
182 {
183  POINT ptSrc, ptDest;
184  SIZE sz;
185  UINT i;
186 
187  for ( i=0; i<TILE_COUNT; i++ )
188  {
189  imagelist_point_from_index( himl, src+i, &ptSrc );
190  imagelist_point_from_index( himl, dest+i, &ptDest );
191  sz.cx = himl->cx;
192  sz.cy = himl->cy * imagelist_height( count - i );
193 
194  BitBlt( hdcDest, ptDest.x, ptDest.y, sz.cx, sz.cy,
195  hdcSrc, ptSrc.x, ptSrc.y, SRCCOPY );
196  }
197 }
198 
199 static void add_dib_bits( HIMAGELIST himl, int pos, int count, int width, int height,
200  BITMAPINFO *info, BITMAPINFO *mask_info, DWORD *bits, BYTE *mask_bits )
201 {
202  int i, j, n;
203  POINT pt;
204  int stride = info->bmiHeader.biWidth;
205  int mask_stride = (info->bmiHeader.biWidth + 31) / 32 * 4;
206 
207  for (n = 0; n < count; n++)
208  {
209  BOOL has_alpha = FALSE;
210 
212 
213  /* check if bitmap has an alpha channel */
214  for (i = 0; i < height && !has_alpha; i++)
215  for (j = n * width; j < (n + 1) * width; j++)
216  if ((has_alpha = ((bits[i * stride + j] & 0xff000000) != 0))) break;
217 
218  if (!has_alpha) /* generate alpha channel from the mask */
219  {
220  for (i = 0; i < height; i++)
221  for (j = n * width; j < (n + 1) * width; j++)
222  if (!mask_info || !((mask_bits[i * mask_stride + j / 8] << (j % 8)) & 0x80))
223  bits[i * stride + j] |= 0xff000000;
224  else
225  bits[i * stride + j] = 0;
226  }
227  else
228  {
229  himl->has_alpha[pos + n] = 1;
230 
231  if (mask_info && himl->hbmMask) /* generate the mask from the alpha channel */
232  {
233  for (i = 0; i < height; i++)
234  for (j = n * width; j < (n + 1) * width; j++)
235  if ((bits[i * stride + j] >> 24) > 25) /* more than 10% alpha */
236  mask_bits[i * mask_stride + j / 8] &= ~(0x80 >> (j % 8));
237  else
238  mask_bits[i * mask_stride + j / 8] |= 0x80 >> (j % 8);
239  }
240  }
241  StretchDIBits( himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy,
243  if (mask_info)
244  StretchDIBits( himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy,
245  n * width, 0, width, height, mask_bits, mask_info, DIB_RGB_COLORS, SRCCOPY );
246  }
247 }
248 
249 /* add images with an alpha channel when the image list is 32 bpp */
251  int width, int height, HBITMAP hbmImage, HBITMAP hbmMask )
252 {
253  BOOL ret = FALSE;
254  BITMAP bm;
255  BITMAPINFO *info, *mask_info = NULL;
256  DWORD *bits = NULL;
257  BYTE *mask_bits = NULL;
258  DWORD mask_width;
259 
260  if (!GetObjectW( hbmImage, sizeof(bm), &bm )) return FALSE;
261 
262  /* if either the imagelist or the source bitmap don't have an alpha channel, bail out now */
263  if (!himl->has_alpha) return FALSE;
264  if (bm.bmBitsPixel != 32) return FALSE;
265 
266  SelectObject( hdc, hbmImage );
267  mask_width = (bm.bmWidth + 31) / 32 * 4;
268 
269  if (!(info = heap_alloc( FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto done;
270  info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
271  info->bmiHeader.biWidth = bm.bmWidth;
272  info->bmiHeader.biHeight = -height;
273  info->bmiHeader.biPlanes = 1;
274  info->bmiHeader.biBitCount = 32;
275  info->bmiHeader.biCompression = BI_RGB;
276  info->bmiHeader.biSizeImage = bm.bmWidth * height * 4;
277  info->bmiHeader.biXPelsPerMeter = 0;
278  info->bmiHeader.biYPelsPerMeter = 0;
279  info->bmiHeader.biClrUsed = 0;
280  info->bmiHeader.biClrImportant = 0;
281  if (!(bits = heap_alloc( info->bmiHeader.biSizeImage ))) goto done;
282  if (!GetDIBits( hdc, hbmImage, 0, height, bits, info, DIB_RGB_COLORS )) goto done;
283 
284  if (hbmMask)
285  {
286  if (!(mask_info = heap_alloc( FIELD_OFFSET( BITMAPINFO, bmiColors[2] ))))
287  goto done;
288  mask_info->bmiHeader = info->bmiHeader;
289  mask_info->bmiHeader.biBitCount = 1;
290  mask_info->bmiHeader.biSizeImage = mask_width * height;
291  if (!(mask_bits = heap_alloc_zero( mask_info->bmiHeader.biSizeImage )))
292  goto done;
293  if (!GetDIBits( hdc, hbmMask, 0, height, mask_bits, mask_info, DIB_RGB_COLORS )) goto done;
294  }
295 
296  add_dib_bits( himl, pos, count, width, height, info, mask_info, bits, mask_bits );
297  ret = TRUE;
298 
299 done:
300  heap_free( info );
301  heap_free( mask_info );
302  heap_free( bits );
303  heap_free( mask_bits );
304  return ret;
305 }
306 
307 UINT WINAPI
308 ImageList_SetColorTable(HIMAGELIST himl, UINT uStartIndex, UINT cEntries, const RGBQUAD *prgb);
309 
310 /*************************************************************************
311  * IMAGELIST_InternalExpandBitmaps [Internal]
312  *
313  * Expands the bitmaps of an image list by the given number of images.
314  *
315  * PARAMS
316  * himl [I] handle to image list
317  * nImageCount [I] number of images to add
318  *
319  * RETURNS
320  * nothing
321  *
322  * NOTES
323  * This function CANNOT be used to reduce the number of images.
324  */
325 static void
327 {
328  HDC hdcBitmap;
329  HBITMAP hbmNewBitmap, hbmNull;
330  INT nNewCount;
331  SIZE sz;
332 
333  TRACE("%p has allocated %d, max %d, grow %d images\n", himl, himl->cCurImage, himl->cMaxImage, himl->cGrow);
334 
335  if (himl->cCurImage + nImageCount < himl->cMaxImage)
336  return;
337 
338  nNewCount = himl->cMaxImage + max(nImageCount, himl->cGrow) + 1;
339 
340  imagelist_get_bitmap_size(himl, nNewCount, &sz);
341 
342  TRACE("Create expanded bitmaps : himl=%p x=%d y=%d count=%d\n", himl, sz.cx, sz.cy, nNewCount);
344 
345  hbmNewBitmap = ImageList_CreateImage(hdcBitmap, himl, nNewCount);
346 
347  if (hbmNewBitmap == 0)
348  ERR("creating new image bitmap (x=%d y=%d)!\n", sz.cx, sz.cy);
349 
350  if (himl->cCurImage)
351  {
352  hbmNull = SelectObject (hdcBitmap, hbmNewBitmap);
353  BitBlt (hdcBitmap, 0, 0, sz.cx, sz.cy,
354  himl->hdcImage, 0, 0, SRCCOPY);
355  SelectObject (hdcBitmap, hbmNull);
356  }
357  SelectObject (himl->hdcImage, hbmNewBitmap);
359  himl->hbmImage = hbmNewBitmap;
360 
361  if (himl->flags & ILC_MASK)
362  {
363  hbmNewBitmap = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
364 
365  if (hbmNewBitmap == 0)
366  ERR("creating new mask bitmap!\n");
367 
368  if(himl->cCurImage)
369  {
370  hbmNull = SelectObject (hdcBitmap, hbmNewBitmap);
371  BitBlt (hdcBitmap, 0, 0, sz.cx, sz.cy,
372  himl->hdcMask, 0, 0, SRCCOPY);
373  SelectObject (hdcBitmap, hbmNull);
374  }
375  SelectObject (himl->hdcMask, hbmNewBitmap);
377  himl->hbmMask = hbmNewBitmap;
378  }
379 
380  if (himl->has_alpha)
381  {
382  char *new_alpha = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, himl->has_alpha, nNewCount );
383  if (new_alpha) himl->has_alpha = new_alpha;
384  else
385  {
387  himl->has_alpha = NULL;
388  }
389  }
390 
391  himl->cMaxImage = nNewCount;
392 
394 }
395 
396 
397 /*************************************************************************
398  * ImageList_Add [COMCTL32.@]
399  *
400  * Add an image or images to an image list.
401  *
402  * PARAMS
403  * himl [I] handle to image list
404  * hbmImage [I] handle to image bitmap
405  * hbmMask [I] handle to mask bitmap
406  *
407  * RETURNS
408  * Success: Index of the first new image.
409  * Failure: -1
410  */
411 
412 INT WINAPI
414 {
415  HDC hdcBitmap, hdcTemp = 0;
416  INT nFirstIndex, nImageCount, i;
417  BITMAP bmp;
418  POINT pt;
419 
420  TRACE("himl=%p hbmimage=%p hbmmask=%p\n", himl, hbmImage, hbmMask);
421  if (!is_valid(himl))
422  return -1;
423 
424  if (!GetObjectW(hbmImage, sizeof(BITMAP), &bmp))
425  return -1;
426 
427  TRACE("himl %p, cCurImage %d, cMaxImage %d, cGrow %d, cx %d, cy %d\n",
429 
430  nImageCount = bmp.bmWidth / himl->cx;
431 
432  TRACE("%p has %d images (%d x %d) bpp %d\n", hbmImage, nImageCount, bmp.bmWidth, bmp.bmHeight,
433  bmp.bmBitsPixel);
434 
436 
438 
439  SelectObject(hdcBitmap, hbmImage);
440 
441  if (add_with_alpha( himl, hdcBitmap, himl->cCurImage, nImageCount,
442  himl->cx, min( himl->cy, bmp.bmHeight), hbmImage, hbmMask ))
443  goto done;
444 
445  if (himl->hbmMask)
446  {
447  hdcTemp = CreateCompatibleDC(0);
448  SelectObject(hdcTemp, hbmMask);
449  }
450 
451  if (himl->uBitsPixel <= 8 && bmp.bmBitsPixel <= 8 &&
452  !himl->color_table_set && himl->cCurImage == 0)
453  {
454  RGBQUAD colors[256];
455  UINT num = GetDIBColorTable( hdcBitmap, 0, 1 << bmp.bmBitsPixel, colors );
456  if (num) ImageList_SetColorTable( himl, 0, num, colors );
457  }
458 
459  for (i=0; i<nImageCount; i++)
460  {
462 
463  /* Copy result to the imagelist
464  */
465  BitBlt( himl->hdcImage, pt.x, pt.y, himl->cx, bmp.bmHeight,
466  hdcBitmap, i*himl->cx, 0, SRCCOPY );
467 
468  if (!himl->hbmMask)
469  continue;
470 
471  BitBlt( himl->hdcMask, pt.x, pt.y, himl->cx, bmp.bmHeight,
472  hdcTemp, i*himl->cx, 0, SRCCOPY );
473 
474  /* Remove the background from the image
475  */
476  BitBlt( himl->hdcImage, pt.x, pt.y, himl->cx, bmp.bmHeight,
477  himl->hdcMask, pt.x, pt.y, 0x220326 ); /* NOTSRCAND */
478  }
479  if (hdcTemp) DeleteDC(hdcTemp);
480 
481 done:
483 
484  nFirstIndex = himl->cCurImage;
485  himl->cCurImage += nImageCount;
486 
487  return nFirstIndex;
488 }
489 
490 
491 /*************************************************************************
492  * ImageList_AddIcon [COMCTL32.@]
493  *
494  * Adds an icon to an image list.
495  *
496  * PARAMS
497  * himl [I] handle to image list
498  * hIcon [I] handle to icon
499  *
500  * RETURNS
501  * Success: index of the new image
502  * Failure: -1
503  */
504 #undef ImageList_AddIcon
506 {
507  return ImageList_ReplaceIcon (himl, -1, hIcon);
508 }
509 
510 
511 /*************************************************************************
512  * ImageList_AddMasked [COMCTL32.@]
513  *
514  * Adds an image or images to an image list and creates a mask from the
515  * specified bitmap using the mask color.
516  *
517  * PARAMS
518  * himl [I] handle to image list.
519  * hBitmap [I] handle to bitmap
520  * clrMask [I] mask color.
521  *
522  * RETURNS
523  * Success: Index of the first new image.
524  * Failure: -1
525  */
526 
527 INT WINAPI
529 {
530  HDC hdcMask, hdcBitmap;
531  INT ret;
532  BITMAP bmp;
533  HBITMAP hMaskBitmap;
534  COLORREF bkColor;
535 
536  TRACE("himl=%p hbitmap=%p clrmask=%x\n", himl, hBitmap, clrMask);
537  if (!is_valid(himl))
538  return -1;
539 
540  if (!GetObjectW(hBitmap, sizeof(BITMAP), &bmp))
541  return -1;
542 
545 
546  /* Create a temp Mask so we can remove the background of the Image */
547  hdcMask = CreateCompatibleDC(0);
548  hMaskBitmap = CreateBitmap(bmp.bmWidth, bmp.bmHeight, 1, 1, NULL);
549  SelectObject(hdcMask, hMaskBitmap);
550 
551  /* create monochrome image to the mask bitmap */
552  bkColor = (clrMask != CLR_DEFAULT) ? clrMask : GetPixel (hdcBitmap, 0, 0);
553  SetBkColor (hdcBitmap, bkColor);
554  BitBlt (hdcMask, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcBitmap, 0, 0, SRCCOPY);
555 
556  /*
557  * Remove the background from the image
558  *
559  * WINDOWS BUG ALERT!!!!!!
560  * The statement below should not be done in common practice
561  * but this is how ImageList_AddMasked works in Windows.
562  * It overwrites the original bitmap passed, this was discovered
563  * by using the same bitmap to iterate the different styles
564  * on windows where it failed (BUT ImageList_Add is OK)
565  * This is here in case some apps rely on this bug
566  *
567  * Blt mode 0x220326 is NOTSRCAND
568  */
569  if (bmp.bmBitsPixel > 8) /* NOTSRCAND can't work with palettes */
570  {
571  SetBkColor(hdcBitmap, RGB(255,255,255));
572  BitBlt(hdcBitmap, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcMask, 0, 0, 0x220326);
573  }
574 
576  DeleteDC(hdcMask);
577 
578  ret = ImageList_Add( himl, hBitmap, hMaskBitmap );
579 
580  DeleteObject(hMaskBitmap);
581  return ret;
582 }
583 
584 
585 /*************************************************************************
586  * ImageList_BeginDrag [COMCTL32.@]
587  *
588  * Creates a temporary image list that contains one image. It will be used
589  * as a drag image.
590  *
591  * PARAMS
592  * himlTrack [I] handle to the source image list
593  * iTrack [I] index of the drag image in the source image list
594  * dxHotspot [I] X position of the hot spot of the drag image
595  * dyHotspot [I] Y position of the hot spot of the drag image
596  *
597  * RETURNS
598  * Success: TRUE
599  * Failure: FALSE
600  */
601 
602 BOOL WINAPI
603 ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
604  INT dxHotspot, INT dyHotspot)
605 {
606  INT cx, cy;
607  POINT src, dst;
608 
609  TRACE("(himlTrack=%p iTrack=%d dx=%d dy=%d)\n", himlTrack, iTrack,
610  dxHotspot, dyHotspot);
611 
612  if (!is_valid(himlTrack))
613  return FALSE;
614 
615  if (iTrack >= himlTrack->cCurImage)
616  return FALSE;
617 
618  if (InternalDrag.himl)
619  return FALSE;
620 
621  cx = himlTrack->cx;
622  cy = himlTrack->cy;
623 
625  if (InternalDrag.himl == NULL) {
626  WARN("Error creating drag image list!\n");
627  return FALSE;
628  }
629 
630  InternalDrag.dxHotspot = dxHotspot;
631  InternalDrag.dyHotspot = dyHotspot;
632 
633  /* copy image */
635  imagelist_point_from_index(himlTrack, iTrack, &src);
636  BitBlt(InternalDrag.himl->hdcImage, dst.x, dst.y, cx, cy, himlTrack->hdcImage, src.x, src.y,
637  SRCCOPY);
638  BitBlt(InternalDrag.himl->hdcMask, dst.x, dst.y, cx, cy, himlTrack->hdcMask, src.x, src.y,
639  SRCCOPY);
640 
642 
643  return TRUE;
644 }
645 
646 
647 /*************************************************************************
648  * ImageList_Copy [COMCTL32.@]
649  *
650  * Copies an image of the source image list to an image of the
651  * destination image list. Images can be copied or swapped.
652  *
653  * PARAMS
654  * himlDst [I] handle to the destination image list
655  * iDst [I] destination image index.
656  * himlSrc [I] handle to the source image list
657  * iSrc [I] source image index
658  * uFlags [I] flags for the copy operation
659  *
660  * RETURNS
661  * Success: TRUE
662  * Failure: FALSE
663  *
664  * NOTES
665  * Copying from one image list to another is possible. The original
666  * implementation just copies or swaps within one image list.
667  * Could this feature become a bug??? ;-)
668  */
669 
670 BOOL WINAPI
671 ImageList_Copy (HIMAGELIST himlDst, INT iDst, HIMAGELIST himlSrc,
672  INT iSrc, UINT uFlags)
673 {
674  POINT ptSrc, ptDst;
675 
676  TRACE("himlDst=%p iDst=%d himlSrc=%p iSrc=%d\n", himlDst, iDst, himlSrc, iSrc);
677 
678  if (!is_valid(himlSrc) || !is_valid(himlDst))
679  return FALSE;
680  if ((iDst < 0) || (iDst >= himlDst->cCurImage))
681  return FALSE;
682  if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage))
683  return FALSE;
684 
685  imagelist_point_from_index( himlDst, iDst, &ptDst );
686  imagelist_point_from_index( himlSrc, iSrc, &ptSrc );
687 
688  if (uFlags & ILCF_SWAP) {
689  /* swap */
690  HDC hdcBmp;
691  HBITMAP hbmTempImage, hbmTempMask;
692 
693  hdcBmp = CreateCompatibleDC (0);
694 
695  /* create temporary bitmaps */
696  hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
697  himlSrc->uBitsPixel, NULL);
698  hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
699  1, NULL);
700 
701  /* copy (and stretch) destination to temporary bitmaps.(save) */
702  /* image */
703  SelectObject (hdcBmp, hbmTempImage);
704  StretchBlt (hdcBmp, 0, 0, himlSrc->cx, himlSrc->cy,
705  himlDst->hdcImage, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
706  SRCCOPY);
707  /* mask */
708  SelectObject (hdcBmp, hbmTempMask);
709  StretchBlt (hdcBmp, 0, 0, himlSrc->cx, himlSrc->cy,
710  himlDst->hdcMask, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
711  SRCCOPY);
712 
713  /* copy (and stretch) source to destination */
714  /* image */
715  StretchBlt (himlDst->hdcImage, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
716  himlSrc->hdcImage, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
717  SRCCOPY);
718  /* mask */
719  StretchBlt (himlDst->hdcMask, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
720  himlSrc->hdcMask, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
721  SRCCOPY);
722 
723  /* copy (without stretching) temporary bitmaps to source (restore) */
724  /* mask */
725  BitBlt (himlSrc->hdcMask, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
726  hdcBmp, 0, 0, SRCCOPY);
727 
728  /* image */
729  BitBlt (himlSrc->hdcImage, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
730  hdcBmp, 0, 0, SRCCOPY);
731  /* delete temporary bitmaps */
732  DeleteObject (hbmTempMask);
733  DeleteObject (hbmTempImage);
734  DeleteDC(hdcBmp);
735  }
736  else {
737  /* copy image */
738  StretchBlt (himlDst->hdcImage, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
739  himlSrc->hdcImage, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
740  SRCCOPY);
741 
742  /* copy mask */
743  StretchBlt (himlDst->hdcMask, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
744  himlSrc->hdcMask, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
745  SRCCOPY);
746  }
747 
748  return TRUE;
749 }
750 
751 
752 /*************************************************************************
753  * ImageList_Create [COMCTL32.@]
754  *
755  * Creates a new image list.
756  *
757  * PARAMS
758  * cx [I] image height
759  * cy [I] image width
760  * flags [I] creation flags
761  * cInitial [I] initial number of images in the image list
762  * cGrow [I] number of images by which image list grows
763  *
764  * RETURNS
765  * Success: Handle to the created image list
766  * Failure: NULL
767  */
770  INT cInitial, INT cGrow)
771 {
773  INT nCount;
774  HBITMAP hbmTemp;
775  UINT ilc = (flags & 0xFE);
776  static const WORD aBitBlend25[] =
777  {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00};
778 
779  static const WORD aBitBlend50[] =
780  {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
781 
782  TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow);
783 
784  if (cx < 0 || cy < 0) return NULL;
785  if (!((flags&ILC_COLORDDB) == ILC_COLORDDB) && (cx == 0 || cy == 0)) return NULL;
786 
787  /* Create the IImageList interface for the image list */
788  if (FAILED(ImageListImpl_CreateInstance(NULL, &IID_IImageList, (void **)&himl)))
789  return NULL;
790 
791  cGrow = (WORD)((max( cGrow, 1 ) + 3) & ~3);
792 
793  if (cGrow > 256)
794  {
795  /* Windows doesn't limit the size here, but X11 doesn't let us allocate such huge bitmaps */
796  WARN( "grow %d too large, limiting to 256\n", cGrow );
797  cGrow = 256;
798  }
799 
800  himl->cx = cx;
801  himl->cy = cy;
802  himl->flags = flags;
803  himl->cMaxImage = cInitial + 1;
804  himl->cInitial = cInitial;
805  himl->cGrow = cGrow;
807  himl->clrBk = CLR_NONE;
809 
810  /* initialize overlay mask indices */
811  for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
812  himl->nOvlIdx[nCount] = -1;
813 
814  /* Create Image & Mask DCs */
816  if (!himl->hdcImage)
817  goto cleanup;
818  if (himl->flags & ILC_MASK){
820  if (!himl->hdcMask)
821  goto cleanup;
822  }
823 
824  /* Default to ILC_COLOR4 if none of the ILC_COLOR* flags are specified */
825  if (ilc == ILC_COLOR)
826  {
827  ilc = ILC_COLOR4;
828  himl->flags |= ILC_COLOR4;
829  }
830 
831  if (ilc >= ILC_COLOR4 && ilc <= ILC_COLOR32)
832  himl->uBitsPixel = ilc;
833  else
835 
836  if (himl->cMaxImage > 0) {
839  } else
840  himl->hbmImage = 0;
841 
842  if ((himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) {
843  SIZE sz;
844 
846  himl->hbmMask = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
847  if (himl->hbmMask == 0) {
848  ERR("Error creating mask bitmap!\n");
849  goto cleanup;
850  }
852  }
853  else
854  himl->hbmMask = 0;
855 
856  if (ilc == ILC_COLOR32)
857  himl->has_alpha = heap_alloc_zero( himl->cMaxImage );
858  else
859  himl->has_alpha = NULL;
860 
861  /* create blending brushes */
862  hbmTemp = CreateBitmap (8, 8, 1, 1, aBitBlend25);
863  himl->hbrBlend25 = CreatePatternBrush (hbmTemp);
864  DeleteObject (hbmTemp);
865 
866  hbmTemp = CreateBitmap (8, 8, 1, 1, aBitBlend50);
867  himl->hbrBlend50 = CreatePatternBrush (hbmTemp);
868  DeleteObject (hbmTemp);
869 
870  TRACE("created imagelist %p\n", himl);
871  return himl;
872 
873 cleanup:
875  return NULL;
876 }
877 
878 
879 /*************************************************************************
880  * ImageList_Destroy [COMCTL32.@]
881  *
882  * Destroys an image list.
883  *
884  * PARAMS
885  * himl [I] handle to image list
886  *
887  * RETURNS
888  * Success: TRUE
889  * Failure: FALSE
890  */
891 
892 BOOL WINAPI
894 {
895  if (!is_valid(himl))
896  return FALSE;
897 
898  IImageList_Release((IImageList *) himl);
899  return TRUE;
900 }
901 
902 
903 /*************************************************************************
904  * ImageList_DragEnter [COMCTL32.@]
905  *
906  * Locks window update and displays the drag image at the given position.
907  *
908  * PARAMS
909  * hwndLock [I] handle of the window that owns the drag image.
910  * x [I] X position of the drag image.
911  * y [I] Y position of the drag image.
912  *
913  * RETURNS
914  * Success: TRUE
915  * Failure: FALSE
916  *
917  * NOTES
918  * The position of the drag image is relative to the window, not
919  * the client area.
920  */
921 
922 BOOL WINAPI
924 {
925  TRACE("(hwnd=%p x=%d y=%d)\n", hwndLock, x, y);
926 
927  if (!is_valid(InternalDrag.himl))
928  return FALSE;
929 
930  if (hwndLock)
931  InternalDrag.hwnd = hwndLock;
932  else
934 
935  InternalDrag.x = x;
936  InternalDrag.y = y;
937 
938  /* draw the drag image and save the background */
940 }
941 
942 
943 /*************************************************************************
944  * ImageList_DragLeave [COMCTL32.@]
945  *
946  * Unlocks window update and hides the drag image.
947  *
948  * PARAMS
949  * hwndLock [I] handle of the window that owns the drag image.
950  *
951  * RETURNS
952  * Success: TRUE
953  * Failure: FALSE
954  */
955 
956 BOOL WINAPI
958 {
959  /* As we don't save drag info in the window this can lead to problems if
960  an app does not supply the same window as DragEnter */
961  /* if (hwndLock)
962  InternalDrag.hwnd = hwndLock;
963  else
964  InternalDrag.hwnd = GetDesktopWindow (); */
965  if(!hwndLock)
966  hwndLock = GetDesktopWindow();
967  if(InternalDrag.hwnd != hwndLock)
968  FIXME("DragLeave hWnd != DragEnter hWnd\n");
969 
971 
972  return TRUE;
973 }
974 
975 
976 /*************************************************************************
977  * ImageList_InternalDragDraw [Internal]
978  *
979  * Draws the drag image.
980  *
981  * PARAMS
982  * hdc [I] device context to draw into.
983  * x [I] X position of the drag image.
984  * y [I] Y position of the drag image.
985  *
986  * RETURNS
987  * Success: TRUE
988  * Failure: FALSE
989  *
990  * NOTES
991  * The position of the drag image is relative to the window, not
992  * the client area.
993  *
994  */
995 
996 static inline void
998 {
999  IMAGELISTDRAWPARAMS imldp;
1000 
1001  ZeroMemory (&imldp, sizeof(imldp));
1002  imldp.cbSize = sizeof(imldp);
1003  imldp.himl = InternalDrag.himl;
1004  imldp.i = 0;
1005  imldp.hdcDst = hdc,
1006  imldp.x = x;
1007  imldp.y = y;
1008  imldp.rgbBk = CLR_DEFAULT;
1009  imldp.rgbFg = CLR_DEFAULT;
1010  imldp.fStyle = ILD_NORMAL;
1011  imldp.fState = ILS_ALPHA;
1012  imldp.Frame = 192;
1013  ImageList_DrawIndirect (&imldp);
1014 }
1015 
1016 /*************************************************************************
1017  * ImageList_DragMove [COMCTL32.@]
1018  *
1019  * Moves the drag image.
1020  *
1021  * PARAMS
1022  * x [I] X position of the drag image.
1023  * y [I] Y position of the drag image.
1024  *
1025  * RETURNS
1026  * Success: TRUE
1027  * Failure: FALSE
1028  *
1029  * NOTES
1030  * The position of the drag image is relative to the window, not
1031  * the client area.
1032  */
1033 
1034 BOOL WINAPI
1036 {
1037  TRACE("(x=%d y=%d)\n", x, y);
1038 
1039  if (!is_valid(InternalDrag.himl))
1040  return FALSE;
1041 
1042  /* draw/update the drag image */
1043  if (InternalDrag.bShow) {
1044  HDC hdcDrag;
1045  HDC hdcOffScreen;
1046  HDC hdcBg;
1047  HBITMAP hbmOffScreen;
1048  INT origNewX, origNewY;
1049  INT origOldX, origOldY;
1050  INT origRegX, origRegY;
1051  INT sizeRegX, sizeRegY;
1052 
1053 
1054  /* calculate the update region */
1055  origNewX = x - InternalDrag.dxHotspot;
1056  origNewY = y - InternalDrag.dyHotspot;
1057  origOldX = InternalDrag.x - InternalDrag.dxHotspot;
1058  origOldY = InternalDrag.y - InternalDrag.dyHotspot;
1059  origRegX = min(origNewX, origOldX);
1060  origRegY = min(origNewY, origOldY);
1061  sizeRegX = InternalDrag.himl->cx + abs(x - InternalDrag.x);
1062  sizeRegY = InternalDrag.himl->cy + abs(y - InternalDrag.y);
1063 
1064  hdcDrag = GetDCEx(InternalDrag.hwnd, 0,
1066  hdcOffScreen = CreateCompatibleDC(hdcDrag);
1067  hdcBg = CreateCompatibleDC(hdcDrag);
1068 
1069  hbmOffScreen = CreateCompatibleBitmap(hdcDrag, sizeRegX, sizeRegY);
1070  SelectObject(hdcOffScreen, hbmOffScreen);
1072 
1073  /* get the actual background of the update region */
1074  BitBlt(hdcOffScreen, 0, 0, sizeRegX, sizeRegY, hdcDrag,
1075  origRegX, origRegY, SRCCOPY);
1076  /* erase the old image */
1077  BitBlt(hdcOffScreen, origOldX - origRegX, origOldY - origRegY,
1078  InternalDrag.himl->cx, InternalDrag.himl->cy, hdcBg, 0, 0,
1079  SRCCOPY);
1080  /* save the background */
1081  BitBlt(hdcBg, 0, 0, InternalDrag.himl->cx, InternalDrag.himl->cy,
1082  hdcOffScreen, origNewX - origRegX, origNewY - origRegY, SRCCOPY);
1083  /* draw the image */
1084  ImageList_InternalDragDraw(hdcOffScreen, origNewX - origRegX,
1085  origNewY - origRegY);
1086  /* draw the update region to the screen */
1087  BitBlt(hdcDrag, origRegX, origRegY, sizeRegX, sizeRegY,
1088  hdcOffScreen, 0, 0, SRCCOPY);
1089 
1090  DeleteDC(hdcBg);
1091  DeleteDC(hdcOffScreen);
1092  DeleteObject(hbmOffScreen);
1093  ReleaseDC(InternalDrag.hwnd, hdcDrag);
1094  }
1095 
1096  /* update the image position */
1097  InternalDrag.x = x;
1098  InternalDrag.y = y;
1099 
1100  return TRUE;
1101 }
1102 
1103 
1104 /*************************************************************************
1105  * ImageList_DragShowNolock [COMCTL32.@]
1106  *
1107  * Shows or hides the drag image.
1108  *
1109  * PARAMS
1110  * bShow [I] TRUE shows the drag image, FALSE hides it.
1111  *
1112  * RETURNS
1113  * Success: TRUE
1114  * Failure: FALSE
1115  */
1116 
1117 BOOL WINAPI
1119 {
1120  HDC hdcDrag;
1121  HDC hdcBg;
1122  INT x, y;
1123 
1124  if (!is_valid(InternalDrag.himl))
1125  return FALSE;
1126 
1127  TRACE("bShow=0x%X!\n", bShow);
1128 
1129  /* DragImage is already visible/hidden */
1130  if ((InternalDrag.bShow && bShow) || (!InternalDrag.bShow && !bShow)) {
1131  return FALSE;
1132  }
1133 
1134  /* position of the origin of the DragImage */
1137 
1138  hdcDrag = GetDCEx (InternalDrag.hwnd, 0,
1140  if (!hdcDrag) {
1141  return FALSE;
1142  }
1143 
1144  hdcBg = CreateCompatibleDC(hdcDrag);
1145  if (!InternalDrag.hbmBg) {
1148  }
1150 
1151  if (bShow) {
1152  /* save the background */
1153  BitBlt(hdcBg, 0, 0, InternalDrag.himl->cx, InternalDrag.himl->cy,
1154  hdcDrag, x, y, SRCCOPY);
1155  /* show the image */
1156  ImageList_InternalDragDraw(hdcDrag, x, y);
1157  } else {
1158  /* hide the image */
1159  BitBlt(hdcDrag, x, y, InternalDrag.himl->cx, InternalDrag.himl->cy,
1160  hdcBg, 0, 0, SRCCOPY);
1161  }
1162 
1164 
1165  DeleteDC(hdcBg);
1166  ReleaseDC (InternalDrag.hwnd, hdcDrag);
1167  return TRUE;
1168 }
1169 
1170 
1171 /*************************************************************************
1172  * ImageList_Draw [COMCTL32.@]
1173  *
1174  * Draws an image.
1175  *
1176  * PARAMS
1177  * himl [I] handle to image list
1178  * i [I] image index
1179  * hdc [I] handle to device context
1180  * x [I] x position
1181  * y [I] y position
1182  * fStyle [I] drawing flags
1183  *
1184  * RETURNS
1185  * Success: TRUE
1186  * Failure: FALSE
1187  *
1188  * SEE
1189  * ImageList_DrawEx.
1190  */
1191 
1192 BOOL WINAPI
1194 {
1195  return ImageList_DrawEx (himl, i, hdc, x, y, 0, 0,
1196  CLR_DEFAULT, CLR_DEFAULT, fStyle);
1197 }
1198 
1199 
1200 /*************************************************************************
1201  * ImageList_DrawEx [COMCTL32.@]
1202  *
1203  * Draws an image and allows using extended drawing features.
1204  *
1205  * PARAMS
1206  * himl [I] handle to image list
1207  * i [I] image index
1208  * hdc [I] handle to device context
1209  * x [I] X position
1210  * y [I] Y position
1211  * dx [I] X offset
1212  * dy [I] Y offset
1213  * rgbBk [I] background color
1214  * rgbFg [I] foreground color
1215  * fStyle [I] drawing flags
1216  *
1217  * RETURNS
1218  * Success: TRUE
1219  * Failure: FALSE
1220  *
1221  * NOTES
1222  * Calls ImageList_DrawIndirect.
1223  *
1224  * SEE
1225  * ImageList_DrawIndirect.
1226  */
1227 
1228 BOOL WINAPI
1230  INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg,
1231  UINT fStyle)
1232 {
1233  IMAGELISTDRAWPARAMS imldp;
1234 
1235  ZeroMemory (&imldp, sizeof(imldp));
1236  imldp.cbSize = sizeof(imldp);
1237  imldp.himl = himl;
1238  imldp.i = i;
1239  imldp.hdcDst = hdc,
1240  imldp.x = x;
1241  imldp.y = y;
1242  imldp.cx = dx;
1243  imldp.cy = dy;
1244  imldp.rgbBk = rgbBk;
1245  imldp.rgbFg = rgbFg;
1246  imldp.fStyle = fStyle;
1247 
1248  return ImageList_DrawIndirect (&imldp);
1249 }
1250 
1251 #ifdef __REACTOS__
1252 static BOOL alpha_blend_image( HIMAGELIST himl, HDC srce_dc, HDC dest_dc, int dest_x, int dest_y,
1253 #else
1254 static BOOL alpha_blend_image( HIMAGELIST himl, HDC dest_dc, int dest_x, int dest_y,
1255 #endif
1256  int src_x, int src_y, int cx, int cy, BLENDFUNCTION func,
1257  UINT style, COLORREF blend_col )
1258 {
1259  BOOL ret = FALSE;
1260  HDC hdc;
1261  HBITMAP bmp = 0, mask = 0;
1262  BITMAPINFO *info;
1263  void *bits, *mask_bits;
1264  unsigned int *ptr;
1265  int i, j;
1266 
1267  if (!(hdc = CreateCompatibleDC( 0 ))) return FALSE;
1268  if (!(info = heap_alloc( FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto done;
1269  info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1270  info->bmiHeader.biWidth = cx;
1271  info->bmiHeader.biHeight = cy;
1272  info->bmiHeader.biPlanes = 1;
1273  info->bmiHeader.biBitCount = 32;
1274  info->bmiHeader.biCompression = BI_RGB;
1275  info->bmiHeader.biSizeImage = cx * cy * 4;
1276  info->bmiHeader.biXPelsPerMeter = 0;
1277  info->bmiHeader.biYPelsPerMeter = 0;
1278  info->bmiHeader.biClrUsed = 0;
1279  info->bmiHeader.biClrImportant = 0;
1280 #ifdef __REACTOS__
1281  if (!(bmp = CreateDIBSection( srce_dc, info, DIB_RGB_COLORS, &bits, 0, 0 ))) goto done;
1282 #else
1283  if (!(bmp = CreateDIBSection( himl->hdcImage, info, DIB_RGB_COLORS, &bits, 0, 0 ))) goto done;
1284 #endif
1285  SelectObject( hdc, bmp );
1286 #ifdef __REACTOS__
1287  BitBlt( hdc, 0, 0, cx, cy, srce_dc, src_x, src_y, SRCCOPY );
1288 #else
1289  BitBlt( hdc, 0, 0, cx, cy, himl->hdcImage, src_x, src_y, SRCCOPY );
1290 #endif
1291 
1292  if (blend_col != CLR_NONE)
1293  {
1294  BYTE r = GetRValue( blend_col );
1295  BYTE g = GetGValue( blend_col );
1296  BYTE b = GetBValue( blend_col );
1297 
1298  if (style & ILD_BLEND25)
1299  {
1300  for (i = 0, ptr = bits; i < cx * cy; i++, ptr++)
1301  *ptr = ((*ptr & 0xff000000) |
1302  ((((*ptr & 0x00ff0000) * 3 + (r << 16)) / 4) & 0x00ff0000) |
1303  ((((*ptr & 0x0000ff00) * 3 + (g << 8)) / 4) & 0x0000ff00) |
1304  ((((*ptr & 0x000000ff) * 3 + (b << 0)) / 4) & 0x000000ff));
1305  }
1306  else if (style & ILD_BLEND50)
1307  {
1308  for (i = 0, ptr = bits; i < cx * cy; i++, ptr++)
1309  *ptr = ((*ptr & 0xff000000) |
1310  ((((*ptr & 0x00ff0000) + (r << 16)) / 2) & 0x00ff0000) |
1311  ((((*ptr & 0x0000ff00) + (g << 8)) / 2) & 0x0000ff00) |
1312  ((((*ptr & 0x000000ff) + (b << 0)) / 2) & 0x000000ff));
1313  }
1314  }
1315 
1316  if (himl->has_alpha) /* we already have an alpha channel in this case */
1317  {
1318  /* pre-multiply by the alpha channel */
1319  for (i = 0, ptr = bits; i < cx * cy; i++, ptr++)
1320  {
1321  DWORD alpha = *ptr >> 24;
1322  *ptr = ((*ptr & 0xff000000) |
1323  (((*ptr & 0x00ff0000) * alpha / 255) & 0x00ff0000) |
1324  (((*ptr & 0x0000ff00) * alpha / 255) & 0x0000ff00) |
1325  (((*ptr & 0x000000ff) * alpha / 255)));
1326  }
1327  }
1328  else if (himl->hbmMask)
1329  {
1330  unsigned int width_bytes = (cx + 31) / 32 * 4;
1331  /* generate alpha channel from the mask */
1332  info->bmiHeader.biBitCount = 1;
1333  info->bmiHeader.biSizeImage = width_bytes * cy;
1334  info->bmiColors[0].rgbRed = 0;
1335  info->bmiColors[0].rgbGreen = 0;
1336  info->bmiColors[0].rgbBlue = 0;
1337  info->bmiColors[0].rgbReserved = 0;
1338  info->bmiColors[1].rgbRed = 0xff;
1339  info->bmiColors[1].rgbGreen = 0xff;
1340  info->bmiColors[1].rgbBlue = 0xff;
1341  info->bmiColors[1].rgbReserved = 0;
1342  if (!(mask = CreateDIBSection( himl->hdcMask, info, DIB_RGB_COLORS, &mask_bits, 0, 0 )))
1343  goto done;
1344  SelectObject( hdc, mask );
1345  BitBlt( hdc, 0, 0, cx, cy, himl->hdcMask, src_x, src_y, SRCCOPY );
1346  SelectObject( hdc, bmp );
1347  for (i = 0, ptr = bits; i < cy; i++)
1348  for (j = 0; j < cx; j++, ptr++)
1349  if ((((BYTE *)mask_bits)[i * width_bytes + j / 8] << (j % 8)) & 0x80) *ptr = 0;
1350  else *ptr |= 0xff000000;
1351  }
1352 
1353  ret = GdiAlphaBlend( dest_dc, dest_x, dest_y, cx, cy, hdc, 0, 0, cx, cy, func );
1354 
1355 done:
1356  DeleteDC( hdc );
1357  if (bmp) DeleteObject( bmp );
1358  if (mask) DeleteObject( mask );
1359  heap_free( info );
1360  return ret;
1361 }
1362 
1363 #ifdef __REACTOS__
1364 HDC saturate_image( HIMAGELIST himl, HDC dest_dc, int dest_x, int dest_y,
1365  int src_x, int src_y, int cx, int cy, COLORREF rgbFg)
1366 {
1367  HDC hdc = NULL;
1368  HBITMAP bmp = 0;
1369  BITMAPINFO *info;
1370 
1371  unsigned int *ptr;
1372  void *bits;
1373  int i;
1374 
1375  /* create a dc and its device independent bitmap for doing the work,
1376  shamelessly copied from the alpha-blending function above */
1377  if (!(hdc = CreateCompatibleDC( 0 ))) return FALSE;
1378  if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto done;
1379  info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1380  info->bmiHeader.biWidth = cx;
1381  info->bmiHeader.biHeight = cy;
1382  info->bmiHeader.biPlanes = 1;
1383  info->bmiHeader.biBitCount = 32;
1384  info->bmiHeader.biCompression = BI_RGB;
1385  info->bmiHeader.biSizeImage = cx * cy * 4;
1386  info->bmiHeader.biXPelsPerMeter = 0;
1387  info->bmiHeader.biYPelsPerMeter = 0;
1388  info->bmiHeader.biClrUsed = 0;
1389  info->bmiHeader.biClrImportant = 0;
1390  if (!(bmp = CreateDIBSection(himl->hdcImage, info, DIB_RGB_COLORS, &bits, 0, 0 ))) goto done;
1391 
1392  /* bind both surfaces */
1393  SelectObject(hdc, bmp);
1394 
1395  /* copy into our dc the section that covers just the icon we we're asked for */
1396  BitBlt(hdc, 0, 0, cx, cy, himl->hdcImage, src_x, src_y, SRCCOPY);
1397 
1398  /* loop every pixel of the bitmap */
1399  for (i = 0, ptr = bits; i < cx * cy; i++, ptr++)
1400  {
1401  COLORREF orig_color = *ptr;
1402 
1403  /* calculate the effective luminance using the constants from here, adapted to the human eye:
1404  <http://bobpowell.net/grayscale.aspx> */
1405  float mixed_color = (GetRValue(orig_color) * .30 +
1406  GetGValue(orig_color) * .59 +
1407  GetBValue(orig_color) * .11);
1408 
1409  *ptr = RGBA(mixed_color, mixed_color, mixed_color, GetAValue(orig_color));
1410  }
1411 
1412 done:
1413 
1414  if (bmp)
1415  DeleteObject(bmp);
1416 
1417  if (info)
1418  HeapFree(GetProcessHeap(), 0, info);
1419 
1420  /* return the handle to our desaturated dc, that will substitute its original counterpart in the next calls */
1421  return hdc;
1422 }
1423 #endif /* __REACTOS__ */
1424 
1425 /*************************************************************************
1426  * ImageList_DrawIndirect [COMCTL32.@]
1427  *
1428  * Draws an image using various parameters specified in pimldp.
1429  *
1430  * PARAMS
1431  * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
1432  *
1433  * RETURNS
1434  * Success: TRUE
1435  * Failure: FALSE
1436  */
1437 
1438 BOOL WINAPI
1440 {
1441  INT cx, cy, nOvlIdx;
1442  DWORD fState, dwRop;
1443  UINT fStyle;
1444  COLORREF oldImageBk, oldImageFg;
1445  HDC hImageDC, hImageListDC, hMaskListDC;
1446  HBITMAP hImageBmp, hOldImageBmp, hBlendMaskBmp;
1447  BOOL bIsTransparent, bBlend, bResult = FALSE, bMask;
1448  HIMAGELIST himl;
1449  HBRUSH hOldBrush;
1450  POINT pt;
1451  BOOL has_alpha;
1452 #ifdef __REACTOS__
1453  HDC hdcSaturated = NULL;
1454 #endif
1455 
1456  if (!pimldp || !(himl = pimldp->himl)) return FALSE;
1457  if (!is_valid(himl)) return FALSE;
1458  if ((pimldp->i < 0) || (pimldp->i >= himl->cCurImage)) return FALSE;
1459 
1460  imagelist_point_from_index( himl, pimldp->i, &pt );
1461  pt.x += pimldp->xBitmap;
1462  pt.y += pimldp->yBitmap;
1463 
1464  fState = pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS) ? ILS_NORMAL : pimldp->fState;
1465  fStyle = pimldp->fStyle & ~ILD_OVERLAYMASK;
1466  cx = (pimldp->cx == 0) ? himl->cx : pimldp->cx;
1467  cy = (pimldp->cy == 0) ? himl->cy : pimldp->cy;
1468 
1469  bIsTransparent = (fStyle & ILD_TRANSPARENT);
1470  if( pimldp->rgbBk == CLR_NONE )
1471  bIsTransparent = TRUE;
1472  if( ( pimldp->rgbBk == CLR_DEFAULT ) && ( himl->clrBk == CLR_NONE ) )
1473  bIsTransparent = TRUE;
1474  bMask = (himl->flags & ILC_MASK) && (fStyle & ILD_MASK) ;
1475  bBlend = (fStyle & (ILD_BLEND25 | ILD_BLEND50) ) && !bMask;
1476 
1477  TRACE("himl(%p) hbmMask(%p) iImage(%d) x(%d) y(%d) cx(%d) cy(%d)\n",
1478  himl, himl->hbmMask, pimldp->i, pimldp->x, pimldp->y, cx, cy);
1479 
1480  /* we will use these DCs to access the images and masks in the ImageList */
1481  hImageListDC = himl->hdcImage;
1482  hMaskListDC = himl->hdcMask;
1483 
1484  /* these will accumulate the image and mask for the image we're drawing */
1485  hImageDC = CreateCompatibleDC( pimldp->hdcDst );
1486  hImageBmp = CreateCompatibleBitmap( pimldp->hdcDst, cx, cy );
1487  hBlendMaskBmp = bBlend ? CreateBitmap(cx, cy, 1, 1, NULL) : 0;
1488 
1489  /* Create a compatible DC. */
1490  if (!hImageListDC || !hImageDC || !hImageBmp ||
1491  (bBlend && !hBlendMaskBmp) || (himl->hbmMask && !hMaskListDC))
1492  goto cleanup;
1493 
1494  hOldImageBmp = SelectObject(hImageDC, hImageBmp);
1495 
1496  /*
1497  * To obtain a transparent look, background color should be set
1498  * to white and foreground color to black when blitting the
1499  * monochrome mask.
1500  */
1501  oldImageFg = SetTextColor( hImageDC, RGB( 0, 0, 0 ) );
1502  oldImageBk = SetBkColor( hImageDC, RGB( 0xff, 0xff, 0xff ) );
1503 
1504 #ifdef __REACTOS__
1505  /*
1506  * If the ILS_SATURATE bit is enabled we should multiply the
1507  * RGB colors of the original image by the contents of rgbFg.
1508  */
1509  if (fState & ILS_SATURATE)
1510  {
1511  hdcSaturated = saturate_image(himl, pimldp->hdcDst, pimldp->x, pimldp->y,
1512  pt.x, pt.y, cx, cy, pimldp->rgbFg);
1513 
1514  hImageListDC = hdcSaturated;
1515  /* shitty way of getting subroutines to blit at the right place (top left corner),
1516  as our modified imagelist only contains a single image for performance reasons */
1517  pt.x = 0;
1518  pt.y = 0;
1519  }
1520 #endif
1521 
1522  has_alpha = (himl->has_alpha && himl->has_alpha[pimldp->i]);
1523  if (!bMask && (has_alpha || (fState & ILS_ALPHA)))
1524  {
1525  COLORREF colour, blend_col = CLR_NONE;
1527 
1528  if (bBlend)
1529  {
1530  blend_col = pimldp->rgbFg;
1531  if (blend_col == CLR_DEFAULT) blend_col = GetSysColor( COLOR_HIGHLIGHT );
1532  else if (blend_col == CLR_NONE) blend_col = GetTextColor( pimldp->hdcDst );
1533  }
1534 
1535  func.BlendOp = AC_SRC_OVER;
1536  func.BlendFlags = 0;
1537  func.SourceConstantAlpha = (fState & ILS_ALPHA) ? pimldp->Frame : 255;
1538  func.AlphaFormat = AC_SRC_ALPHA;
1539 
1540  if (bIsTransparent)
1541  {
1542 #ifdef __REACTOS__
1543  bResult = alpha_blend_image( himl, hImageListDC, pimldp->hdcDst, pimldp->x, pimldp->y,
1544 #else
1545  bResult = alpha_blend_image( himl, pimldp->hdcDst, pimldp->x, pimldp->y,
1546 #endif
1547  pt.x, pt.y, cx, cy, func, fStyle, blend_col );
1548  goto end;
1549  }
1550  colour = pimldp->rgbBk;
1551  if (colour == CLR_DEFAULT) colour = himl->clrBk;
1552  if (colour == CLR_NONE) colour = GetBkColor( pimldp->hdcDst );
1553 
1554  hOldBrush = SelectObject (hImageDC, CreateSolidBrush (colour));
1555  PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY );
1556 #ifdef __REACTOS__
1557  alpha_blend_image( himl, hImageListDC, hImageDC, 0, 0, pt.x, pt.y, cx, cy, func, fStyle, blend_col );
1558 #else
1559  alpha_blend_image( himl, hImageDC, 0, 0, pt.x, pt.y, cx, cy, func, fStyle, blend_col );
1560 #endif
1561  DeleteObject (SelectObject (hImageDC, hOldBrush));
1562  bResult = BitBlt( pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hImageDC, 0, 0, SRCCOPY );
1563  goto end;
1564  }
1565 
1566  /*
1567  * Draw the initial image
1568  */
1569  if( bMask ) {
1570  if (himl->hbmMask) {
1571  hOldBrush = SelectObject (hImageDC, CreateSolidBrush (GetTextColor(pimldp->hdcDst)));
1572  PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY );
1573  BitBlt(hImageDC, 0, 0, cx, cy, hMaskListDC, pt.x, pt.y, SRCPAINT);
1574  DeleteObject (SelectObject (hImageDC, hOldBrush));
1575  if( bIsTransparent )
1576  {
1577  BitBlt ( pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hImageDC, 0, 0, SRCAND);
1578  bResult = TRUE;
1579  goto end;
1580  }
1581  } else {
1582  hOldBrush = SelectObject (hImageDC, GetStockObject(BLACK_BRUSH));
1583  PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY);
1584  SelectObject(hImageDC, hOldBrush);
1585  }
1586  } else {
1587  /* blend the image with the needed solid background */
1588  COLORREF colour = RGB(0,0,0);
1589 
1590  if( !bIsTransparent )
1591  {
1592  colour = pimldp->rgbBk;
1593  if( colour == CLR_DEFAULT )
1594  colour = himl->clrBk;
1595  if( colour == CLR_NONE )
1596  colour = GetBkColor(pimldp->hdcDst);
1597  }
1598 
1599  hOldBrush = SelectObject (hImageDC, CreateSolidBrush (colour));
1600  PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY );
1601  if (himl->hbmMask)
1602  {
1603  BitBlt( hImageDC, 0, 0, cx, cy, hMaskListDC, pt.x, pt.y, SRCAND );
1604  BitBlt( hImageDC, 0, 0, cx, cy, hImageListDC, pt.x, pt.y, SRCPAINT );
1605  }
1606  else
1607  BitBlt( hImageDC, 0, 0, cx, cy, hImageListDC, pt.x, pt.y, SRCCOPY);
1608  DeleteObject (SelectObject (hImageDC, hOldBrush));
1609  }
1610 
1611  /* Time for blending, if required */
1612  if (bBlend) {
1613  HBRUSH hBlendBrush;
1614  COLORREF clrBlend = pimldp->rgbFg;
1615  HDC hBlendMaskDC = hImageListDC;
1616  HBITMAP hOldBitmap;
1617 
1618  /* Create the blend Mask */
1619  hOldBitmap = SelectObject(hBlendMaskDC, hBlendMaskBmp);
1620  hBlendBrush = fStyle & ILD_BLEND50 ? himl->hbrBlend50 : himl->hbrBlend25;
1621  hOldBrush = SelectObject(hBlendMaskDC, hBlendBrush);
1622  PatBlt(hBlendMaskDC, 0, 0, cx, cy, PATCOPY);
1623  SelectObject(hBlendMaskDC, hOldBrush);
1624 
1625  /* Modify the blend mask if an Image Mask exist */
1626  if(himl->hbmMask) {
1627  BitBlt(hBlendMaskDC, 0, 0, cx, cy, hMaskListDC, pt.x, pt.y, 0x220326); /* NOTSRCAND */
1628  BitBlt(hBlendMaskDC, 0, 0, cx, cy, hBlendMaskDC, 0, 0, NOTSRCCOPY);
1629  }
1630 
1631  /* now apply blend to the current image given the BlendMask */
1632  if (clrBlend == CLR_DEFAULT) clrBlend = GetSysColor (COLOR_HIGHLIGHT);
1633  else if (clrBlend == CLR_NONE) clrBlend = GetTextColor (pimldp->hdcDst);
1634  hOldBrush = SelectObject (hImageDC, CreateSolidBrush(clrBlend));
1635  BitBlt (hImageDC, 0, 0, cx, cy, hBlendMaskDC, 0, 0, 0xB8074A); /* PSDPxax */
1636  DeleteObject(SelectObject(hImageDC, hOldBrush));
1637  SelectObject(hBlendMaskDC, hOldBitmap);
1638  }
1639 
1640  /* Now do the overlay image, if any */
1641  nOvlIdx = (pimldp->fStyle & ILD_OVERLAYMASK) >> 8;
1642  if ( (nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE)) {
1643  nOvlIdx = himl->nOvlIdx[nOvlIdx - 1];
1644  if ((nOvlIdx >= 0) && (nOvlIdx < himl->cCurImage)) {
1645  POINT ptOvl;
1646  imagelist_point_from_index( himl, nOvlIdx, &ptOvl );
1647  ptOvl.x += pimldp->xBitmap;
1648  if (himl->hbmMask && !(fStyle & ILD_IMAGE))
1649  BitBlt (hImageDC, 0, 0, cx, cy, hMaskListDC, ptOvl.x, ptOvl.y, SRCAND);
1650  BitBlt (hImageDC, 0, 0, cx, cy, hImageListDC, ptOvl.x, ptOvl.y, SRCPAINT);
1651  }
1652  }
1653 
1654 #ifndef __REACTOS__
1655  if (fState & ILS_SATURATE) FIXME("ILS_SATURATE: unimplemented!\n");
1656 #endif
1657  if (fState & ILS_GLOW) FIXME("ILS_GLOW: unimplemented!\n");
1658  if (fState & ILS_SHADOW) FIXME("ILS_SHADOW: unimplemented!\n");
1659 
1660  if (fStyle & ILD_PRESERVEALPHA) FIXME("ILD_PRESERVEALPHA: unimplemented!\n");
1661  if (fStyle & ILD_SCALE) FIXME("ILD_SCALE: unimplemented!\n");
1662  if (fStyle & ILD_DPISCALE) FIXME("ILD_DPISCALE: unimplemented!\n");
1663 
1664  /* now copy the image to the screen */
1665  dwRop = SRCCOPY;
1666  if (himl->hbmMask && bIsTransparent ) {
1667  COLORREF oldDstFg = SetTextColor(pimldp->hdcDst, RGB( 0, 0, 0 ) );
1668  COLORREF oldDstBk = SetBkColor(pimldp->hdcDst, RGB( 0xff, 0xff, 0xff ));
1669  BitBlt (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hMaskListDC, pt.x, pt.y, SRCAND);
1670  SetBkColor(pimldp->hdcDst, oldDstBk);
1671  SetTextColor(pimldp->hdcDst, oldDstFg);
1672  dwRop = SRCPAINT;
1673  }
1674  if (fStyle & ILD_ROP) dwRop = pimldp->dwRop;
1675  BitBlt (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hImageDC, 0, 0, dwRop);
1676 
1677  bResult = TRUE;
1678 end:
1679  /* cleanup the mess */
1680  SetBkColor(hImageDC, oldImageBk);
1681  SetTextColor(hImageDC, oldImageFg);
1682  SelectObject(hImageDC, hOldImageBmp);
1683 cleanup:
1684 #ifdef __REACTOS__
1685  if (hdcSaturated)
1686  DeleteDC(hdcSaturated);
1687 #endif
1688  DeleteObject(hBlendMaskBmp);
1689  DeleteObject(hImageBmp);
1690  DeleteDC(hImageDC);
1691 
1692  return bResult;
1693 }
1694 
1695 
1696 /*************************************************************************
1697  * ImageList_Duplicate [COMCTL32.@]
1698  *
1699  * Duplicates an image list.
1700  *
1701  * PARAMS
1702  * himlSrc [I] source image list handle
1703  *
1704  * RETURNS
1705  * Success: Handle of duplicated image list.
1706  * Failure: NULL
1707  */
1708 
1711 {
1712  HIMAGELIST himlDst;
1713 
1714  if (!is_valid(himlSrc)) {
1715  ERR("Invalid image list handle!\n");
1716  return NULL;
1717  }
1718 
1719  himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
1720  himlSrc->cCurImage, himlSrc->cGrow);
1721 
1722  if (himlDst)
1723  {
1724  SIZE sz;
1725 
1726  imagelist_get_bitmap_size(himlSrc, himlSrc->cCurImage, &sz);
1727  BitBlt (himlDst->hdcImage, 0, 0, sz.cx, sz.cy,
1728  himlSrc->hdcImage, 0, 0, SRCCOPY);
1729 
1730  if (himlDst->hbmMask)
1731  BitBlt (himlDst->hdcMask, 0, 0, sz.cx, sz.cy,
1732  himlSrc->hdcMask, 0, 0, SRCCOPY);
1733 
1734  himlDst->cCurImage = himlSrc->cCurImage;
1735  if (himlSrc->has_alpha && himlDst->has_alpha)
1736  memcpy( himlDst->has_alpha, himlSrc->has_alpha, himlDst->cCurImage );
1737  }
1738  return himlDst;
1739 }
1740 
1741 
1742 /*************************************************************************
1743  * ImageList_EndDrag [COMCTL32.@]
1744  *
1745  * Finishes a drag operation.
1746  *
1747  * PARAMS
1748  * no Parameters
1749  *
1750  * RETURNS
1751  * Success: TRUE
1752  * Failure: FALSE
1753  */
1754 
1755 VOID WINAPI
1757 {
1758  /* cleanup the InternalDrag struct */
1759  InternalDrag.hwnd = 0;
1764  InternalDrag.x= 0;
1765  InternalDrag.y= 0;
1766  InternalDrag.dxHotspot = 0;
1767  InternalDrag.dyHotspot = 0;
1770  InternalDrag.hbmBg = 0;
1771 }
1772 
1773 
1774 /*************************************************************************
1775  * ImageList_GetBkColor [COMCTL32.@]
1776  *
1777  * Returns the background color of an image list.
1778  *
1779  * PARAMS
1780  * himl [I] Image list handle.
1781  *
1782  * RETURNS
1783  * Success: background color
1784  * Failure: CLR_NONE
1785  */
1786 
1789 {
1790  return himl ? himl->clrBk : CLR_NONE;
1791 }
1792 
1793 
1794 /*************************************************************************
1795  * ImageList_GetDragImage [COMCTL32.@]
1796  *
1797  * Returns the handle to the internal drag image list.
1798  *
1799  * PARAMS
1800  * ppt [O] Pointer to the drag position. Can be NULL.
1801  * pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
1802  *
1803  * RETURNS
1804  * Success: Handle of the drag image list.
1805  * Failure: NULL.
1806  */
1807 
1810 {
1811  if (is_valid(InternalDrag.himl)) {
1812  if (ppt) {
1813  ppt->x = InternalDrag.x;
1814  ppt->y = InternalDrag.y;
1815  }
1816  if (pptHotspot) {
1819  }
1820  return (InternalDrag.himl);
1821  }
1822 
1823  return NULL;
1824 }
1825 
1826 
1827 /*************************************************************************
1828  * ImageList_GetFlags [COMCTL32.@]
1829  *
1830  * Gets the flags of the specified image list.
1831  *
1832  * PARAMS
1833  * himl [I] Handle to image list
1834  *
1835  * RETURNS
1836  * Image list flags.
1837  *
1838  * BUGS
1839  * Stub.
1840  */
1841 
1842 DWORD WINAPI
1844 {
1845  TRACE("%p\n", himl);
1846 
1847  return is_valid(himl) ? himl->flags : 0;
1848 }
1849 
1850 
1851 /*************************************************************************
1852  * ImageList_GetIcon [COMCTL32.@]
1853  *
1854  * Creates an icon from a masked image of an image list.
1855  *
1856  * PARAMS
1857  * himl [I] handle to image list
1858  * i [I] image index
1859  * flags [I] drawing style flags
1860  *
1861  * RETURNS
1862  * Success: icon handle
1863  * Failure: NULL
1864  */
1865 
1866 HICON WINAPI
1868 {
1869  ICONINFO ii;
1870  HICON hIcon;
1871  HBITMAP hOldDstBitmap;
1872  HDC hdcDst;
1873  POINT pt;
1874 
1875  TRACE("%p %d %d\n", himl, i, fStyle);
1876  if (!is_valid(himl) || (i < 0) || (i >= himl->cCurImage)) return NULL;
1877 
1878  ii.fIcon = TRUE;
1879  ii.xHotspot = 0;
1880  ii.yHotspot = 0;
1881 
1882  /* create colour bitmap */
1883  hdcDst = GetDC(0);
1885  ReleaseDC(0, hdcDst);
1886 
1888 
1890 
1891  /* draw mask*/
1892  ii.hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
1893  hOldDstBitmap = SelectObject (hdcDst, ii.hbmMask);
1894  if (himl->hbmMask) {
1895  BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1896  himl->hdcMask, pt.x, pt.y, SRCCOPY);
1897  }
1898  else
1899  PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS);
1900 
1901  /* draw image*/
1903  BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1904  himl->hdcImage, pt.x, pt.y, SRCCOPY);
1905 
1906  /*
1907  * CreateIconIndirect requires us to deselect the bitmaps from
1908  * the DCs before calling
1909  */
1910  SelectObject(hdcDst, hOldDstBitmap);
1911 
1912  hIcon = CreateIconIndirect (&ii);
1913 
1914  DeleteObject (ii.hbmMask);
1915  DeleteObject (ii.hbmColor);
1916  DeleteDC (hdcDst);
1917 
1918  return hIcon;
1919 }
1920 
1921 
1922 /*************************************************************************
1923  * ImageList_GetIconSize [COMCTL32.@]
1924  *
1925  * Retrieves the size of an image in an image list.
1926  *
1927  * PARAMS
1928  * himl [I] handle to image list
1929  * cx [O] pointer to the image width.
1930  * cy [O] pointer to the image height.
1931  *
1932  * RETURNS
1933  * Success: TRUE
1934  * Failure: FALSE
1935  *
1936  * NOTES
1937  * All images in an image list have the same size.
1938  */
1939 
1940 BOOL WINAPI
1942 {
1943  if (!is_valid(himl) || !cx || !cy)
1944  return FALSE;
1945 
1946  *cx = himl->cx;
1947  *cy = himl->cy;
1948 
1949  return TRUE;
1950 }
1951 
1952 
1953 /*************************************************************************
1954  * ImageList_GetImageCount [COMCTL32.@]
1955  *
1956  * Returns the number of images in an image list.
1957  *
1958  * PARAMS
1959  * himl [I] handle to image list
1960  *
1961  * RETURNS
1962  * Success: Number of images.
1963  * Failure: 0
1964  */
1965 
1966 INT WINAPI
1968 {
1969  if (!is_valid(himl))
1970  return 0;
1971 
1972  return himl->cCurImage;
1973 }
1974 
1975 
1976 /*************************************************************************
1977  * ImageList_GetImageInfo [COMCTL32.@]
1978  *
1979  * Returns information about an image in an image list.
1980  *
1981  * PARAMS
1982  * himl [I] handle to image list
1983  * i [I] image index
1984  * pImageInfo [O] pointer to the image information
1985  *
1986  * RETURNS
1987  * Success: TRUE
1988  * Failure: FALSE
1989  */
1990 
1991 BOOL WINAPI
1993 {
1994  POINT pt;
1995 
1996  if (!is_valid(himl) || (pImageInfo == NULL))
1997  return FALSE;
1998  if ((i < 0) || (i >= himl->cCurImage))
1999  return FALSE;
2000 
2003 
2005  pImageInfo->rcImage.top = pt.y;
2006  pImageInfo->rcImage.bottom = pt.y + himl->cy;
2007  pImageInfo->rcImage.left = pt.x;
2008  pImageInfo->rcImage.right = pt.x + himl->cx;
2009 
2010  return TRUE;
2011 }
2012 
2013 
2014 /*************************************************************************
2015  * ImageList_GetImageRect [COMCTL32.@]
2016  *
2017  * Retrieves the rectangle of the specified image in an image list.
2018  *
2019  * PARAMS
2020  * himl [I] handle to image list
2021  * i [I] image index
2022  * lpRect [O] pointer to the image rectangle
2023  *
2024  * RETURNS
2025  * Success: TRUE
2026  * Failure: FALSE
2027  *
2028  * NOTES
2029  * This is an UNDOCUMENTED function!!!
2030  */
2031 
2032 BOOL WINAPI
2034 {
2035  POINT pt;
2036 
2037  if (!is_valid(himl) || (lpRect == NULL))
2038  return FALSE;
2039  if ((i < 0) || (i >= himl->cCurImage))
2040  return FALSE;
2041 
2043  lpRect->left = pt.x;
2044  lpRect->top = pt.y;
2045  lpRect->right = pt.x + himl->cx;
2046  lpRect->bottom = pt.y + himl->cy;
2047 
2048  return TRUE;
2049 }
2050 
2051 
2052 /*************************************************************************
2053  * ImageList_LoadImage [COMCTL32.@]
2054  * ImageList_LoadImageA [COMCTL32.@]
2055  *
2056  * Creates an image list from a bitmap, icon or cursor.
2057  *
2058  * See ImageList_LoadImageW.
2059  */
2060 
2063  COLORREF clrMask, UINT uType, UINT uFlags)
2064 {
2065  HIMAGELIST himl;
2066  LPWSTR lpbmpW;
2067  DWORD len;
2068 
2069  if (IS_INTRESOURCE(lpbmp))
2070  return ImageList_LoadImageW(hi, (LPCWSTR)lpbmp, cx, cGrow, clrMask,
2071  uType, uFlags);
2072 
2073  len = MultiByteToWideChar(CP_ACP, 0, lpbmp, -1, NULL, 0);
2074  lpbmpW = heap_alloc(len * sizeof(WCHAR));
2075  MultiByteToWideChar(CP_ACP, 0, lpbmp, -1, lpbmpW, len);
2076 
2077  himl = ImageList_LoadImageW(hi, lpbmpW, cx, cGrow, clrMask, uType, uFlags);
2078  heap_free (lpbmpW);
2079  return himl;
2080 }
2081 
2082 
2083 /*************************************************************************
2084  * ImageList_LoadImageW [COMCTL32.@]
2085  *
2086  * Creates an image list from a bitmap, icon or cursor.
2087  *
2088  * PARAMS
2089  * hi [I] instance handle
2090  * lpbmp [I] name or id of the image
2091  * cx [I] width of each image
2092  * cGrow [I] number of images to expand
2093  * clrMask [I] mask color
2094  * uType [I] type of image to load
2095  * uFlags [I] loading flags
2096  *
2097  * RETURNS
2098  * Success: handle to the loaded image list
2099  * Failure: NULL
2100  *
2101  * SEE
2102  * LoadImage ()
2103  */
2104 
2107  COLORREF clrMask, UINT uType, UINT uFlags)
2108 {
2109  HIMAGELIST himl = NULL;
2110  HANDLE handle;
2111  INT nImageCount;
2112 
2113  handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags);
2114  if (!handle) {
2115  WARN("Couldn't load image\n");
2116  return NULL;
2117  }
2118 
2119  if (uType == IMAGE_BITMAP) {
2120  DIBSECTION dib;
2121  UINT color;
2122 
2123  if (GetObjectW (handle, sizeof(dib), &dib) == sizeof(BITMAP)) color = ILC_COLOR;
2124  else color = dib.dsBm.bmBitsPixel;
2125 
2126  /* To match windows behavior, if cx is set to zero and
2127  the flag DI_DEFAULTSIZE is specified, cx becomes the
2128  system metric value for icons. If the flag is not specified
2129  the function sets the size to the height of the bitmap */
2130  if (cx == 0)
2131  {
2132  if (uFlags & DI_DEFAULTSIZE)
2134  else
2135  cx = dib.dsBm.bmHeight;
2136  }
2137 
2138  nImageCount = dib.dsBm.bmWidth / cx;
2139 
2140  if (clrMask != CLR_NONE) color |= ILC_MASK;
2141  himl = ImageList_Create (cx, dib.dsBm.bmHeight, color, nImageCount, cGrow);
2142  if (!himl) {
2143  DeleteObject (handle);
2144  return NULL;
2145  }
2146  ImageList_AddMasked (himl, handle, clrMask);
2147  }
2148  else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
2149  ICONINFO ii;
2150  BITMAP bmp;
2151 
2152  GetIconInfo (handle, &ii);
2153  GetObjectW (ii.hbmColor, sizeof(BITMAP), &bmp);
2154  himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
2155  ILC_MASK | ILC_COLOR, 1, cGrow);
2156  if (!himl) {
2157  DeleteObject (ii.hbmColor);
2158  DeleteObject (ii.hbmMask);
2159  DeleteObject (handle);
2160  return NULL;
2161  }
2162  ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
2163  DeleteObject (ii.hbmColor);
2164  DeleteObject (ii.hbmMask);
2165  }
2166 
2167  DeleteObject (handle);
2168 
2169  return himl;
2170 }
2171 
2172 
2173 /*************************************************************************
2174  * ImageList_Merge [COMCTL32.@]
2175  *
2176  * Create an image list containing a merged image from two image lists.
2177  *
2178  * PARAMS
2179  * himl1 [I] handle to first image list
2180  * i1 [I] first image index
2181  * himl2 [I] handle to second image list
2182  * i2 [I] second image index
2183  * dx [I] X offset of the second image relative to the first.
2184  * dy [I] Y offset of the second image relative to the first.
2185  *
2186  * RETURNS
2187  * Success: The newly created image list. It contains a single image
2188  * consisting of the second image merged with the first.
2189  * Failure: NULL, if either himl1 or himl2 is invalid.
2190  *
2191  * NOTES
2192  * - The returned image list should be deleted by the caller using
2193  * ImageList_Destroy() when it is no longer required.
2194  * - If either i1 or i2 is not a valid image index, they will be treated
2195  * as blank images.
2196  */
2199  INT dx, INT dy)
2200 {
2201  HIMAGELIST himlDst = NULL;
2202  INT cxDst, cyDst;
2203  INT xOff1, yOff1, xOff2, yOff2;
2204  POINT pt1, pt2;
2205  INT newFlags;
2206 
2207  TRACE("(himl1=%p i1=%d himl2=%p i2=%d dx=%d dy=%d)\n", himl1, i1, himl2,
2208  i2, dx, dy);
2209 
2210  if (!is_valid(himl1) || !is_valid(himl2))
2211  return NULL;
2212 
2213  if (dx > 0) {
2214  cxDst = max (himl1->cx, dx + himl2->cx);
2215  xOff1 = 0;
2216  xOff2 = dx;
2217  }
2218  else if (dx < 0) {
2219  cxDst = max (himl2->cx, himl1->cx - dx);
2220  xOff1 = -dx;
2221  xOff2 = 0;
2222  }
2223  else {
2224  cxDst = max (himl1->cx, himl2->cx);
2225  xOff1 = 0;
2226  xOff2 = 0;
2227  }
2228 
2229  if (dy > 0) {
2230  cyDst = max (himl1->cy, dy + himl2->cy);
2231  yOff1 = 0;
2232  yOff2 = dy;
2233  }
2234  else if (dy < 0) {
2235  cyDst = max (himl2->cy, himl1->cy - dy);
2236  yOff1 = -dy;
2237  yOff2 = 0;
2238  }
2239  else {
2240  cyDst = max (himl1->cy, himl2->cy);
2241  yOff1 = 0;
2242  yOff2 = 0;
2243  }
2244 
2245  newFlags = (himl1->flags > himl2->flags ? himl1->flags : himl2->flags) & ILC_COLORDDB;
2246  if (newFlags == ILC_COLORDDB && (himl1->flags & ILC_COLORDDB) == ILC_COLOR16)
2247  newFlags = ILC_COLOR16; /* this is what native (at least v5) does, don't know why */
2248  himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | newFlags, 1, 1);
2249 
2250  if (himlDst)
2251  {
2252  imagelist_point_from_index( himl1, i1, &pt1 );
2253  imagelist_point_from_index( himl2, i2, &pt2 );
2254 
2255  /* copy image */
2256  BitBlt (himlDst->hdcImage, 0, 0, cxDst, cyDst, himl1->hdcImage, 0, 0, BLACKNESS);
2257  if (i1 >= 0 && i1 < himl1->cCurImage)
2258  BitBlt (himlDst->hdcImage, xOff1, yOff1, himl1->cx, himl1->cy, himl1->hdcImage, pt1.x, pt1.y, SRCCOPY);
2259  if (i2 >= 0 && i2 < himl2->cCurImage)
2260  {
2261  if (himl2->flags & ILC_MASK)
2262  {
2263  BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcMask , pt2.x, pt2.y, SRCAND);
2264  BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcImage, pt2.x, pt2.y, SRCPAINT);
2265  }
2266  else
2267  BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcImage, pt2.x, pt2.y, SRCCOPY);
2268  }
2269 
2270  /* copy mask */
2271  BitBlt (himlDst->hdcMask, 0, 0, cxDst, cyDst, himl1->hdcMask, 0, 0, WHITENESS);
2272  if (i1 >= 0 && i1 < himl1->cCurImage)
2273  BitBlt (himlDst->hdcMask, xOff1, yOff1, himl1->cx, himl1->cy, himl1->hdcMask, pt1.x, pt1.y, SRCCOPY);
2274  if (i2 >= 0 && i2 < himl2->cCurImage)
2275  BitBlt (himlDst->hdcMask, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcMask, pt2.x, pt2.y, SRCAND);
2276 
2277  himlDst->cCurImage = 1;
2278  }
2279 
2280  return himlDst;
2281 }
2282 
2283 
2284 /* helper for ImageList_Read, see comments below */
2285 static void *read_bitmap(IStream *pstm, BITMAPINFO *bmi)
2286 {
2287  BITMAPFILEHEADER bmfh;
2288  int bitsperpixel, palspace;
2289  void *bits;
2290 
2291  if (FAILED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL)))
2292  return NULL;
2293 
2294  if (bmfh.bfType != (('M'<<8)|'B'))
2295  return NULL;
2296 
2297  if (FAILED(IStream_Read ( pstm, &bmi->bmiHeader, sizeof(bmi->bmiHeader), NULL)))
2298  return NULL;
2299 
2300  if ((bmi->bmiHeader.biSize != sizeof(bmi->bmiHeader)))
2301  return NULL;
2302 
2303  TRACE("width %u, height %u, planes %u, bpp %u\n",
2304  bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
2305  bmi->bmiHeader.biPlanes, bmi->bmiHeader.biBitCount);
2306 
2307  bitsperpixel = bmi->bmiHeader.biPlanes * bmi->bmiHeader.biBitCount;
2308  if (bitsperpixel<=8)
2309  palspace = (1<<bitsperpixel)*sizeof(RGBQUAD);
2310  else
2311  palspace = 0;
2312 
2314 
2315  /* read the palette right after the end of the bitmapinfoheader */
2316  if (palspace && FAILED(IStream_Read(pstm, bmi->bmiColors, palspace, NULL)))
2317  return NULL;
2318 
2319  bits = heap_alloc_zero(bmi->bmiHeader.biSizeImage);
2320  if (!bits) return NULL;
2321 
2322  if (FAILED(IStream_Read(pstm, bits, bmi->bmiHeader.biSizeImage, NULL)))
2323  {
2324  heap_free(bits);
2325  return NULL;
2326  }
2327  return bits;
2328 }
2329 
2330 /*************************************************************************
2331  * ImageList_Read [COMCTL32.@]
2332  *
2333  * Reads an image list from a stream.
2334  *
2335  * PARAMS
2336  * pstm [I] pointer to a stream
2337  *
2338  * RETURNS
2339  * Success: handle to image list
2340  * Failure: NULL
2341  *
2342  * The format is like this:
2343  * ILHEAD ilheadstruct;
2344  *
2345  * for the color image part:
2346  * BITMAPFILEHEADER bmfh;
2347  * BITMAPINFOHEADER bmih;
2348  * only if it has a palette:
2349  * RGBQUAD rgbs[nr_of_paletted_colors];
2350  *
2351  * BYTE colorbits[imagesize];
2352  *
2353  * the following only if the ILC_MASK bit is set in ILHEAD.ilFlags:
2354  * BITMAPFILEHEADER bmfh_mask;
2355  * BITMAPINFOHEADER bmih_mask;
2356  * only if it has a palette (it usually does not):
2357  * RGBQUAD rgbs[nr_of_paletted_colors];
2358  *
2359  * BYTE maskbits[imagesize];
2360  */
2362 {
2363  char image_buf[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256];
2364  char mask_buf[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256];
2365  BITMAPINFO *image_info = (BITMAPINFO *)image_buf;
2366  BITMAPINFO *mask_info = (BITMAPINFO *)mask_buf;
2367  void *image_bits, *mask_bits = NULL;
2368  ILHEAD ilHead;
2369  HIMAGELIST himl;
2370  unsigned int i;
2371 
2372  TRACE("%p\n", pstm);
2373 
2374  if (FAILED(IStream_Read (pstm, &ilHead, sizeof(ILHEAD), NULL)))
2375  return NULL;
2376  if (ilHead.usMagic != (('L' << 8) | 'I'))
2377  return NULL;
2378  if (ilHead.usVersion != 0x101) /* probably version? */
2379  return NULL;
2380 
2381  TRACE("cx %u, cy %u, flags 0x%04x, cCurImage %u, cMaxImage %u\n",
2382  ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage);
2383 
2384  himl = ImageList_Create(ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage);
2385  if (!himl)
2386  return NULL;
2387 
2388  if (!(image_bits = read_bitmap(pstm, image_info)))
2389  {
2390  WARN("failed to read bitmap from stream\n");
2391  return NULL;
2392  }
2393  if (ilHead.flags & ILC_MASK)
2394  {
2395  if (!(mask_bits = read_bitmap(pstm, mask_info)))
2396  {
2397  WARN("failed to read mask bitmap from stream\n");
2398  return NULL;
2399  }
2400  }
2401  else mask_info = NULL;
2402 
2403  if (himl->has_alpha && image_info->bmiHeader.biBitCount == 32)
2404  {
2405  DWORD *ptr = image_bits;
2406  BYTE *mask_ptr = mask_bits;
2407  int stride = himl->cy * image_info->bmiHeader.biWidth;
2408 
2409  if (image_info->bmiHeader.biHeight > 0) /* bottom-up */
2410  {
2411  ptr += image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride;
2412  mask_ptr += (image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride) / 8;
2413  stride = -stride;
2414  image_info->bmiHeader.biHeight = himl->cy;
2415  }
2416  else image_info->bmiHeader.biHeight = -himl->cy;
2417 
2418  for (i = 0; i < ilHead.cCurImage; i += TILE_COUNT)
2419  {
2420  add_dib_bits( himl, i, min( ilHead.cCurImage - i, TILE_COUNT ),
2421  himl->cx, himl->cy, image_info, mask_info, ptr, mask_ptr );
2422  ptr += stride;
2423  mask_ptr += stride / 8;
2424  }
2425  }
2426  else
2427  {
2428  StretchDIBits( himl->hdcImage, 0, 0, image_info->bmiHeader.biWidth, image_info->bmiHeader.biHeight,
2429  0, 0, image_info->bmiHeader.biWidth, image_info->bmiHeader.biHeight,
2430  image_bits, image_info, DIB_RGB_COLORS, SRCCOPY);
2431  if (mask_info)
2432  StretchDIBits( himl->hdcMask, 0, 0, mask_info->bmiHeader.biWidth, mask_info->bmiHeader.biHeight,
2433  0, 0, mask_info->bmiHeader.biWidth, mask_info->bmiHeader.biHeight,
2434  mask_bits, mask_info, DIB_RGB_COLORS, SRCCOPY);
2435  }
2436  heap_free( image_bits );
2437  heap_free( mask_bits );
2438 
2439  himl->cCurImage = ilHead.cCurImage;
2440  himl->cMaxImage = ilHead.cMaxImage;
2441 
2443  for (i=0;i<4;i++)
2444  ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1);
2445  return himl;
2446 }
2447 
2448 
2449 /*************************************************************************
2450  * ImageList_Remove [COMCTL32.@]
2451  *
2452  * Removes an image from an image list
2453  *
2454  * PARAMS
2455  * himl [I] image list handle
2456  * i [I] image index
2457  *
2458  * RETURNS
2459  * Success: TRUE
2460  * Failure: FALSE
2461  *
2462  * FIXME: as the image list storage test shows, native comctl32 simply shifts
2463  * images without creating a new bitmap.
2464  */
2465 BOOL WINAPI
2467 {
2468  HBITMAP hbmNewImage, hbmNewMask;
2469  HDC hdcBmp;
2470  SIZE sz;
2471 
2472  TRACE("(himl=%p i=%d)\n", himl, i);
2473 
2474  if (!is_valid(himl)) {
2475  ERR("Invalid image list handle!\n");
2476  return FALSE;
2477  }
2478 
2479  if ((i < -1) || (i >= himl->cCurImage)) {
2480  TRACE("index out of range! %d\n", i);
2481  return FALSE;
2482  }
2483 
2484  if (i == -1) {
2485  INT nCount;
2486 
2487  /* remove all */
2488  if (himl->cCurImage == 0) {
2489  /* remove all on empty ImageList is allowed */
2490  TRACE("remove all on empty ImageList!\n");
2491  return TRUE;
2492  }
2493 
2494  himl->cMaxImage = himl->cGrow;
2495  himl->cCurImage = 0;
2496  for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2497  himl->nOvlIdx[nCount] = -1;
2498 
2499  if (himl->has_alpha)
2500  {
2501  heap_free( himl->has_alpha );
2502  himl->has_alpha = heap_alloc_zero( himl->cMaxImage );
2503  }
2504 
2506  SelectObject (himl->hdcImage, hbmNewImage);
2508  himl->hbmImage = hbmNewImage;
2509 
2510  if (himl->hbmMask) {
2511 
2513  hbmNewMask = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
2514  SelectObject (himl->hdcMask, hbmNewMask);
2516  himl->hbmMask = hbmNewMask;
2517  }
2518  }
2519  else {
2520  /* delete one image */
2521  TRACE("Remove single image! %d\n", i);
2522 
2523  /* create new bitmap(s) */
2524  TRACE(" - Number of images: %d / %d (Old/New)\n",
2525  himl->cCurImage, himl->cCurImage - 1);
2526 
2528 
2530  if (himl->hbmMask)
2531  hbmNewMask = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
2532  else
2533  hbmNewMask = 0; /* Just to keep compiler happy! */
2534 
2535  hdcBmp = CreateCompatibleDC (0);
2536 
2537  /* copy all images and masks prior to the "removed" image */
2538  if (i > 0) {
2539  TRACE("Pre image copy: Copy %d images\n", i);
2540 
2541  SelectObject (hdcBmp, hbmNewImage);
2542  imagelist_copy_images( himl, himl->hdcImage, hdcBmp, 0, i, 0 );
2543 
2544  if (himl->hbmMask) {
2545  SelectObject (hdcBmp, hbmNewMask);
2546  imagelist_copy_images( himl, himl->hdcMask, hdcBmp, 0, i, 0 );
2547  }
2548  }
2549 
2550  /* copy all images and masks behind the removed image */
2551  if (i < himl->cCurImage - 1) {
2552  TRACE("Post image copy!\n");
2553 
2554  SelectObject (hdcBmp, hbmNewImage);
2555  imagelist_copy_images( himl, himl->hdcImage, hdcBmp, i + 1,
2556  (himl->cCurImage - i), i );
2557 
2558  if (himl->hbmMask) {
2559  SelectObject (hdcBmp, hbmNewMask);
2560  imagelist_copy_images( himl, himl->hdcMask, hdcBmp, i + 1,
2561  (himl->cCurImage - i), i );
2562  }
2563  }
2564 
2565  DeleteDC (hdcBmp);
2566 
2567  /* delete old images and insert new ones */
2568  SelectObject (himl->hdcImage, hbmNewImage);
2570  himl->hbmImage = hbmNewImage;
2571  if (himl->hbmMask) {
2572  SelectObject (himl->hdcMask, hbmNewMask);
2574  himl->hbmMask = hbmNewMask;
2575  }
2576 
2577  himl->cCurImage--;
2578  }
2579 
2580  return TRUE;
2581 }
2582 
2583 
2584 /*************************************************************************
2585  * ImageList_Replace [COMCTL32.@]
2586  *
2587  * Replaces an image in an image list with a new image.
2588  *
2589  * PARAMS
2590  * himl [I] handle to image list
2591  * i [I] image index
2592  * hbmImage [I] handle to image bitmap
2593  * hbmMask [I] handle to mask bitmap. Can be NULL.
2594  *
2595  * RETURNS
2596  * Success: TRUE
2597  * Failure: FALSE
2598  */
2599 
2600 BOOL WINAPI
2602  HBITMAP hbmMask)
2603 {
2604  HDC hdcImage;
2605  BITMAP bmp;
2606  POINT pt;
2607 
2608  TRACE("%p %d %p %p\n", himl, i, hbmImage, hbmMask);
2609 
2610  if (!is_valid(himl)) {
2611  ERR("Invalid image list handle!\n");
2612  return FALSE;
2613  }
2614 
2615  if ((i >= himl->cMaxImage) || (i < 0)) {
2616  ERR("Invalid image index!\n");
2617  return FALSE;
2618  }
2619 
2620  if (!GetObjectW(hbmImage, sizeof(BITMAP), &bmp))
2621  return FALSE;
2622 
2623  hdcImage = CreateCompatibleDC (0);
2624 
2625  /* Replace Image */
2626  SelectObject (hdcImage, hbmImage);
2627 
2628  if (add_with_alpha( himl, hdcImage, i, 1, bmp.bmWidth, bmp.bmHeight, hbmImage, hbmMask ))
2629  goto done;
2630 
2632  StretchBlt (himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy,
2633  hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2634 
2635  if (himl->hbmMask)
2636  {
2637  HDC hdcTemp;
2638  HBITMAP hOldBitmapTemp;
2639 
2640  hdcTemp = CreateCompatibleDC(0);
2641  hOldBitmapTemp = SelectObject(hdcTemp, hbmMask);
2642 
2643  StretchBlt (himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy,
2644  hdcTemp, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2645  SelectObject(hdcTemp, hOldBitmapTemp);
2646  DeleteDC(hdcTemp);
2647 
2648  /* Remove the background from the image
2649  */
2650  BitBlt (himl->hdcImage, pt.x, pt.y, bmp.bmWidth, bmp.bmHeight,
2651  himl->hdcMask, pt.x, pt.y, 0x220326); /* NOTSRCAND */
2652  }
2653 
2654 done:
2655  DeleteDC (hdcImage);
2656 
2657  return TRUE;
2658 }
2659 
2660 
2661 /*************************************************************************
2662  * ImageList_ReplaceIcon [COMCTL32.@]
2663  *
2664  * Replaces an image in an image list using an icon.
2665  *
2666  * PARAMS
2667  * himl [I] handle to image list
2668  * i [I] image index
2669  * hIcon [I] handle to icon
2670  *
2671  * RETURNS
2672  * Success: index of the replaced image
2673  * Failure: -1
2674  */
2675 
2676 INT WINAPI
2678 {
2679  HICON hBestFitIcon;
2680  ICONINFO ii;
2681  BITMAP bmp;
2682  BOOL ret;
2683  POINT pt;
2684 
2685  TRACE("(%p %d %p)\n", himl, nIndex, hIcon);
2686 
2687  if (!is_valid(himl)) {
2688  ERR("invalid image list\n");
2689  return -1;
2690  }
2691  if ((nIndex >= himl->cMaxImage) || (nIndex < -1)) {
2692  ERR("invalid image index %d / %d\n", nIndex, himl->cMaxImage);
2693  return -1;
2694  }
2695 
2696  hBestFitIcon = CopyImage(
2697  hIcon, IMAGE_ICON,
2698  himl->cx, himl->cy,
2700  /* the above will fail if the icon wasn't loaded from a resource, so try
2701  * again without LR_COPYFROMRESOURCE flag */
2702  if (!hBestFitIcon)
2703  hBestFitIcon = CopyImage(
2704  hIcon, IMAGE_ICON,
2705  himl->cx, himl->cy,
2706  0);
2707  if (!hBestFitIcon)
2708  return -1;
2709 
2710  if (nIndex == -1) {
2711  if (himl->cCurImage + 1 >= himl->cMaxImage)
2713 
2714  nIndex = himl->cCurImage;
2715  himl->cCurImage++;
2716  }
2717 
2718  if (himl->has_alpha && GetIconInfo (hBestFitIcon, &ii))
2719  {
2720  HDC hdcImage = CreateCompatibleDC( 0 );
2721  GetObjectW (ii.hbmMask, sizeof(BITMAP), &bmp);
2722 
2723  if (!ii.hbmColor)
2724  {
2725  UINT height = bmp.bmHeight / 2;
2726  HDC hdcMask = CreateCompatibleDC( 0 );
2727  HBITMAP color = CreateBitmap( bmp.bmWidth, height, 1, 1, NULL );
2728  SelectObject( hdcImage, color );
2729  SelectObject( hdcMask, ii.hbmMask );
2730  BitBlt( hdcImage, 0, 0, bmp.bmWidth, height, hdcMask, 0, height, SRCCOPY );
2731  ret = add_with_alpha( himl, hdcImage, nIndex, 1, bmp.bmWidth, height, color, ii.hbmMask );
2732  DeleteDC( hdcMask );
2733  DeleteObject( color );
2734  }
2735  else ret = add_with_alpha( himl, hdcImage, nIndex, 1, bmp.bmWidth, bmp.bmHeight,
2736  ii.hbmColor, ii.hbmMask );
2737 
2738  DeleteDC( hdcImage );
2739  DeleteObject (ii.hbmMask);
2740  if (ii.hbmColor) DeleteObject (ii.hbmColor);
2741  if (ret) goto done;
2742  }
2743 
2744  imagelist_point_from_index(himl, nIndex, &pt);
2745 
2746  if (himl->hbmMask)
2747  {
2748  DrawIconEx( himl->hdcImage, pt.x, pt.y, hBestFitIcon, himl->cx, himl->cy, 0, 0, DI_IMAGE );
2749  PatBlt( himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy, WHITENESS );
2750  DrawIconEx( himl->hdcMask, pt.x, pt.y, hBestFitIcon, himl->cx, himl->cy, 0, 0, DI_MASK );
2751  }
2752  else
2753  {
2755  HBRUSH brush = CreateSolidBrush( GetNearestColor( himl->hdcImage, color ));
2756 
2757  SelectObject( himl->hdcImage, brush );
2758  PatBlt( himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy, PATCOPY );
2760  DeleteObject( brush );
2761  DrawIconEx( himl->hdcImage, pt.x, pt.y, hBestFitIcon, himl->cx, himl->cy, 0, 0, DI_NORMAL );
2762  }
2763 
2764 done:
2765  DestroyIcon(hBestFitIcon);
2766 
2767  TRACE("Insert index = %d, himl->cCurImage = %d\n", nIndex, himl->cCurImage);
2768  return nIndex;
2769 }
2770 
2771 
2772 /*************************************************************************
2773  * ImageList_SetBkColor [COMCTL32.@]
2774  *
2775  * Sets the background color of an image list.
2776  *
2777  * PARAMS
2778  * himl [I] handle to image list
2779  * clrBk [I] background color
2780  *
2781  * RETURNS
2782  * Success: previous background color
2783  * Failure: CLR_NONE
2784  */
2785 
2788 {
2789  COLORREF clrOldBk;
2790 
2791  if (!is_valid(himl))
2792  return CLR_NONE;
2793 
2794  clrOldBk = himl->clrBk;
2795  himl->clrBk = clrBk;
2796  return clrOldBk;
2797 }
2798 
2799 
2800 /*************************************************************************
2801  * ImageList_SetDragCursorImage [COMCTL32.@]
2802  *
2803  * Combines the specified image with the current drag image
2804  *
2805  * PARAMS
2806  * himlDrag [I] handle to drag image list
2807  * iDrag [I] drag image index
2808  * dxHotspot [I] X position of the hot spot
2809  * dyHotspot [I] Y position of the hot spot
2810  *
2811  * RETURNS
2812  * Success: TRUE
2813  * Failure: FALSE
2814  *
2815  * NOTES
2816  * - The names dxHotspot, dyHotspot are misleading because they have nothing
2817  * to do with a hotspot but are only the offset of the origin of the new
2818  * image relative to the origin of the old image.
2819  *
2820  * - When this function is called and the drag image is visible, a
2821  * short flickering occurs but this matches the Win9x behavior. It is
2822  * possible to fix the flickering using code like in ImageList_DragMove.
2823  */
2824 
2825 BOOL WINAPI
2827  INT dxHotspot, INT dyHotspot)
2828 {
2829  HIMAGELIST himlTemp;
2830  BOOL visible;
2831 
2832  if (!is_valid(InternalDrag.himl) || !is_valid(himlDrag))
2833  return FALSE;
2834 
2835  TRACE(" dxH=%d dyH=%d nX=%d nY=%d\n",
2836  dxHotspot, dyHotspot, InternalDrag.dxHotspot, InternalDrag.dyHotspot);
2837 
2838  visible = InternalDrag.bShow;
2839 
2840  himlTemp = ImageList_Merge (InternalDrag.himlNoCursor, 0, himlDrag, iDrag,
2841  dxHotspot, dyHotspot);
2842 
2843  if (visible) {
2844  /* hide the drag image */
2846  }
2847  if ((InternalDrag.himl->cx != himlTemp->cx) ||
2848  (InternalDrag.himl->cy != himlTemp->cy)) {
2849  /* the size of the drag image changed, invalidate the buffer */
2851  InternalDrag.hbmBg = 0;
2852  }
2853 
2856  InternalDrag.himl = himlTemp;
2857 
2858  if (visible) {
2859  /* show the drag image */
2861  }
2862 
2863  return TRUE;
2864 }
2865 
2866 
2867 /*************************************************************************
2868  * ImageList_SetFilter [COMCTL32.@]
2869  *
2870  * Sets a filter (or does something completely different)!!???
2871  * It removes 12 Bytes from the stack (3 Parameters).
2872  *
2873  * PARAMS
2874  * himl [I] SHOULD be a handle to image list
2875  * i [I] COULD be an index?
2876  * dwFilter [I] ???
2877  *
2878  * RETURNS
2879  * Success: TRUE ???
2880  * Failure: FALSE ???
2881  *
2882  * BUGS
2883  * This is an UNDOCUMENTED function!!!!
2884  * empty stub.
2885  */
2886 
2887 BOOL WINAPI
2889 {
2890  FIXME("(%p 0x%x 0x%x):empty stub!\n", himl, i, dwFilter);
2891 
2892  return FALSE;
2893 }
2894 
2895 
2896 /*************************************************************************
2897  * ImageList_SetFlags [COMCTL32.@]
2898  *
2899  * Sets the image list flags.
2900  *
2901  * PARAMS
2902  * himl [I] Handle to image list
2903  * flags [I] Flags to set
2904  *
2905  * RETURNS
2906  * Old flags?
2907  *
2908  * BUGS
2909  * Stub.
2910  */
2911 
2912 DWORD WINAPI
2914 {
2915  FIXME("(%p %08x):empty stub\n", himl, flags);
2916  return 0;
2917 }
2918 
2919 
2920 /*************************************************************************
2921  * ImageList_SetIconSize [COMCTL32.@]
2922  *
2923  * Sets the image size of the bitmap and deletes all images.
2924  *
2925  * PARAMS
2926  * himl [I] handle to image list
2927  * cx [I] image width
2928  * cy [I] image height
2929  *
2930  * RETURNS
2931  * Success: TRUE
2932  * Failure: FALSE
2933  */
2934 
2935 BOOL WINAPI
2937 {
2938  INT nCount;
2939  HBITMAP hbmNew;
2940 
2941  if (!is_valid(himl))
2942  return FALSE;
2943 
2944  /* remove all images */
2945  himl->cMaxImage = himl->cInitial + 1;
2946  himl->cCurImage = 0;
2947  himl->cx = cx;
2948  himl->cy = cy;
2949 
2950  /* initialize overlay mask indices */
2951  for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2952  himl->nOvlIdx[nCount] = -1;
2953 
2955  SelectObject (himl->hdcImage, hbmNew);
2957  himl->hbmImage = hbmNew;
2958 
2959  if (himl->hbmMask) {
2960  SIZE sz;
2962  hbmNew = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
2963  SelectObject (himl->hdcMask, hbmNew);
2965  himl->hbmMask = hbmNew;
2966  }
2967 
2968  return TRUE;
2969 }
2970 
2971 
2972 /*************************************************************************
2973  * ImageList_SetImageCount [COMCTL32.@]
2974  *
2975  * Resizes an image list to the specified number of images.
2976  *
2977  * PARAMS
2978  * himl [I] handle to image list
2979  * iImageCount [I] number of images in the image list
2980  *
2981  * RETURNS
2982  * Success: TRUE
2983  * Failure: FALSE
2984  */
2985 
2986 BOOL WINAPI
2988 {
2989  HDC hdcBitmap;
2990  HBITMAP hbmNewBitmap, hbmOld;
2991  INT nNewCount, nCopyCount;
2992 
2993  TRACE("%p %d\n",himl,iImageCount);
2994 
2995  if (!is_valid(himl))
2996  return FALSE;
2997 
2998  nNewCount = iImageCount + 1;
2999  nCopyCount = min(himl->cCurImage, iImageCount);
3000 
3002 
3003  hbmNewBitmap = ImageList_CreateImage(hdcBitmap, himl, nNewCount);
3004 
3005  if (hbmNewBitmap != 0)
3006  {
3007  hbmOld = SelectObject (hdcBitmap, hbmNewBitmap);
3008  imagelist_copy_images( himl, himl->hdcImage, hdcBitmap, 0, nCopyCount, 0 );
3009  SelectObject (hdcBitmap, hbmOld);
3010 
3011  /* FIXME: delete 'empty' image space? */
3012 
3013  SelectObject (himl->hdcImage, hbmNewBitmap);
3015  himl->hbmImage = hbmNewBitmap;
3016  }
3017  else
3018  ERR("Could not create new image bitmap!\n");
3019 
3020  if (himl->hbmMask)
3021  {
3022  SIZE sz;
3023  imagelist_get_bitmap_size( himl, nNewCount, &sz );
3024  hbmNewBitmap = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
3025  if (hbmNewBitmap != 0)
3026  {
3027  hbmOld = SelectObject (hdcBitmap, hbmNewBitmap);
3028  imagelist_copy_images( himl, himl->hdcMask, hdcBitmap, 0, nCopyCount, 0 );
3029  SelectObject (hdcBitmap, hbmOld);
3030 
3031  /* FIXME: delete 'empty' image space? */
3032 
3033  SelectObject (himl->hdcMask, hbmNewBitmap);
3035  himl->hbmMask = hbmNewBitmap;
3036  }
3037  else
3038  ERR("Could not create new mask bitmap!\n");
3039  }
3040 
3041  DeleteDC (hdcBitmap);
3042 
3043  if (himl->has_alpha)
3044  {
3045  char *new_alpha = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, himl->has_alpha, nNewCount );
3046  if (new_alpha) himl->has_alpha = new_alpha;
3047  else
3048  {
3049  heap_free( himl->has_alpha );
3050  himl->has_alpha = NULL;
3051  }
3052  }
3053 
3054  /* Update max image count and current image count */
3055  himl->cMaxImage = nNewCount;
3056  himl->cCurImage = iImageCount;
3057 
3058  return TRUE;
3059 }
3060 
3061 
3062 /*************************************************************************
3063  * ImageList_SetOverlayImage [COMCTL32.@]
3064  *
3065  * Assigns an overlay mask index to an existing image in an image list.
3066  *
3067  * PARAMS
3068  * himl [I] handle to image list
3069  * iImage [I] image index
3070  * iOverlay [I] overlay mask index
3071  *
3072  * RETURNS
3073  * Success: TRUE
3074  * Failure: FALSE
3075  */
3076 
3077 BOOL WINAPI
3079 {
3080  if (!is_valid(himl))
3081  return FALSE;
3082  if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
3083  return FALSE;
3084  if ((iImage!=-1) && ((iImage < 0) || (iImage > himl->cCurImage)))
3085  return FALSE;
3086  himl->nOvlIdx[iOverlay - 1] = iImage;
3087  return TRUE;
3088 }
3089 
3090 
3091 
3092 /* helper for ImageList_Write - write bitmap to pstm
3093  * currently everything is written as 24 bit RGB, except masks
3094  */
3096 {
3097  LPBITMAPFILEHEADER bmfh;
3098  LPBITMAPINFOHEADER bmih;
3099  LPBYTE data = NULL, lpBits;
3100  BITMAP bm;
3101  INT bitCount, sizeImage, offBits, totalSize;
3102  HDC xdc;
3103  BOOL result = FALSE;
3104 
3105  if (!GetObjectW(hBitmap, sizeof(BITMAP), &bm))
3106  return FALSE;
3107 
3108  bitCount = bm.bmBitsPixel;
3109  sizeImage = get_dib_stride(bm.bmWidth, bitCount) * bm.bmHeight;
3110 
3111  totalSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
3112  if(bitCount <= 8)
3113  totalSize += (1 << bitCount) * sizeof(RGBQUAD);
3114  offBits = totalSize;
3115  totalSize += sizeImage;
3116 
3117  data = heap_alloc_zero(totalSize);
3118  bmfh = (LPBITMAPFILEHEADER)data;
3119  bmih = (LPBITMAPINFOHEADER)(data + sizeof(BITMAPFILEHEADER));
3120  lpBits = data + offBits;
3121 
3122  /* setup BITMAPFILEHEADER */
3123  bmfh->bfType = (('M' << 8) | 'B');
3124  bmfh->bfSize = offBits;
3125  bmfh->bfReserved1 = 0;
3126  bmfh->bfReserved2 = 0;
3127  bmfh->bfOffBits = offBits;
3128 
3129  /* setup BITMAPINFOHEADER */
3130  bmih->biSize = sizeof(BITMAPINFOHEADER);
3131  bmih->biWidth = bm.bmWidth;
3132  bmih->biHeight = bm.bmHeight;
3133  bmih->biPlanes = 1;
3134  bmih->biBitCount = bitCount;
3135  bmih->biCompression = BI_RGB;
3136  bmih->biSizeImage = sizeImage;
3137  bmih->biXPelsPerMeter = 0;
3138  bmih->biYPelsPerMeter = 0;
3139  bmih->biClrUsed = 0;
3140  bmih->biClrImportant = 0;
3141 
3142  xdc = GetDC(0);
3143  result = GetDIBits(xdc, hBitmap, 0, bm.bmHeight, lpBits, (BITMAPINFO *)bmih, DIB_RGB_COLORS) == bm.bmHeight;
3144  ReleaseDC(0, xdc);
3145  if (!result)
3146  goto failed;
3147 
3148  TRACE("width %u, height %u, planes %u, bpp %u\n",
3149  bmih->biWidth, bmih->biHeight,
3150  bmih->biPlanes, bmih->biBitCount);
3151 
3152  if(FAILED(IStream_Write(pstm, data, totalSize, NULL)))
3153  goto failed;
3154 
3155  result = TRUE;
3156 
3157 failed:
3158  heap_free(data);
3159 
3160  return result;
3161 }
3162 
3163 
3164 /*************************************************************************
3165  * ImageList_Write [COMCTL32.@]
3166  *
3167  * Writes an image list to a stream.
3168  *
3169  * PARAMS
3170  * himl [I] handle to image list
3171  * pstm [O] Pointer to a stream.
3172  *
3173  * RETURNS
3174  * Success: TRUE
3175  * Failure: FALSE
3176  *
3177  * BUGS
3178  * probably.
3179  */
3180 
3182 {
3183  ILHEAD ilHead;
3184  int i;
3185 
3186  TRACE("%p %p\n", himl, pstm);
3187 
3188  if (!is_valid(himl))
3189  return FALSE;
3190 
3191  ilHead.usMagic = (('L' << 8) | 'I');
3192  ilHead.usVersion = 0x101;
3193  ilHead.cCurImage = himl->cCurImage;
3194  ilHead.cMaxImage = himl->cMaxImage;
3195  ilHead.cGrow = himl->cGrow;
3196  ilHead.cx = himl->cx;
3197  ilHead.cy = himl->cy;
3198  ilHead.bkcolor = himl->clrBk;
3199  ilHead.flags = himl->flags;
3200  for(i = 0; i < 4; i++) {
3201  ilHead.ovls[i] = himl->nOvlIdx[i];
3202  }
3203 
3204  TRACE("cx %u, cy %u, flags 0x04%x, cCurImage %u, cMaxImage %u\n",
3205  ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage);
3206 
3207  if(FAILED(IStream_Write(pstm, &ilHead, sizeof(ILHEAD), NULL)))
3208  return FALSE;
3209 
3210  /* write the bitmap */
3211  if(!_write_bitmap(himl->hbmImage, pstm))
3212  return FALSE;
3213 
3214  /* write the mask if we have one */
3215  if(himl->flags & ILC_MASK) {
3216  if(!_write_bitmap(himl->hbmMask, pstm))
3217  return FALSE;
3218  }
3219 
3220  return TRUE;
3221 }
3222 
3223 
3225 {
3226  HBITMAP hbmNewBitmap;
3227  UINT ilc = (himl->flags & 0xFE);
3228  SIZE sz;
3229 
3231 
3232  if ((ilc >= ILC_COLOR4 && ilc <= ILC_COLOR32) || ilc == ILC_COLOR)
3233  {
3234  char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
3235  BITMAPINFO *bmi = (BITMAPINFO *)buffer;
3236 
3237  TRACE("Creating DIBSection %d x %d, %d Bits per Pixel\n",
3238  sz.cx, sz.cy, himl->uBitsPixel);
3239 
3240  memset( buffer, 0, sizeof(buffer) );
3241  bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
3242  bmi->bmiHeader.biWidth = sz.cx;
3243  bmi->bmiHeader.biHeight = sz.cy;
3244  bmi->bmiHeader.biPlanes = 1;
3247 
3248  if (himl->uBitsPixel <= ILC_COLOR8)
3249  {
3250  if (!himl->color_table_set)
3251  {
3252  /* retrieve the default color map */
3253  HBITMAP tmp = CreateBitmap( 1, 1, 1, 1, NULL );
3254  GetDIBits( hdc, tmp, 0, 0, NULL, bmi, DIB_RGB_COLORS );
3255  DeleteObject( tmp );
3256  if (ilc == ILC_COLOR4)
3257  {
3258  RGBQUAD tmp;
3259  tmp = bmi->bmiColors[7];
3260  bmi->bmiColors[7] = bmi->bmiColors[8];
3261  bmi->bmiColors[8] = tmp;
3262  }
3263  }
3264  else
3265  {
3267  }
3268  }
3269  hbmNewBitmap = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, 0, 0);
3270  }
3271  else /*if (ilc == ILC_COLORDDB)*/
3272  {
3273  TRACE("Creating Bitmap: %d Bits per Pixel\n", himl->uBitsPixel);
3274 
3275  hbmNewBitmap = CreateBitmap (sz.cx, sz.cy, 1, himl->uBitsPixel, NULL);
3276  }
3277  TRACE("returning %p\n", hbmNewBitmap);
3278  return hbmNewBitmap;
3279 }
3280 
3281 /*************************************************************************
3282  * ImageList_SetColorTable [COMCTL32.@]
3283  *
3284  * Sets the color table of an image list.
3285  *
3286  * PARAMS
3287  * himl [I] Handle to the image list.
3288  * uStartIndex [I] The first index to set.
3289  * cEntries [I] Number of entries to set.
3290  * prgb [I] New color information for color table for the image list.
3291  *
3292  * RETURNS
3293  * Success: Number of entries in the table that were set.
3294  * Failure: Zero.
3295  *
3296  * SEE
3297  * ImageList_Create(), SetDIBColorTable()
3298  */
3299 
3300 UINT WINAPI
3302 {
3303  TRACE("(%p, %d, %d, %p)\n", himl, uStartIndex, cEntries, prgb);
3305  return SetDIBColorTable(himl->hdcImage, uStartIndex, cEntries, prgb);
3306 }
3307 
3308 /*************************************************************************
3309  * ImageList_CoCreateInstance [COMCTL32.@]
3310  *
3311  * Creates a new imagelist instance and returns an interface pointer to it.
3312  *
3313  * PARAMS
3314  * rclsid [I] A reference to the CLSID (CLSID_ImageList).
3315  * punkOuter [I] Pointer to IUnknown interface for aggregation, if desired
3316  * riid [I] Identifier of the requested interface.
3317  * ppv [O] Returns the address of the pointer requested, or NULL.
3318  *
3319  * RETURNS
3320  * Success: S_OK.
3321  * Failure: Error value.
3322  */
3324 ImageList_CoCreateInstance (REFCLSID rclsid, const IUnknown *punkOuter, REFIID riid, void **ppv)
3325 {
3326  TRACE("(%s,%p,%s,%p)\n", debugstr_guid(rclsid), punkOuter, debugstr_guid(riid), ppv);
3327 
3328  if (!IsEqualCLSID(&CLSID_ImageList, rclsid))
3329  return E_NOINTERFACE;
3330 
3331  return ImageListImpl_CreateInstance(punkOuter, riid, ppv);
3332 }
3333 
3334 
3335 /*************************************************************************
3336  * IImageList implementation
3337  */
3338 
3340  REFIID iid, void **ppv)
3341 {
3342  HIMAGELIST imgl = impl_from_IImageList2(iface);
3343 
3344  TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
3345 
3346  if (!ppv) return E_INVALIDARG;
3347 
3348  if (IsEqualIID(&IID_IUnknown, iid) ||
3349  IsEqualIID(&IID_IImageList, iid) ||
3350  IsEqualIID(&IID_IImageList2, iid))
3351  {
3352  *ppv = &imgl->IImageList2_iface;
3353  }
3354  else
3355  {
3356  *ppv = NULL;
3357  return E_NOINTERFACE;
3358  }
3359 
3360  IImageList2_AddRef(iface);
3361  return S_OK;
3362 }
3363 
3365 {
3366  HIMAGELIST imgl = impl_from_IImageList2(iface);
3367  ULONG ref = InterlockedIncrement(&imgl->ref);
3368 
3369  TRACE("(%p) refcount=%u\n", iface, ref);
3370  return ref;
3371 }
3372 
3374 {
3377 
3378  TRACE("(%p) refcount=%u\n", iface, ref);
3379 
3380  if (ref == 0)
3381  {
3382  /* delete image bitmaps */
3383  if (This->hbmImage) DeleteObject (This->hbmImage);
3384  if (This->hbmMask) DeleteObject (This->hbmMask);
3385 
3386  /* delete image & mask DCs */
3387  if (This->hdcImage) DeleteDC (This->hdcImage);
3388  if (This->hdcMask) DeleteDC (This->hdcMask);
3389 
3390  /* delete blending brushes */
3391  if (This->hbrBlend25) DeleteObject (This->hbrBlend25);
3392  if (This->hbrBlend50) DeleteObject (This->hbrBlend50);
3393 
3394  This->IImageList2_iface.lpVtbl = NULL;
3395  heap_free(This->has_alpha);
3396  heap_free(This);
3397  }
3398 
3399  return ref;
3400 }
3401 
3403  HBITMAP hbmMask, int *pi)
3404 {
3405  HIMAGELIST imgl = impl_from_IImageList2(iface);
3406  int ret;
3407 
3408  if (!pi)
3409  return E_FAIL;
3410 
3411  ret = ImageList_Add(imgl, hbmImage, hbmMask);
3412 
3413  if (ret == -1)
3414  return E_FAIL;
3415 
3416  *pi = ret;
3417  return S_OK;
3418 }
3419 
3421  HICON hicon, int *pi)
3422 {
3423  HIMAGELIST imgl = impl_from_IImageList2(iface);
3424  int ret;
3425 
3426  if (!pi)
3427  return E_FAIL;
3428 
3429  ret = ImageList_ReplaceIcon(imgl, i, hicon);
3430 
3431  if (ret == -1)
3432  return E_FAIL;
3433 
3434  *pi = ret;
3435  return S_OK;
3436 }
3437 
3439  int iImage, int iOverlay)
3440 {
3441  HIMAGELIST imgl = impl_from_IImageList2(iface);
3442  return ImageList_SetOverlayImage(imgl, iImage, iOverlay) ? S_OK : E_FAIL;
3443 }
3444 
3446  HBITMAP hbmImage, HBITMAP hbmMask)
3447 {
3448  HIMAGELIST imgl = impl_from_IImageList2(iface);
3449  return ImageList_Replace(imgl, i, hbmImage, hbmMask) ? S_OK : E_FAIL;
3450 }
3451 
3453  COLORREF crMask, int *pi)
3454 {
3455  HIMAGELIST imgl = impl_from_IImageList2(iface);
3456  int ret;
3457 
3458  if (!pi)
3459  return E_FAIL;
3460 
3461  ret = ImageList_AddMasked(imgl, hbmImage, crMask);
3462 
3463  if (ret == -1)
3464  return E_FAIL;
3465 
3466  *pi = ret;
3467  return S_OK;
3468 }
3469 
3471  IMAGELISTDRAWPARAMS *pimldp)
3472 {
3473  HIMAGELIST imgl = impl_from_IImageList2(iface);
3474  HIMAGELIST old_himl;
3475  int ret;
3476 
3477  /* As far as I can tell, Windows simply ignores the contents of pimldp->himl
3478  so we shall simulate the same */
3479  old_himl = pimldp->himl;
3480  pimldp->himl = imgl;
3481 
3482  ret = ImageList_DrawIndirect(pimldp);
3483 
3484  pimldp->himl = old_himl;
3485  return ret ? S_OK : E_INVALIDARG;
3486 }
3487 
3489 {
3490  HIMAGELIST imgl = impl_from_IImageList2(iface);
3491  return (ImageList_Remove(imgl, i) == 0) ? E_INVALIDARG : S_OK;
3492 }
3493 
3495  HICON *picon)
3496 {
3497  HIMAGELIST imgl = impl_from_IImageList2(iface);
3498  HICON hIcon;
3499 
3500  if (!picon)
3501  return E_FAIL;
3502 
3503  hIcon = ImageList_GetIcon(imgl, i, flags);
3504 
3505  if (hIcon == NULL)
3506  return E_FAIL;
3507 
3508  *picon = hIcon;
3509  return S_OK;
3510 }
3511 
3514 {
3515  HIMAGELIST imgl = impl_from_IImageList2(iface);
3516  return ImageList_GetImageInfo(imgl, i, pImageInfo) ? S_OK : E_FAIL;
3517 }
3518 
3519 static HRESULT WINAPI ImageListImpl_Copy(IImageList2 *iface, int dst_index,
3520  IUnknown *unk_src, int src_index, UINT flags)
3521 {
3522  HIMAGELIST imgl = impl_from_IImageList2(iface);
3523  IImageList *src = NULL;
3524  HRESULT ret;
3525 
3526  if (!unk_src)
3527  return E_FAIL;
3528 
3529  /* TODO: Add test for IID_ImageList2 too */
3530  if (FAILED(IUnknown_QueryInterface(unk_src, &IID_IImageList,
3531  (void **) &src)))
3532  return E_FAIL;
3533 
3534  if (ImageList_Copy(imgl, dst_index, (HIMAGELIST) src, src_index, flags))
3535  ret = S_OK;
3536  else
3537  ret = E_FAIL;
3538 
3539  IImageList_Release(src);
3540  return ret;
3541 }
3542 
3544  IUnknown *punk2, int i2, int dx, int dy, REFIID riid, void **ppv)
3545 {
3546  HIMAGELIST imgl = impl_from_IImageList2(iface);
3547  IImageList *iml2 = NULL;
3548  HIMAGELIST merged;
3549  HRESULT ret = E_FAIL;
3550 
3551  TRACE("(%p)->(%d %p %d %d %d %s %p)\n", iface, i1, punk2, i2, dx, dy, debugstr_guid(riid), ppv);
3552 
3553  /* TODO: Add test for IID_ImageList2 too */
3554  if (FAILED(IUnknown_QueryInterface(punk2, &IID_IImageList,
3555  (void **) &iml2)))
3556  return E_FAIL;
3557 
3558  merged = ImageList_Merge(imgl, i1, (HIMAGELIST) iml2, i2, dx, dy);
3559 
3560  /* Get the interface for the new image list */
3561  if (merged)
3562  {
3563  ret = HIMAGELIST_QueryInterface(merged, riid, ppv);
3564  ImageList_Destroy(merged);
3565  }
3566 
3567  IImageList_Release(iml2);
3568  return ret;
3569 }
3570 
3572 {
3573  HIMAGELIST imgl = impl_from_IImageList2(iface);
3574  HIMAGELIST clone;
3575  HRESULT ret = E_FAIL;
3576 
3577  TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
3578 
3579  clone = ImageList_Duplicate(imgl);
3580 
3581  /* Get the interface for the new image list */
3582  if (clone)
3583  {
3585  ImageList_Destroy(clone);
3586  }
3587 
3588  return ret;
3589 }
3590 
3592  RECT *prc)
3593 {
3594  HIMAGELIST imgl = impl_from_IImageList2(iface);
3595  IMAGEINFO info;
3596 
3597  if (!prc)
3598  return E_FAIL;
3599 
3600  if (!ImageList_GetImageInfo(imgl, i, &info))
3601  return E_FAIL;
3602 
3603  *prc = info.rcImage;
3604 
3605  return S_OK;
3606 }
3607 
3609  int *cy)
3610 {
3611  HIMAGELIST imgl = impl_from_IImageList2(iface);
3612  return ImageList_GetIconSize(imgl, cx, cy) ? S_OK : E_INVALIDARG;
3613 }
3614 
3616  int cy)
3617 {
3618  HIMAGELIST imgl = impl_from_IImageList2(iface);
3619  return ImageList_SetIconSize(imgl, cx, cy) ? S_OK : E_FAIL;
3620 }
3621 
3623 {
3624  HIMAGELIST imgl = impl_from_IImageList2(iface);
3625  *pi = ImageList_GetImageCount(imgl);
3626  return S_OK;
3627 }
3628 
3630 {
3631  HIMAGELIST imgl = impl_from_IImageList2(iface);
3632  return ImageList_SetImageCount(imgl, count) ? S_OK : E_FAIL;
3633 }
3634 
3636  COLORREF *pclr)
3637 {
3638  HIMAGELIST imgl = impl_from_IImageList2(iface);
3639  *pclr = ImageList_SetBkColor(imgl, clrBk);
3640  return S_OK;
3641 }
3642 
3644 {
3645  HIMAGELIST imgl = impl_from_IImageList2(iface);
3646  *pclr = ImageList_GetBkColor(imgl);
3647  return S_OK;
3648 }
3649 
3651  int dxHotspot, int dyHotspot)
3652 {
3653  HIMAGELIST imgl = impl_from_IImageList2(iface);
3654  return ImageList_BeginDrag(imgl, iTrack, dxHotspot, dyHotspot) ? S_OK : E_FAIL;
3655 }
3656 
3658 {
3660  return S_OK;
3661 }
3662 
3664  int x, int y)
3665 {
3666  return ImageList_DragEnter(hwndLock, x, y) ? S_OK : E_FAIL;
3667 }
3668 
3670 {
3671  return ImageList_DragLeave(hwndLock) ? S_OK : E_FAIL;
3672 }
3673 
3675 {
3676  return ImageList_DragMove(x, y) ? S_OK : E_FAIL;
3677 }
3678 
3680  IUnknown *punk, int iDrag, int dxHotspot, int dyHotspot)
3681 {
3682  IImageList *iml2 = NULL;
3683  BOOL ret;
3684 
3685  if (!punk)
3686  return E_FAIL;
3687 
3688  /* TODO: Add test for IID_ImageList2 too */
3689  if (FAILED(IUnknown_QueryInterface(punk, &IID_IImageList,
3690  (void **) &iml2)))
3691  return E_FAIL;
3692 
3693  ret = ImageList_SetDragCursorImage((HIMAGELIST) iml2, iDrag, dxHotspot,
3694  dyHotspot);
3695 
3696  IImageList_Release(iml2);
3697 
3698  return ret ? S_OK : E_FAIL;
3699 }
3700 
3702 {
3703  return ImageList_DragShowNolock(fShow) ? S_OK : E_FAIL;
3704 }
3705 
3708 {
3709  HRESULT ret = E_FAIL;
3710  HIMAGELIST hNew;
3711 
3712  if (!ppv)
3713  return E_FAIL;
3714 
3715  hNew = ImageList_GetDragImage(ppt, pptHotspot);
3716 
3717  /* Get the interface for the new image list */
3718  if (hNew)
3719  {
3720  IImageList *idrag = (IImageList*)hNew;
3721 
3723  IImageList_Release(idrag);
3724  }
3725 
3726  return ret;
3727 }
3728 
3730  DWORD *dwFlags)
3731 {
3732  FIXME("STUB: %p %d %p\n", iface, i, dwFlags);
3733  return E_NOTIMPL;
3734 }
3735 
3737  int *piIndex)
3738 {
3740  int i;
3741 
3742  if ((iOverlay < 0) || (iOverlay > This->cCurImage))
3743  return E_FAIL;
3744 
3745  for (i = 0; i < MAX_OVERLAYIMAGE; i++)
3746  {
3747  if (This->nOvlIdx[i] == iOverlay)
3748  {
3749  *piIndex = i + 1;
3750  return S_OK;
3751  }
3752  }
3753 
3754  return E_FAIL;
3755 }
3756 
3758 {
3759  FIXME("(%p)->(%d %d): stub\n", iface, cx, cy);
3760  return E_NOTIMPL;
3761 }
3762 
3764 {
3765  FIXME("(%p)->(%d %x %p %p): stub\n", iface, image, flags, cx, cy);
3766  return E_NOTIMPL;
3767 }
3768 
3770 {
3771  FIXME("(%p)->(%d %d %d): stub\n", iface, image, cx, cy);
3772  return E_NOTIMPL;
3773 }
3774 
3776 {
3777  FIXME("(%p)->(%p): stub\n", iface, callback);
3778  return E_NOTIMPL;
3779 }
3780 
3782 {
3783  FIXME("(%p)->(%s %p): stub\n", iface, debugstr_guid(riid), ppv);
3784  return E_NOTIMPL;
3785 }
3786 
3788 {
3789  FIXME("(%p)->(%d %x): stub\n", iface, image, flags);
3790  return E_NOTIMPL;
3791 }
3792 
3793 static HRESULT WINAPI ImageListImpl_DiscardImages(IImageList2 *iface, INT first_image, INT last_image, DWORD flags)
3794 {
3795  FIXME("(%p)->(%d %d %x): stub\n", iface, first_image, last_image, flags);
3796  return E_NOTIMPL;
3797 }
3798 
3800 {
3801  FIXME("(%p)->(%p): stub\n", iface, params);
3802  return E_NOTIMPL;
3803 }
3804 
3805 static HRESULT WINAPI ImageListImpl_GetStatistics(IImageList2 *iface, IMAGELISTSTATS *stats)
3806 {
3807  FIXME("(%p)->(%p): stub\n", iface, stats);
3808  return E_NOTIMPL;
3809 }
3810 
3812 {
3813  FIXME("(%p)->(%d %d %d %d %d): stub\n", iface, cx, cy, flags, initial, grow);
3814  return E_NOTIMPL;
3815 }
3816 
3818 {
3819  FIXME("(%p)->(%d %p %p %p %x): stub\n", iface, i, image, mask, unk, flags);
3820  return E_NOTIMPL;
3821 }
3822 
3824  IUnknown *unk, DWORD flags)
3825 {
3826  FIXME("(%p)->(%d %p %d %p %x): stub\n", iface, i, imagelist, src, unk, flags);
3827  return E_NOTIMPL;
3828 }
3829 
3830 static const IImageList2Vtbl ImageListImpl_Vtbl = {
3875 };
3876 
3878 {
3879  BOOL valid;
3880  __TRY
3881  {
3882  valid = himl && himl->IImageList2_iface.lpVtbl == &ImageListImpl_Vtbl;
3883  }
3885  {
3886  valid = FALSE;
3887  }
3888  __ENDTRY
3889  return valid;
3890 }
3891 
3892 /*************************************************************************
3893  * HIMAGELIST_QueryInterface [COMCTL32.@]
3894  *
3895  * Returns a pointer to an IImageList or IImageList2 object for the given
3896  * HIMAGELIST.
3897  *
3898  * PARAMS
3899  * himl [I] Image list handle.
3900  * riid [I] Identifier of the requested interface.
3901  * ppv [O] Returns the address of the pointer requested, or NULL.
3902  *
3903  * RETURNS
3904  * Success: S_OK.
3905  * Failure: Error value.
3906  */
3909 {
3910  TRACE("(%p,%s,%p)\n", himl, debugstr_guid(riid), ppv);
3911  return IImageList2_QueryInterface((IImageList2 *) himl, riid, ppv);
3912 }
3913 
3914 static HRESULT ImageListImpl_CreateInstance(const IUnknown *pUnkOuter, REFIID iid, void** ppv)
3915 {
3916  HIMAGELIST This;
3917  HRESULT ret;
3918 
3919  TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
3920 
3921  *ppv = NULL;
3922 
3923  if (pUnkOuter) return CLASS_E_NOAGGREGATION;
3924 
3925  This = heap_alloc_zero(sizeof(struct _IMAGELIST));
3926  if (!This) return E_OUTOFMEMORY;
3927 
3928  This->IImageList2_iface.lpVtbl = &ImageListImpl_Vtbl;
3929  This->ref = 1;
3930 
3931  ret = IImageList2_QueryInterface(&This->IImageList2_iface, iid, ppv);
3932  IImageList2_Release(&This->IImageList2_iface);
3933 
3934  return ret;
3935 }
#define SRCPAINT
Definition: wingdi.h:333
HGDIOBJ WINAPI GetStockObject(_In_ int)
DWORD WINAPI ImageList_GetFlags(HIMAGELIST himl)
Definition: imagelist.c:1843
BOOL WINAPI ImageList_GetImageRect(HIMAGELIST himl, INT i, LPRECT lpRect)
Definition: imagelist.c:2033
INT WINAPI ImageList_GetImageCount(HIMAGELIST himl)
Definition: imagelist.c:1967
#define ILCF_SWAP
Definition: commctrl.h:496
GLenum func
Definition: glext.h:6028
INT WINAPI ImageList_ReplaceIcon(HIMAGELIST himl, INT nIndex, HICON hIcon)
Definition: imagelist.c:2677
#define abs(i)
Definition: fconv.c:206
#define ILS_ALPHA
Definition: commctrl.h:424
#define ILC_COLOR16
Definition: commctrl.h:341
int WINAPI StretchDIBits(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_opt_ const VOID *, _In_ const BITMAPINFO *, _In_ UINT, _In_ DWORD)
static HRESULT WINAPI ImageListImpl_Replace2(IImageList2 *iface, INT i, HBITMAP image, HBITMAP mask, IUnknown *unk, DWORD flags)
Definition: imagelist.c:3817
#define BITSPIXEL
Definition: wingdi.h:719
HBITMAP hbmImage
GLint GLint GLsizei width
Definition: gl.h:1546
COLORREF WINAPI GetBkColor(_In_ HDC)
Definition: dc.c:954
HDC WINAPI GetDCEx(_In_opt_ HWND, _In_opt_ HRGN, _In_ DWORD)
#define max(a, b)
Definition: svc.c:63
static HRESULT WINAPI ImageListImpl_AddMasked(IImageList2 *iface, HBITMAP hbmImage, COLORREF crMask, int *pi)
Definition: imagelist.c:3452
static HICON
Definition: imagelist.c:84
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define TRUE
Definition: types.h:120
BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heightDst, HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc, BLENDFUNCTION blendFunction)
#define ILS_SHADOW
Definition: commctrl.h:422
#define COLOR_HIGHLIGHT
Definition: winuser.h:916
#define E_NOINTERFACE
Definition: winerror.h:2364
#define IMAGE_ICON
Definition: winuser.h:212
static HRESULT WINAPI ImageListImpl_BeginDrag(IImageList2 *iface, int iTrack, int dxHotspot, int dyHotspot)
Definition: imagelist.c:3650
static void imagelist_point_from_index(HIMAGELIST himl, UINT index, LPPOINT pt)
Definition: imagelist.c:151
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1454
long y
Definition: polytest.cpp:48
COLORREF WINAPI ImageList_SetBkColor(HIMAGELIST himl, COLORREF clrBk)
Definition: imagelist.c:2787
BOOL WINAPI ImageList_Write(HIMAGELIST himl, IStream *pstm)
Definition: imagelist.c:3181
INT WINAPI ImageList_Add(HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
Definition: imagelist.c:413
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
DWORD biClrImportant
Definition: amvideo.idl:40
#define DI_MASK
Definition: wingdi.h:71
long x
Definition: polytest.cpp:48
HRESULT WINAPI ImageList_CoCreateInstance(REFCLSID rclsid, const IUnknown *punkOuter, REFIID riid, void **ppv)
Definition: imagelist.c:3324
HDC WINAPI GetDC(_In_opt_ HWND)
HBITMAP WINAPI CreateCompatibleBitmap(_In_ HDC hdc, _In_ INT cx, _In_ INT cy)
COLORREF WINAPI GetNearestColor(_In_ HDC, _In_ COLORREF)
BOOL WINAPI DestroyIcon(_In_ HICON)
Definition: cursoricon.c:2022
HDC hdcBitmap
Definition: solcreate.cpp:11
#define pt(x, y)
Definition: drawing.c:79
REFIID riid
Definition: precomp.h:44
#define ILS_SATURATE
Definition: commctrl.h:423
static HRESULT WINAPI ImageListImpl_SetImageCount(IImageList2 *iface, UINT count)
Definition: imagelist.c:3629
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
static BOOL is_valid(HIMAGELIST himl)
Definition: imagelist.c:3877
#define REFCLSID
Definition: guiddef.h:112
INT cMaxImage
Definition: imagelist.c:58
DWORD yHotspot
Definition: winuser.h:3078
LONG biXPelsPerMeter
Definition: amvideo.idl:37
#define CP_ACP
Definition: compat.h:99
struct tagBITMAPINFOHEADER BITMAPINFOHEADER
GLuint GLuint GLsizei count
Definition: gl.h:1545
INT nOvlIdx[MAX_OVERLAYIMAGE]
Definition: imagelist.c:72
GLint dy
Definition: linetemp.h:97
#define IMAGE_CURSOR
Definition: winuser.h:213
HIMAGELIST WINAPI ImageList_LoadImageA(HINSTANCE hi, LPCSTR lpbmp, INT cx, INT cGrow, COLORREF clrMask, UINT uType, UINT uFlags)
Definition: imagelist.c:2062
static HRESULT WINAPI ImageListImpl_ReplaceIcon(IImageList2 *iface, int i, HICON hicon, int *pi)
Definition: imagelist.c:3420
#define WARN(fmt,...)
Definition: debug.h:111
BOOL WINAPI ImageList_DragMove(INT x, INT y)
Definition: imagelist.c:1035
HBITMAP hbmBg
Definition: imagelist.c:119
static INTERNALDRAG InternalDrag
Definition: imagelist.c:122
static HDC
Definition: imagelist.c:92
static HRESULT WINAPI ImageListImpl_Initialize(IImageList2 *iface, INT cx, INT cy, UINT flags, INT initial, INT grow)
Definition: imagelist.c:3811
#define GetRValue(rgb)
Definition: wingdi.h:2913
REFIID LPVOID * ppv
Definition: atlbase.h:39
GLdouble n
Definition: glext.h:7729
LONG top
Definition: windef.h:292
SHORT ovls[4]
Definition: imagelist.c:100
static HRESULT WINAPI ImageListImpl_GetImageCount(IImageList2 *iface, int *pi)
Definition: imagelist.c:3622
HRESULT WINAPI HIMAGELIST_QueryInterface(HIMAGELIST himl, REFIID riid, void **ppv)
Definition: imagelist.c:3908
static HRESULT WINAPI ImageListImpl_ForceImagePresent(IImageList2 *iface, INT image, DWORD flags)
Definition: imagelist.c:3787
DWORD x4
Definition: imagelist.c:62
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1497
#define ILS_GLOW
Definition: commctrl.h:421
WORD cy
Definition: imagelist.c:97
#define ZeroMemory
Definition: winbase.h:1635
BOOL WINAPI DeleteObject(_In_ HGDIOBJ)
GLuint buffer
Definition: glext.h:5915
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
char * has_alpha
Definition: imagelist.c:79
GLuint GLuint end
Definition: gl.h:1545
static HRESULT WINAPI ImageListImpl_GetOverlayImage(IImageList2 *iface, int iOverlay, int *piIndex)
Definition: imagelist.c:3736
BOOL WINAPI ImageList_Draw(HIMAGELIST himl, INT i, HDC hdc, INT x, INT y, UINT fStyle)
Definition: imagelist.c:1193
WORD cx
Definition: imagelist.c:96
LONG left
Definition: windef.h:291
UINT uFlags
Definition: api.c:60
static HDC hdcSrc
Definition: xlate.c:32
static HRESULT WINAPI ImageListImpl_Add(IImageList2 *iface, HBITMAP hbmImage, HBITMAP hbmMask, int *pi)
Definition: imagelist.c:3402
#define AC_SRC_ALPHA
Definition: alphablend.c:9
DWORD GetPixel(LPDIRECTDRAWSURFACE7 Surface, UINT x, UINT y)
Definition: blt.cpp:2
static HRESULT WINAPI ImageListImpl_Clone(IImageList2 *iface, REFIID riid, void **ppv)
Definition: imagelist.c:3571
static UINT imagelist_height(UINT count)
Definition: imagelist.c:146
static void * read_bitmap(IStream *pstm, BITMAPINFO *bmi)
Definition: imagelist.c:2285
UINT flags
Definition: imagelist.c:63
LONG right
Definition: windef.h:293
struct _ILHEAD ILHEAD
LONG biYPelsPerMeter
Definition: amvideo.idl:38
VOID WINAPI ImageList_EndDrag(void)
Definition: imagelist.c:1756
#define E_FAIL
Definition: ddrawi.h:102
HIMAGELIST himl
static VOID NTAPI BitBlt(IN ULONG Left, IN ULONG Top, IN ULONG Width, IN ULONG Height, IN PUCHAR Buffer, IN ULONG BitsPerPixel, IN ULONG Delta)
Definition: vga.c:416
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: glext.h:10929
UINT uBitsPixel
Definition: imagelist.c:78
int32_t INT
Definition: typedefs.h:56
BOOL WINAPI GetIconInfo(_In_ HICON, _Out_ PICONINFO)
Definition: cursoricon.c:2014
Definition: send.c:47
WORD flags
Definition: imagelist.c:99
DWORD WINAPI GetSysColor(_In_ int)
BOOL WINAPI StretchBlt(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_opt_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ DWORD)
#define ILD_BLEND25
Definition: commctrl.h:407
static HIMAGELIST impl_from_IImageList2(IImageList2 *iface)
Definition: imagelist.c:124
#define TILE_COUNT
Definition: imagelist.c:144
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
static HRESULT WINAPI ImageListImpl_DiscardImages(IImageList2 *iface, INT first_image, INT last_image, DWORD flags)
Definition: imagelist.c:3793
#define ILC_COLOR4
Definition: commctrl.h:339
#define DCX_WINDOW
Definition: winuser.h:2074
BOOL WINAPI ImageList_DragShowNolock(BOOL bShow)
Definition: imagelist.c:1118
HBITMAP hbmImage
Definition: imagelist.c:68
static const IUnknown REFIID
Definition: imagelist.c:72
BOOL WINAPI ImageList_Destroy(HIMAGELIST himl)
Definition: imagelist.c:893
struct _test_info info[]
Definition: SetCursorPos.c:19
#define ILC_COLOR32
Definition: commctrl.h:343
static HRESULT WINAPI ImageListImpl_SetIconSize(IImageList2 *iface, int cx, int cy)
Definition: imagelist.c:3615
static int get_dib_image_size(const BITMAPINFO *info)
Definition: imagelist.c:168
COLORREF WINAPI SetBkColor(_In_ HDC, _In_ COLORREF)
Definition: dc.c:975
#define GetGValue(rgb)
Definition: wingdi.h:2914
BOOL WINAPI PatBlt(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ DWORD)
static HRESULT WINAPI ImageListImpl_Copy(IImageList2 *iface, int dst_index, IUnknown *unk_src, int src_index, UINT flags)
Definition: imagelist.c:3519
BOOL WINAPI ImageList_GetImageInfo(HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
Definition: imagelist.c:1992
static void imagelist_get_bitmap_size(HIMAGELIST himl, UINT count, SIZE *sz)
Definition: imagelist.c:157
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
BOOL WINAPI ImageList_DragEnter(HWND hwndLock, INT x, INT y)
Definition: imagelist.c:923
static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT count)
Definition: imagelist.c:3224
GLenum GLint GLuint mask
Definition: glext.h:6028
COLORREF bkcolor
Definition: imagelist.c:98
HIMAGELIST WINAPI ImageList_Create(INT cx, INT cy, UINT flags, INT cInitial, INT cGrow)
Definition: imagelist.c:769
unsigned char * LPBYTE
Definition: typedefs.h:52
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
GLenum const GLfloat * params
Definition: glext.h:5645
unsigned int BOOL
Definition: ntddk_ex.h:94