ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

imagelist.c
Go to the documentation of this file.
00001 /*
00002  *  ImageList implementation
00003  *
00004  *  Copyright 1998 Eric Kohl
00005  *  Copyright 2000 Jason Mawdsley
00006  *  Copyright 2001, 2004 Michael Stefaniuc
00007  *  Copyright 2001 Charles Loep for CodeWeavers
00008  *  Copyright 2002 Dimitrie O. Paun
00009  *  Copyright 2009 Owen Rudge for CodeWeavers
00010  *
00011  * This library is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU Lesser General Public
00013  * License as published by the Free Software Foundation; either
00014  * version 2.1 of the License, or (at your option) any later version.
00015  *
00016  * This library is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  * Lesser General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with this library; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00024  *
00025  * NOTE
00026  *
00027  * This code was audited for completeness against the documented features
00028  * of Comctl32.dll version 6.0 on Sep. 12, 2002, by Dimitrie O. Paun.
00029  *
00030  * Unless otherwise noted, we believe this code to be complete, as per
00031  * the specification mentioned above.
00032  * If you discover missing features, or bugs, please note them below.
00033  *
00034  *  TODO:
00035  *    - Add support for ILD_PRESERVEALPHA, ILD_SCALE, ILD_DPISCALE
00036  *    - Add support for ILS_GLOW, ILS_SHADOW, ILS_SATURATE
00037  *    - Thread-safe locking
00038  */
00039 
00040 #include <stdarg.h>
00041 #include <stdlib.h>
00042 #include <string.h>
00043 
00044 #define COBJMACROS
00045 
00046 #include "winerror.h"
00047 #include "windef.h"
00048 #include "winbase.h"
00049 #include "objbase.h"
00050 #include "wingdi.h"
00051 #include "winuser.h"
00052 #include "commctrl.h"
00053 #include "comctl32.h"
00054 #include "commoncontrols.h"
00055 #include "wine/debug.h"
00056 #include "wine/exception.h"
00057 
00058 WINE_DEFAULT_DEBUG_CHANNEL(imagelist);
00059 
00060 #define MAX_OVERLAYIMAGE 15
00061 
00062 struct _IMAGELIST
00063 {
00064     const struct IImageListVtbl *lpVtbl; /* 00: IImageList vtable */
00065 
00066     INT         cCurImage;                 /* 04: ImageCount */
00067     INT         cMaxImage;                 /* 08: maximages */
00068     INT         cGrow;                     /* 0C: cGrow */
00069     INT         cx;                        /* 10: cx */
00070     INT         cy;                        /* 14: cy */
00071     DWORD       x4;
00072     UINT        flags;                     /* 1C: flags */
00073     COLORREF    clrFg;                     /* 20: foreground color */
00074     COLORREF    clrBk;                     /* 24: background color */
00075 
00076 
00077     HBITMAP     hbmImage;                  /* 28: images Bitmap */
00078     HBITMAP     hbmMask;                   /* 2C: masks  Bitmap */
00079     HDC         hdcImage;                  /* 30: images MemDC  */
00080     HDC         hdcMask;                   /* 34: masks  MemDC  */
00081     INT         nOvlIdx[MAX_OVERLAYIMAGE]; /* 38: overlay images index */
00082 
00083     /* not yet found out */
00084     HBRUSH  hbrBlend25;
00085     HBRUSH  hbrBlend50;
00086     INT     cInitial;
00087     UINT    uBitsPixel;
00088     char   *has_alpha;
00089 
00090     LONG        ref;                       /* reference count */
00091 };
00092 
00093 #define IMAGELIST_MAGIC 0x53414D58
00094 
00095 /* Header used by ImageList_Read() and ImageList_Write() */
00096 #include "pshpack2.h"
00097 typedef struct _ILHEAD
00098 {
00099     USHORT  usMagic;
00100     USHORT  usVersion;
00101     WORD    cCurImage;
00102     WORD    cMaxImage;
00103     WORD    cGrow;
00104     WORD    cx;
00105     WORD    cy;
00106     COLORREF    bkcolor;
00107     WORD    flags;
00108     SHORT   ovls[4];
00109 } ILHEAD;
00110 #include "poppack.h"
00111 
00112 /* internal image list data used for Drag & Drop operations */
00113 typedef struct
00114 {
00115     HWND    hwnd;
00116     HIMAGELIST  himl;
00117     /* position of the drag image relative to the window */
00118     INT     x;
00119     INT     y;
00120     /* offset of the hotspot relative to the origin of the image */
00121     INT     dxHotspot;
00122     INT     dyHotspot;
00123     /* is the drag image visible */
00124     BOOL    bShow;
00125     /* saved background */
00126     HBITMAP hbmBg;
00127 } INTERNALDRAG;
00128 
00129 static INTERNALDRAG InternalDrag = { 0, 0, 0, 0, 0, 0, FALSE, 0 };
00130 
00131 static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT count);
00132 static HRESULT ImageListImpl_CreateInstance(const IUnknown *pUnkOuter, REFIID iid, void** ppv);
00133 static inline BOOL is_valid(HIMAGELIST himl);
00134 
00135 /*
00136  * An imagelist with N images is tiled like this:
00137  *
00138  *   N/4 ->
00139  *
00140  * 4 048C..
00141  *   159D..
00142  * | 26AE.N
00143  * V 37BF.
00144  */
00145 
00146 #define TILE_COUNT 4
00147 
00148 static inline UINT imagelist_height( UINT count )
00149 {
00150     return ((count + TILE_COUNT - 1)/TILE_COUNT);
00151 }
00152 
00153 static inline void imagelist_point_from_index( HIMAGELIST himl, UINT index, LPPOINT pt )
00154 {
00155     pt->x = (index%TILE_COUNT) * himl->cx;
00156     pt->y = (index/TILE_COUNT) * himl->cy;
00157 }
00158 
00159 static inline void imagelist_get_bitmap_size( HIMAGELIST himl, UINT count, SIZE *sz )
00160 {
00161     sz->cx = himl->cx * TILE_COUNT;
00162     sz->cy = imagelist_height( count ) * himl->cy;
00163 }
00164 
00165 static inline int get_dib_stride( int width, int bpp )
00166 {
00167     return ((width * bpp + 31) >> 3) & ~3;
00168 }
00169 
00170 static inline int get_dib_image_size( const BITMAPINFO *info )
00171 {
00172     return get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount )
00173         * abs( info->bmiHeader.biHeight );
00174 }
00175 
00176 /*
00177  * imagelist_copy_images()
00178  *
00179  * Copies a block of count images from offset src in the list to offset dest.
00180  * Images are copied a row at at time. Assumes hdcSrc and hdcDest are different.
00181  */
00182 static inline void imagelist_copy_images( HIMAGELIST himl, HDC hdcSrc, HDC hdcDest,
00183                                           UINT src, UINT count, UINT dest )
00184 {
00185     POINT ptSrc, ptDest;
00186     SIZE sz;
00187     UINT i;
00188 
00189     for ( i=0; i<TILE_COUNT; i++ )
00190     {
00191         imagelist_point_from_index( himl, src+i, &ptSrc );
00192         imagelist_point_from_index( himl, dest+i, &ptDest );
00193         sz.cx = himl->cx;
00194         sz.cy = himl->cy * imagelist_height( count - i );
00195 
00196         BitBlt( hdcDest, ptDest.x, ptDest.y, sz.cx, sz.cy,
00197                 hdcSrc, ptSrc.x, ptSrc.y, SRCCOPY );
00198     }
00199 }
00200 
00201 static void add_dib_bits( HIMAGELIST himl, int pos, int count, int width, int height,
00202                           BITMAPINFO *info, BITMAPINFO *mask_info, DWORD *bits, BYTE *mask_bits )
00203 {
00204     int i, j, n;
00205     POINT pt;
00206     int stride = info->bmiHeader.biWidth;
00207     int mask_stride = (info->bmiHeader.biWidth + 31) / 32 * 4;
00208 
00209     for (n = 0; n < count; n++)
00210     {
00211         int has_alpha = 0;
00212 
00213         imagelist_point_from_index( himl, pos + n, &pt );
00214 
00215         /* check if bitmap has an alpha channel */
00216         for (i = 0; i < height && !has_alpha; i++)
00217             for (j = n * width; j < (n + 1) * width; j++)
00218                 if ((has_alpha = ((bits[i * stride + j] & 0xff000000) != 0))) break;
00219 
00220         if (!has_alpha)  /* generate alpha channel from the mask */
00221         {
00222             for (i = 0; i < height; i++)
00223                 for (j = n * width; j < (n + 1) * width; j++)
00224                     if (!mask_info || !((mask_bits[i * mask_stride + j / 8] << (j % 8)) & 0x80))
00225                         bits[i * stride + j] |= 0xff000000;
00226                     else
00227                         bits[i * stride + j] = 0;
00228         }
00229         else
00230         {
00231             himl->has_alpha[pos + n] = 1;
00232 
00233             if (mask_info && himl->hbmMask)  /* generate the mask from the alpha channel */
00234             {
00235                 for (i = 0; i < height; i++)
00236                     for (j = n * width; j < (n + 1) * width; j++)
00237                         if ((bits[i * stride + j] >> 24) > 25) /* more than 10% alpha */
00238                             mask_bits[i * mask_stride + j / 8] &= ~(0x80 >> (j % 8));
00239                         else
00240                             mask_bits[i * mask_stride + j / 8] |= 0x80 >> (j % 8);
00241             }
00242         }
00243         StretchDIBits( himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy,
00244                        n * width, 0, width, height, bits, info, DIB_RGB_COLORS, SRCCOPY );
00245         if (mask_info)
00246             StretchDIBits( himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy,
00247                            n * width, 0, width, height, mask_bits, mask_info, DIB_RGB_COLORS, SRCCOPY );
00248     }
00249 }
00250 
00251 /* add images with an alpha channel when the image list is 32 bpp */
00252 static BOOL add_with_alpha( HIMAGELIST himl, HDC hdc, int pos, int count,
00253                             int width, int height, HBITMAP hbmImage, HBITMAP hbmMask )
00254 {
00255     BOOL ret = FALSE;
00256     BITMAP bm;
00257     BITMAPINFO *info, *mask_info = NULL;
00258     DWORD *bits = NULL;
00259     BYTE *mask_bits = NULL;
00260     DWORD mask_width;
00261 
00262     if (!GetObjectW( hbmImage, sizeof(bm), &bm )) return FALSE;
00263 
00264     /* if either the imagelist or the source bitmap don't have an alpha channel, bail out now */
00265     if (!himl->has_alpha) return FALSE;
00266     if (bm.bmBitsPixel != 32) return FALSE;
00267 
00268     SelectObject( hdc, hbmImage );
00269     mask_width = (bm.bmWidth + 31) / 32 * 4;
00270 
00271     if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto done;
00272     info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
00273     info->bmiHeader.biWidth = bm.bmWidth;
00274     info->bmiHeader.biHeight = -height;
00275     info->bmiHeader.biPlanes = 1;
00276     info->bmiHeader.biBitCount = 32;
00277     info->bmiHeader.biCompression = BI_RGB;
00278     info->bmiHeader.biSizeImage = bm.bmWidth * height * 4;
00279     info->bmiHeader.biXPelsPerMeter = 0;
00280     info->bmiHeader.biYPelsPerMeter = 0;
00281     info->bmiHeader.biClrUsed = 0;
00282     info->bmiHeader.biClrImportant = 0;
00283     if (!(bits = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage ))) goto done;
00284     if (!GetDIBits( hdc, hbmImage, 0, height, bits, info, DIB_RGB_COLORS )) goto done;
00285 
00286     if (hbmMask)
00287     {
00288         if (!(mask_info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[2] ))))
00289             goto done;
00290         mask_info->bmiHeader = info->bmiHeader;
00291         mask_info->bmiHeader.biBitCount = 1;
00292         mask_info->bmiHeader.biSizeImage = mask_width * height;
00293         if (!(mask_bits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, info->bmiHeader.biSizeImage )))
00294             goto done;
00295         if (!GetDIBits( hdc, hbmMask, 0, height, mask_bits, mask_info, DIB_RGB_COLORS )) goto done;
00296     }
00297 
00298     add_dib_bits( himl, pos, count, width, height, info, mask_info, bits, mask_bits );
00299     ret = TRUE;
00300 
00301 done:
00302     HeapFree( GetProcessHeap(), 0, info );
00303     HeapFree( GetProcessHeap(), 0, mask_info );
00304     HeapFree( GetProcessHeap(), 0, bits );
00305     HeapFree( GetProcessHeap(), 0, mask_bits );
00306     return ret;
00307 }
00308 
00309 /*************************************************************************
00310  * IMAGELIST_InternalExpandBitmaps [Internal]
00311  *
00312  * Expands the bitmaps of an image list by the given number of images.
00313  *
00314  * PARAMS
00315  *     himl        [I] handle to image list
00316  *     nImageCount [I] number of images to add
00317  *
00318  * RETURNS
00319  *     nothing
00320  *
00321  * NOTES
00322  *     This function CANNOT be used to reduce the number of images.
00323  */
00324 static void
00325 IMAGELIST_InternalExpandBitmaps(HIMAGELIST himl, INT nImageCount)
00326 {
00327     HDC     hdcBitmap;
00328     HBITMAP hbmNewBitmap, hbmNull;
00329     INT     nNewCount;
00330     SIZE    sz;
00331 
00332     TRACE("%p has allocated %d, max %d, grow %d images\n", himl, himl->cCurImage, himl->cMaxImage, himl->cGrow);
00333 
00334     if (himl->cCurImage + nImageCount < himl->cMaxImage)
00335         return;
00336 
00337     nNewCount = himl->cMaxImage + max(nImageCount, himl->cGrow) + 1;
00338 
00339     imagelist_get_bitmap_size(himl, nNewCount, &sz);
00340 
00341     TRACE("Create expanded bitmaps : himl=%p x=%d y=%d count=%d\n", himl, sz.cx, sz.cy, nNewCount);
00342     hdcBitmap = CreateCompatibleDC (0);
00343 
00344     hbmNewBitmap = ImageList_CreateImage(hdcBitmap, himl, nNewCount);
00345 
00346     if (hbmNewBitmap == 0)
00347         ERR("creating new image bitmap (x=%d y=%d)!\n", sz.cx, sz.cy);
00348 
00349     if (himl->cCurImage)
00350     {
00351         hbmNull = SelectObject (hdcBitmap, hbmNewBitmap);
00352         BitBlt (hdcBitmap, 0, 0, sz.cx, sz.cy,
00353                 himl->hdcImage, 0, 0, SRCCOPY);
00354         SelectObject (hdcBitmap, hbmNull);
00355     }
00356     SelectObject (himl->hdcImage, hbmNewBitmap);
00357     DeleteObject (himl->hbmImage);
00358     himl->hbmImage = hbmNewBitmap;
00359 
00360     if (himl->flags & ILC_MASK)
00361     {
00362         hbmNewBitmap = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
00363 
00364         if (hbmNewBitmap == 0)
00365             ERR("creating new mask bitmap!\n");
00366 
00367     if(himl->cCurImage)
00368     {
00369         hbmNull = SelectObject (hdcBitmap, hbmNewBitmap);
00370         BitBlt (hdcBitmap, 0, 0, sz.cx, sz.cy,
00371             himl->hdcMask, 0, 0, SRCCOPY);
00372         SelectObject (hdcBitmap, hbmNull);
00373     }
00374         SelectObject (himl->hdcMask, hbmNewBitmap);
00375         DeleteObject (himl->hbmMask);
00376         himl->hbmMask = hbmNewBitmap;
00377     }
00378 
00379     if (himl->has_alpha)
00380     {
00381         char *new_alpha = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, himl->has_alpha, nNewCount );
00382         if (new_alpha) himl->has_alpha = new_alpha;
00383         else
00384         {
00385             HeapFree( GetProcessHeap(), 0, himl->has_alpha );
00386             himl->has_alpha = NULL;
00387         }
00388     }
00389 
00390     himl->cMaxImage = nNewCount;
00391 
00392     DeleteDC (hdcBitmap);
00393 }
00394 
00395 
00396 /*************************************************************************
00397  * ImageList_Add [COMCTL32.@]
00398  *
00399  * Add an image or images to an image list.
00400  *
00401  * PARAMS
00402  *     himl     [I] handle to image list
00403  *     hbmImage [I] handle to image bitmap
00404  *     hbmMask  [I] handle to mask bitmap
00405  *
00406  * RETURNS
00407  *     Success: Index of the first new image.
00408  *     Failure: -1
00409  */
00410 
00411 INT WINAPI
00412 ImageList_Add (HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
00413 {
00414     HDC     hdcBitmap, hdcTemp = 0;
00415     INT     nFirstIndex, nImageCount, i;
00416     BITMAP  bmp;
00417     POINT   pt;
00418 
00419     TRACE("himl=%p hbmimage=%p hbmmask=%p\n", himl, hbmImage, hbmMask);
00420     if (!is_valid(himl))
00421         return -1;
00422 
00423     if (!GetObjectW(hbmImage, sizeof(BITMAP), &bmp))
00424         return -1;
00425 
00426     TRACE("himl %p, cCurImage %d, cMaxImage %d, cGrow %d, cx %d, cy %d\n",
00427           himl, himl->cCurImage, himl->cMaxImage, himl->cGrow, himl->cx, himl->cy);
00428 
00429     nImageCount = bmp.bmWidth / himl->cx;
00430 
00431     TRACE("%p has %d images (%d x %d)\n", hbmImage, nImageCount, bmp.bmWidth, bmp.bmHeight);
00432 
00433     IMAGELIST_InternalExpandBitmaps(himl, nImageCount);
00434 
00435     hdcBitmap = CreateCompatibleDC(0);
00436 
00437     SelectObject(hdcBitmap, hbmImage);
00438 
00439     if (add_with_alpha( himl, hdcBitmap, himl->cCurImage, nImageCount,
00440                         himl->cx, min( himl->cy, bmp.bmHeight), hbmImage, hbmMask ))
00441         goto done;
00442 
00443     if (himl->hbmMask)
00444     {
00445         hdcTemp = CreateCompatibleDC(0);
00446         SelectObject(hdcTemp, hbmMask);
00447     }
00448 
00449     for (i=0; i<nImageCount; i++)
00450     {
00451         imagelist_point_from_index( himl, himl->cCurImage + i, &pt );
00452 
00453         /* Copy result to the imagelist
00454         */
00455         BitBlt( himl->hdcImage, pt.x, pt.y, himl->cx, bmp.bmHeight,
00456                 hdcBitmap, i*himl->cx, 0, SRCCOPY );
00457 
00458         if (!himl->hbmMask)
00459              continue;
00460 
00461         BitBlt( himl->hdcMask, pt.x, pt.y, himl->cx, bmp.bmHeight,
00462                 hdcTemp, i*himl->cx, 0, SRCCOPY );
00463 
00464         /* Remove the background from the image
00465         */
00466         BitBlt( himl->hdcImage, pt.x, pt.y, himl->cx, bmp.bmHeight,
00467                 himl->hdcMask, pt.x, pt.y, 0x220326 ); /* NOTSRCAND */
00468     }
00469     if (hdcTemp) DeleteDC(hdcTemp);
00470 
00471 done:
00472     DeleteDC(hdcBitmap);
00473 
00474     nFirstIndex = himl->cCurImage;
00475     himl->cCurImage += nImageCount;
00476 
00477     return nFirstIndex;
00478 }
00479 
00480 
00481 /*************************************************************************
00482  * ImageList_AddIcon [COMCTL32.@]
00483  *
00484  * Adds an icon to an image list.
00485  *
00486  * PARAMS
00487  *     himl  [I] handle to image list
00488  *     hIcon [I] handle to icon
00489  *
00490  * RETURNS
00491  *     Success: index of the new image
00492  *     Failure: -1
00493  */
00494 #undef ImageList_AddIcon
00495 INT WINAPI ImageList_AddIcon (HIMAGELIST himl, HICON hIcon)
00496 {
00497     return ImageList_ReplaceIcon (himl, -1, hIcon);
00498 }
00499 
00500 
00501 /*************************************************************************
00502  * ImageList_AddMasked [COMCTL32.@]
00503  *
00504  * Adds an image or images to an image list and creates a mask from the
00505  * specified bitmap using the mask color.
00506  *
00507  * PARAMS
00508  *     himl    [I] handle to image list.
00509  *     hBitmap [I] handle to bitmap
00510  *     clrMask [I] mask color.
00511  *
00512  * RETURNS
00513  *     Success: Index of the first new image.
00514  *     Failure: -1
00515  */
00516 
00517 INT WINAPI
00518 ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
00519 {
00520     HDC    hdcMask, hdcBitmap;
00521     INT    ret;
00522     BITMAP bmp;
00523     HBITMAP hMaskBitmap;
00524     COLORREF bkColor;
00525 
00526     TRACE("himl=%p hbitmap=%p clrmask=%x\n", himl, hBitmap, clrMask);
00527     if (!is_valid(himl))
00528         return -1;
00529 
00530     if (!GetObjectW(hBitmap, sizeof(BITMAP), &bmp))
00531         return -1;
00532 
00533     hdcBitmap = CreateCompatibleDC(0);
00534     SelectObject(hdcBitmap, hBitmap);
00535 
00536     /* Create a temp Mask so we can remove the background of the Image */
00537     hdcMask = CreateCompatibleDC(0);
00538     hMaskBitmap = CreateBitmap(bmp.bmWidth, bmp.bmHeight, 1, 1, NULL);
00539     SelectObject(hdcMask, hMaskBitmap);
00540 
00541     /* create monochrome image to the mask bitmap */
00542     bkColor = (clrMask != CLR_DEFAULT) ? clrMask : GetPixel (hdcBitmap, 0, 0);
00543     SetBkColor (hdcBitmap, bkColor);
00544     BitBlt (hdcMask, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcBitmap, 0, 0, SRCCOPY);
00545 
00546     /*
00547      * Remove the background from the image
00548      *
00549      * WINDOWS BUG ALERT!!!!!!
00550      *  The statement below should not be done in common practice
00551      *  but this is how ImageList_AddMasked works in Windows.
00552      *  It overwrites the original bitmap passed, this was discovered
00553      *  by using the same bitmap to iterate the different styles
00554      *  on windows where it failed (BUT ImageList_Add is OK)
00555      *  This is here in case some apps rely on this bug
00556      *
00557      *  Blt mode 0x220326 is NOTSRCAND
00558      */
00559     if (bmp.bmBitsPixel > 8)  /* NOTSRCAND can't work with palettes */
00560     {
00561         SetBkColor(hdcBitmap, RGB(255,255,255));
00562         BitBlt(hdcBitmap, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcMask, 0, 0, 0x220326);
00563     }
00564 
00565     DeleteDC(hdcBitmap);
00566     DeleteDC(hdcMask);
00567 
00568     ret = ImageList_Add( himl, hBitmap, hMaskBitmap );
00569 
00570     DeleteObject(hMaskBitmap);
00571     return ret;
00572 }
00573 
00574 
00575 /*************************************************************************
00576  * ImageList_BeginDrag [COMCTL32.@]
00577  *
00578  * Creates a temporary image list that contains one image. It will be used
00579  * as a drag image.
00580  *
00581  * PARAMS
00582  *     himlTrack [I] handle to the source image list
00583  *     iTrack    [I] index of the drag image in the source image list
00584  *     dxHotspot [I] X position of the hot spot of the drag image
00585  *     dyHotspot [I] Y position of the hot spot of the drag image
00586  *
00587  * RETURNS
00588  *     Success: TRUE
00589  *     Failure: FALSE
00590  */
00591 
00592 BOOL WINAPI
00593 ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
00594                  INT dxHotspot, INT dyHotspot)
00595 {
00596     INT cx, cy;
00597 
00598     TRACE("(himlTrack=%p iTrack=%d dx=%d dy=%d)\n", himlTrack, iTrack,
00599       dxHotspot, dyHotspot);
00600 
00601     if (!is_valid(himlTrack))
00602     return FALSE;
00603 
00604     if (InternalDrag.himl)
00605         ImageList_EndDrag ();
00606 
00607     cx = himlTrack->cx;
00608     cy = himlTrack->cy;
00609 
00610     InternalDrag.himl = ImageList_Create (cx, cy, himlTrack->flags, 1, 1);
00611     if (InternalDrag.himl == NULL) {
00612         WARN("Error creating drag image list!\n");
00613         return FALSE;
00614     }
00615 
00616     InternalDrag.dxHotspot = dxHotspot;
00617     InternalDrag.dyHotspot = dyHotspot;
00618 
00619     /* copy image */
00620     BitBlt (InternalDrag.himl->hdcImage, 0, 0, cx, cy, himlTrack->hdcImage, iTrack * cx, 0, SRCCOPY);
00621 
00622     /* copy mask */
00623     BitBlt (InternalDrag.himl->hdcMask, 0, 0, cx, cy, himlTrack->hdcMask, iTrack * cx, 0, SRCCOPY);
00624 
00625     InternalDrag.himl->cCurImage = 1;
00626 
00627     return TRUE;
00628 }
00629 
00630 
00631 /*************************************************************************
00632  * ImageList_Copy [COMCTL32.@]
00633  *
00634  *  Copies an image of the source image list to an image of the
00635  *  destination image list. Images can be copied or swapped.
00636  *
00637  * PARAMS
00638  *     himlDst [I] handle to the destination image list
00639  *     iDst    [I] destination image index.
00640  *     himlSrc [I] handle to the source image list
00641  *     iSrc    [I] source image index
00642  *     uFlags  [I] flags for the copy operation
00643  *
00644  * RETURNS
00645  *     Success: TRUE
00646  *     Failure: FALSE
00647  *
00648  * NOTES
00649  *     Copying from one image list to another is possible. The original
00650  *     implementation just copies or swaps within one image list.
00651  *     Could this feature become a bug??? ;-)
00652  */
00653 
00654 BOOL WINAPI
00655 ImageList_Copy (HIMAGELIST himlDst, INT iDst,   HIMAGELIST himlSrc,
00656         INT iSrc, UINT uFlags)
00657 {
00658     POINT ptSrc, ptDst;
00659 
00660     TRACE("himlDst=%p iDst=%d himlSrc=%p iSrc=%d\n", himlDst, iDst, himlSrc, iSrc);
00661 
00662     if (!is_valid(himlSrc) || !is_valid(himlDst))
00663     return FALSE;
00664     if ((iDst < 0) || (iDst >= himlDst->cCurImage))
00665     return FALSE;
00666     if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage))
00667     return FALSE;
00668 
00669     imagelist_point_from_index( himlDst, iDst, &ptDst );
00670     imagelist_point_from_index( himlSrc, iSrc, &ptSrc );
00671 
00672     if (uFlags & ILCF_SWAP) {
00673         /* swap */
00674         HDC     hdcBmp;
00675         HBITMAP hbmTempImage, hbmTempMask;
00676 
00677         hdcBmp = CreateCompatibleDC (0);
00678 
00679         /* create temporary bitmaps */
00680         hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
00681                                        himlSrc->uBitsPixel, NULL);
00682         hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
00683                       1, NULL);
00684 
00685         /* copy (and stretch) destination to temporary bitmaps.(save) */
00686         /* image */
00687         SelectObject (hdcBmp, hbmTempImage);
00688         StretchBlt   (hdcBmp, 0, 0, himlSrc->cx, himlSrc->cy,
00689                       himlDst->hdcImage, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
00690                       SRCCOPY);
00691         /* mask */
00692         SelectObject (hdcBmp, hbmTempMask);
00693         StretchBlt   (hdcBmp, 0, 0, himlSrc->cx, himlSrc->cy,
00694                       himlDst->hdcMask, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
00695                       SRCCOPY);
00696 
00697         /* copy (and stretch) source to destination */
00698         /* image */
00699         StretchBlt   (himlDst->hdcImage, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
00700                       himlSrc->hdcImage, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
00701                       SRCCOPY);
00702         /* mask */
00703         StretchBlt   (himlDst->hdcMask, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
00704                       himlSrc->hdcMask, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
00705                       SRCCOPY);
00706 
00707         /* copy (without stretching) temporary bitmaps to source (restore) */
00708         /* mask */
00709         BitBlt       (himlSrc->hdcMask, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
00710                       hdcBmp, 0, 0, SRCCOPY);
00711 
00712         /* image */
00713         BitBlt       (himlSrc->hdcImage, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
00714                       hdcBmp, 0, 0, SRCCOPY);
00715         /* delete temporary bitmaps */
00716         DeleteObject (hbmTempMask);
00717         DeleteObject (hbmTempImage);
00718         DeleteDC(hdcBmp);
00719     }
00720     else {
00721         /* copy image */
00722         StretchBlt   (himlDst->hdcImage, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
00723                       himlSrc->hdcImage, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
00724                       SRCCOPY);
00725 
00726         /* copy mask */
00727         StretchBlt   (himlDst->hdcMask, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
00728                       himlSrc->hdcMask, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
00729                       SRCCOPY);
00730     }
00731 
00732     return TRUE;
00733 }
00734 
00735 
00736 /*************************************************************************
00737  * ImageList_Create [COMCTL32.@]
00738  *
00739  * Creates a new image list.
00740  *
00741  * PARAMS
00742  *     cx       [I] image height
00743  *     cy       [I] image width
00744  *     flags    [I] creation flags
00745  *     cInitial [I] initial number of images in the image list
00746  *     cGrow    [I] number of images by which image list grows
00747  *
00748  * RETURNS
00749  *     Success: Handle to the created image list
00750  *     Failure: NULL
00751  */
00752 HIMAGELIST WINAPI
00753 ImageList_Create (INT cx, INT cy, UINT flags,
00754           INT cInitial, INT cGrow)
00755 {
00756     HIMAGELIST himl;
00757     INT      nCount;
00758     HBITMAP  hbmTemp;
00759     UINT     ilc = (flags & 0xFE);
00760     static const WORD aBitBlend25[] =
00761         {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00};
00762 
00763     static const WORD aBitBlend50[] =
00764         {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
00765 
00766     TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow);
00767 
00768     if (cx <= 0 || cy <= 0) return NULL;
00769 
00770     /* Create the IImageList interface for the image list */
00771     if (FAILED(ImageListImpl_CreateInstance(NULL, &IID_IImageList, (void **)&himl)))
00772         return NULL;
00773 
00774     cGrow = (WORD)((max( cGrow, 1 ) + 3) & ~3);
00775 
00776     if (cGrow > 256)
00777     {
00778         /* Windows doesn't limit the size here, but X11 doesn't let us allocate such huge bitmaps */
00779         WARN( "grow %d too large, limiting to 256\n", cGrow );
00780         cGrow = 256;
00781     }
00782 
00783     himl->cx        = cx;
00784     himl->cy        = cy;
00785     himl->flags     = flags;
00786     himl->cMaxImage = cInitial + 1;
00787     himl->cInitial  = cInitial;
00788     himl->cGrow     = cGrow;
00789     himl->clrFg     = CLR_DEFAULT;
00790     himl->clrBk     = CLR_NONE;
00791 
00792     /* initialize overlay mask indices */
00793     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
00794         himl->nOvlIdx[nCount] = -1;
00795 
00796     /* Create Image & Mask DCs */
00797     himl->hdcImage = CreateCompatibleDC (0);
00798     if (!himl->hdcImage)
00799         goto cleanup;
00800     if (himl->flags & ILC_MASK){
00801         himl->hdcMask = CreateCompatibleDC(0);
00802         if (!himl->hdcMask)
00803             goto cleanup;
00804     }
00805 
00806     /* Default to ILC_COLOR4 if none of the ILC_COLOR* flags are specified */
00807     if (ilc == ILC_COLOR)
00808     {
00809         ilc = ILC_COLOR4;
00810         himl->flags |= ILC_COLOR4;
00811     }
00812 
00813     if (ilc >= ILC_COLOR4 && ilc <= ILC_COLOR32)
00814         himl->uBitsPixel = ilc;
00815     else
00816         himl->uBitsPixel = (UINT)GetDeviceCaps (himl->hdcImage, BITSPIXEL);
00817 
00818     if (himl->cMaxImage > 0) {
00819         himl->hbmImage = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage);
00820     SelectObject(himl->hdcImage, himl->hbmImage);
00821     } else
00822         himl->hbmImage = 0;
00823 
00824     if ((himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) {
00825         SIZE sz;
00826 
00827         imagelist_get_bitmap_size(himl, himl->cMaxImage, &sz);
00828         himl->hbmMask = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
00829         if (himl->hbmMask == 0) {
00830             ERR("Error creating mask bitmap!\n");
00831             goto cleanup;
00832         }
00833         SelectObject(himl->hdcMask, himl->hbmMask);
00834     }
00835     else
00836         himl->hbmMask = 0;
00837 
00838     if (ilc == ILC_COLOR32)
00839         himl->has_alpha = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, himl->cMaxImage );
00840     else
00841         himl->has_alpha = NULL;
00842 
00843     /* create blending brushes */
00844     hbmTemp = CreateBitmap (8, 8, 1, 1, aBitBlend25);
00845     himl->hbrBlend25 = CreatePatternBrush (hbmTemp);
00846     DeleteObject (hbmTemp);
00847 
00848     hbmTemp = CreateBitmap (8, 8, 1, 1, aBitBlend50);
00849     himl->hbrBlend50 = CreatePatternBrush (hbmTemp);
00850     DeleteObject (hbmTemp);
00851 
00852     TRACE("created imagelist %p\n", himl);
00853     return himl;
00854 
00855 cleanup:
00856     ImageList_Destroy(himl);
00857     return NULL;
00858 }
00859 
00860 
00861 /*************************************************************************
00862  * ImageList_Destroy [COMCTL32.@]
00863  *
00864  * Destroys an image list.
00865  *
00866  * PARAMS
00867  *     himl [I] handle to image list
00868  *
00869  * RETURNS
00870  *     Success: TRUE
00871  *     Failure: FALSE
00872  */
00873 
00874 BOOL WINAPI
00875 ImageList_Destroy (HIMAGELIST himl)
00876 {
00877     if (!is_valid(himl))
00878     return FALSE;
00879 
00880     IImageList_Release((IImageList *) himl);
00881     return TRUE;
00882 }
00883 
00884 
00885 /*************************************************************************
00886  * ImageList_DragEnter [COMCTL32.@]
00887  *
00888  * Locks window update and displays the drag image at the given position.
00889  *
00890  * PARAMS
00891  *     hwndLock [I] handle of the window that owns the drag image.
00892  *     x        [I] X position of the drag image.
00893  *     y        [I] Y position of the drag image.
00894  *
00895  * RETURNS
00896  *     Success: TRUE
00897  *     Failure: FALSE
00898  *
00899  * NOTES
00900  *     The position of the drag image is relative to the window, not
00901  *     the client area.
00902  */
00903 
00904 BOOL WINAPI
00905 ImageList_DragEnter (HWND hwndLock, INT x, INT y)
00906 {
00907     TRACE("(hwnd=%p x=%d y=%d)\n", hwndLock, x, y);
00908 
00909     if (!is_valid(InternalDrag.himl))
00910     return FALSE;
00911 
00912     if (hwndLock)
00913     InternalDrag.hwnd = hwndLock;
00914     else
00915     InternalDrag.hwnd = GetDesktopWindow ();
00916 
00917     InternalDrag.x = x;
00918     InternalDrag.y = y;
00919 
00920     /* draw the drag image and save the background */
00921     if (!ImageList_DragShowNolock(TRUE)) {
00922     return FALSE;
00923     }
00924 
00925     return TRUE;
00926 }
00927 
00928 
00929 /*************************************************************************
00930  * ImageList_DragLeave [COMCTL32.@]
00931  *
00932  * Unlocks window update and hides the drag image.
00933  *
00934  * PARAMS
00935  *     hwndLock [I] handle of the window that owns the drag image.
00936  *
00937  * RETURNS
00938  *     Success: TRUE
00939  *     Failure: FALSE
00940  */
00941 
00942 BOOL WINAPI
00943 ImageList_DragLeave (HWND hwndLock)
00944 {
00945     /* As we don't save drag info in the window this can lead to problems if
00946        an app does not supply the same window as DragEnter */
00947     /* if (hwndLock)
00948     InternalDrag.hwnd = hwndLock;
00949     else
00950     InternalDrag.hwnd = GetDesktopWindow (); */
00951     if(!hwndLock)
00952     hwndLock = GetDesktopWindow();
00953     if(InternalDrag.hwnd != hwndLock)
00954     FIXME("DragLeave hWnd != DragEnter hWnd\n");
00955 
00956     ImageList_DragShowNolock (FALSE);
00957 
00958     return TRUE;
00959 }
00960 
00961 
00962 /*************************************************************************
00963  * ImageList_InternalDragDraw [Internal]
00964  *
00965  * Draws the drag image.
00966  *
00967  * PARAMS
00968  *     hdc [I] device context to draw into.
00969  *     x   [I] X position of the drag image.
00970  *     y   [I] Y position of the drag image.
00971  *
00972  * RETURNS
00973  *     Success: TRUE
00974  *     Failure: FALSE
00975  *
00976  * NOTES
00977  *     The position of the drag image is relative to the window, not
00978  *     the client area.
00979  *
00980  */
00981 
00982 static inline void
00983 ImageList_InternalDragDraw (HDC hdc, INT x, INT y)
00984 {
00985     IMAGELISTDRAWPARAMS imldp;
00986 
00987     ZeroMemory (&imldp, sizeof(imldp));
00988     imldp.cbSize  = sizeof(imldp);
00989     imldp.himl    = InternalDrag.himl;
00990     imldp.i       = 0;
00991     imldp.hdcDst  = hdc,
00992     imldp.x       = x;
00993     imldp.y       = y;
00994     imldp.rgbBk   = CLR_DEFAULT;
00995     imldp.rgbFg   = CLR_DEFAULT;
00996     imldp.fStyle  = ILD_NORMAL;
00997     imldp.fState  = ILS_ALPHA;
00998     imldp.Frame   = 192;
00999     ImageList_DrawIndirect (&imldp);
01000 }
01001 
01002 /*************************************************************************
01003  * ImageList_DragMove [COMCTL32.@]
01004  *
01005  * Moves the drag image.
01006  *
01007  * PARAMS
01008  *     x [I] X position of the drag image.
01009  *     y [I] Y position of the drag image.
01010  *
01011  * RETURNS
01012  *     Success: TRUE
01013  *     Failure: FALSE
01014  *
01015  * NOTES
01016  *     The position of the drag image is relative to the window, not
01017  *     the client area.
01018  */
01019 
01020 BOOL WINAPI
01021 ImageList_DragMove (INT x, INT y)
01022 {
01023     TRACE("(x=%d y=%d)\n", x, y);
01024 
01025     if (!is_valid(InternalDrag.himl))
01026     return FALSE;
01027 
01028     /* draw/update the drag image */
01029     if (InternalDrag.bShow) {
01030     HDC hdcDrag;
01031     HDC hdcOffScreen;
01032     HDC hdcBg;
01033     HBITMAP hbmOffScreen;
01034     INT origNewX, origNewY;
01035     INT origOldX, origOldY;
01036     INT origRegX, origRegY;
01037     INT sizeRegX, sizeRegY;
01038 
01039 
01040     /* calculate the update region */
01041     origNewX = x - InternalDrag.dxHotspot;
01042     origNewY = y - InternalDrag.dyHotspot;
01043     origOldX = InternalDrag.x - InternalDrag.dxHotspot;
01044     origOldY = InternalDrag.y - InternalDrag.dyHotspot;
01045     origRegX = min(origNewX, origOldX);
01046     origRegY = min(origNewY, origOldY);
01047     sizeRegX = InternalDrag.himl->cx + abs(x - InternalDrag.x);
01048     sizeRegY = InternalDrag.himl->cy + abs(y - InternalDrag.y);
01049 
01050     hdcDrag = GetDCEx(InternalDrag.hwnd, 0,
01051               DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
01052         hdcOffScreen = CreateCompatibleDC(hdcDrag);
01053         hdcBg = CreateCompatibleDC(hdcDrag);
01054 
01055     hbmOffScreen = CreateCompatibleBitmap(hdcDrag, sizeRegX, sizeRegY);
01056     SelectObject(hdcOffScreen, hbmOffScreen);
01057     SelectObject(hdcBg, InternalDrag.hbmBg);
01058 
01059     /* get the actual background of the update region */
01060     BitBlt(hdcOffScreen, 0, 0, sizeRegX, sizeRegY, hdcDrag,
01061            origRegX, origRegY, SRCCOPY);
01062     /* erase the old image */
01063     BitBlt(hdcOffScreen, origOldX - origRegX, origOldY - origRegY,
01064            InternalDrag.himl->cx, InternalDrag.himl->cy, hdcBg, 0, 0,
01065            SRCCOPY);
01066     /* save the background */
01067     BitBlt(hdcBg, 0, 0, InternalDrag.himl->cx, InternalDrag.himl->cy,
01068            hdcOffScreen, origNewX - origRegX, origNewY - origRegY, SRCCOPY);
01069     /* draw the image */
01070     ImageList_InternalDragDraw(hdcOffScreen, origNewX - origRegX, 
01071                    origNewY - origRegY);
01072     /* draw the update region to the screen */
01073     BitBlt(hdcDrag, origRegX, origRegY, sizeRegX, sizeRegY,
01074            hdcOffScreen, 0, 0, SRCCOPY);
01075 
01076     DeleteDC(hdcBg);
01077     DeleteDC(hdcOffScreen);
01078     DeleteObject(hbmOffScreen);
01079     ReleaseDC(InternalDrag.hwnd, hdcDrag);
01080     }
01081 
01082     /* update the image position */
01083     InternalDrag.x = x;
01084     InternalDrag.y = y;
01085 
01086     return TRUE;
01087 }
01088 
01089 
01090 /*************************************************************************
01091  * ImageList_DragShowNolock [COMCTL32.@]
01092  *
01093  * Shows or hides the drag image.
01094  *
01095  * PARAMS
01096  *     bShow [I] TRUE shows the drag image, FALSE hides it.
01097  *
01098  * RETURNS
01099  *     Success: TRUE
01100  *     Failure: FALSE
01101  */
01102 
01103 BOOL WINAPI
01104 ImageList_DragShowNolock (BOOL bShow)
01105 {
01106     HDC hdcDrag;
01107     HDC hdcBg;
01108     INT x, y;
01109 
01110     if (!is_valid(InternalDrag.himl))
01111         return FALSE;
01112     
01113     TRACE("bShow=0x%X!\n", bShow);
01114 
01115     /* DragImage is already visible/hidden */
01116     if ((InternalDrag.bShow && bShow) || (!InternalDrag.bShow && !bShow)) {
01117     return FALSE;
01118     }
01119 
01120     /* position of the origin of the DragImage */
01121     x = InternalDrag.x - InternalDrag.dxHotspot;
01122     y = InternalDrag.y - InternalDrag.dyHotspot;
01123 
01124     hdcDrag = GetDCEx (InternalDrag.hwnd, 0,
01125              DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
01126     if (!hdcDrag) {
01127     return FALSE;
01128     }
01129 
01130     hdcBg = CreateCompatibleDC(hdcDrag);
01131     if (!InternalDrag.hbmBg) {
01132     InternalDrag.hbmBg = CreateCompatibleBitmap(hdcDrag,
01133             InternalDrag.himl->cx, InternalDrag.himl->cy);
01134     }
01135     SelectObject(hdcBg, InternalDrag.hbmBg);
01136 
01137     if (bShow) {
01138     /* save the background */
01139     BitBlt(hdcBg, 0, 0, InternalDrag.himl->cx, InternalDrag.himl->cy,
01140            hdcDrag, x, y, SRCCOPY);
01141     /* show the image */
01142     ImageList_InternalDragDraw(hdcDrag, x, y);
01143     } else {
01144     /* hide the image */
01145     BitBlt(hdcDrag, x, y, InternalDrag.himl->cx, InternalDrag.himl->cy,
01146            hdcBg, 0, 0, SRCCOPY);
01147     }
01148 
01149     InternalDrag.bShow = !InternalDrag.bShow;
01150 
01151     DeleteDC(hdcBg);
01152     ReleaseDC (InternalDrag.hwnd, hdcDrag);
01153     return TRUE;
01154 }
01155 
01156 
01157 /*************************************************************************
01158  * ImageList_Draw [COMCTL32.@]
01159  *
01160  * Draws an image.
01161  *
01162  * PARAMS
01163  *     himl   [I] handle to image list
01164  *     i      [I] image index
01165  *     hdc    [I] handle to device context
01166  *     x      [I] x position
01167  *     y      [I] y position
01168  *     fStyle [I] drawing flags
01169  *
01170  * RETURNS
01171  *     Success: TRUE
01172  *     Failure: FALSE
01173  *
01174  * SEE
01175  *     ImageList_DrawEx.
01176  */
01177 
01178 BOOL WINAPI
01179 ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y, UINT fStyle)
01180 {
01181     return ImageList_DrawEx (himl, i, hdc, x, y, 0, 0, 
01182                      CLR_DEFAULT, CLR_DEFAULT, fStyle);
01183 }
01184 
01185 
01186 /*************************************************************************
01187  * ImageList_DrawEx [COMCTL32.@]
01188  *
01189  * Draws an image and allows to use extended drawing features.
01190  *
01191  * PARAMS
01192  *     himl   [I] handle to image list
01193  *     i      [I] image index
01194  *     hdc    [I] handle to device context
01195  *     x      [I] X position
01196  *     y      [I] Y position
01197  *     dx     [I] X offset
01198  *     dy     [I] Y offset
01199  *     rgbBk  [I] background color
01200  *     rgbFg  [I] foreground color
01201  *     fStyle [I] drawing flags
01202  *
01203  * RETURNS
01204  *     Success: TRUE
01205  *     Failure: FALSE
01206  *
01207  * NOTES
01208  *     Calls ImageList_DrawIndirect.
01209  *
01210  * SEE
01211  *     ImageList_DrawIndirect.
01212  */
01213 
01214 BOOL WINAPI
01215 ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y,
01216           INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg,
01217           UINT fStyle)
01218 {
01219     IMAGELISTDRAWPARAMS imldp;
01220 
01221     ZeroMemory (&imldp, sizeof(imldp));
01222     imldp.cbSize  = sizeof(imldp);
01223     imldp.himl    = himl;
01224     imldp.i       = i;
01225     imldp.hdcDst  = hdc,
01226     imldp.x       = x;
01227     imldp.y       = y;
01228     imldp.cx      = dx;
01229     imldp.cy      = dy;
01230     imldp.rgbBk   = rgbBk;
01231     imldp.rgbFg   = rgbFg;
01232     imldp.fStyle  = fStyle;
01233 
01234     return ImageList_DrawIndirect (&imldp);
01235 }
01236 
01237 
01238 static BOOL alpha_blend_image( HIMAGELIST himl, HDC dest_dc, int dest_x, int dest_y,
01239                                int src_x, int src_y, int cx, int cy, BLENDFUNCTION func,
01240                                UINT style, COLORREF blend_col )
01241 {
01242     BOOL ret = FALSE;
01243     HDC hdc;
01244     HBITMAP bmp = 0, mask = 0;
01245     BITMAPINFO *info;
01246     void *bits, *mask_bits;
01247     unsigned int *ptr;
01248     int i, j;
01249 
01250     if (!(hdc = CreateCompatibleDC( 0 ))) return FALSE;
01251     if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto done;
01252     info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
01253     info->bmiHeader.biWidth = cx;
01254     info->bmiHeader.biHeight = cy;
01255     info->bmiHeader.biPlanes = 1;
01256     info->bmiHeader.biBitCount = 32;
01257     info->bmiHeader.biCompression = BI_RGB;
01258     info->bmiHeader.biSizeImage = cx * cy * 4;
01259     info->bmiHeader.biXPelsPerMeter = 0;
01260     info->bmiHeader.biYPelsPerMeter = 0;
01261     info->bmiHeader.biClrUsed = 0;
01262     info->bmiHeader.biClrImportant = 0;
01263     if (!(bmp = CreateDIBSection( himl->hdcImage, info, DIB_RGB_COLORS, &bits, 0, 0 ))) goto done;
01264     SelectObject( hdc, bmp );
01265     BitBlt( hdc, 0, 0, cx, cy, himl->hdcImage, src_x, src_y, SRCCOPY );
01266 
01267     if (blend_col != CLR_NONE)
01268     {
01269         BYTE r = GetRValue( blend_col );
01270         BYTE g = GetGValue( blend_col );
01271         BYTE b = GetBValue( blend_col );
01272 
01273         if (style & ILD_BLEND25)
01274         {
01275             for (i = 0, ptr = bits; i < cx * cy; i++, ptr++)
01276                 *ptr = ((*ptr & 0xff000000) |
01277                         ((((*ptr & 0x00ff0000) * 3 + (r << 16)) / 4) & 0x00ff0000) |
01278                         ((((*ptr & 0x0000ff00) * 3 + (g << 8))  / 4) & 0x0000ff00) |
01279                         ((((*ptr & 0x000000ff) * 3 + (b << 0))  / 4) & 0x000000ff));
01280         }
01281         else if (style & ILD_BLEND50)
01282         {
01283             for (i = 0, ptr = bits; i < cx * cy; i++, ptr++)
01284                 *ptr = ((*ptr & 0xff000000) |
01285                         ((((*ptr & 0x00ff0000) + (r << 16)) / 2) & 0x00ff0000) |
01286                         ((((*ptr & 0x0000ff00) + (g << 8))  / 2) & 0x0000ff00) |
01287                         ((((*ptr & 0x000000ff) + (b << 0))  / 2) & 0x000000ff));
01288         }
01289     }
01290 
01291     if (himl->has_alpha)  /* we already have an alpha channel in this case */
01292     {
01293         /* pre-multiply by the alpha channel */
01294         for (i = 0, ptr = bits; i < cx * cy; i++, ptr++)
01295         {
01296             DWORD alpha = *ptr >> 24;
01297             *ptr = ((*ptr & 0xff000000) |
01298                     (((*ptr & 0x00ff0000) * alpha / 255) & 0x00ff0000) |
01299                     (((*ptr & 0x0000ff00) * alpha / 255) & 0x0000ff00) |
01300                     (((*ptr & 0x000000ff) * alpha / 255)));
01301         }
01302     }
01303     else if (himl->hbmMask)
01304     {
01305         unsigned int width_bytes = (cx + 31) / 32 * 4;
01306         /* generate alpha channel from the mask */
01307         info->bmiHeader.biBitCount = 1;
01308         info->bmiHeader.biSizeImage = width_bytes * cy;
01309         info->bmiColors[0].rgbRed      = 0;
01310         info->bmiColors[0].rgbGreen    = 0;
01311         info->bmiColors[0].rgbBlue     = 0;
01312         info->bmiColors[0].rgbReserved = 0;
01313         info->bmiColors[1].rgbRed      = 0xff;
01314         info->bmiColors[1].rgbGreen    = 0xff;
01315         info->bmiColors[1].rgbBlue     = 0xff;
01316         info->bmiColors[1].rgbReserved = 0;
01317         if (!(mask = CreateDIBSection( himl->hdcMask, info, DIB_RGB_COLORS, &mask_bits, 0, 0 )))
01318             goto done;
01319         SelectObject( hdc, mask );
01320         BitBlt( hdc, 0, 0, cx, cy, himl->hdcMask, src_x, src_y, SRCCOPY );
01321         SelectObject( hdc, bmp );
01322         for (i = 0, ptr = bits; i < cy; i++)
01323             for (j = 0; j < cx; j++, ptr++)
01324                 if ((((BYTE *)mask_bits)[i * width_bytes + j / 8] << (j % 8)) & 0x80) *ptr = 0;
01325                 else *ptr |= 0xff000000;
01326     }
01327 
01328     ret = GdiAlphaBlend( dest_dc, dest_x, dest_y, cx, cy, hdc, 0, 0, cx, cy, func );
01329 
01330 done:
01331     DeleteDC( hdc );
01332     if (bmp) DeleteObject( bmp );
01333     if (mask) DeleteObject( mask );
01334     HeapFree( GetProcessHeap(), 0, info );
01335     return ret;
01336 }
01337 
01338 /*************************************************************************
01339  * ImageList_DrawIndirect [COMCTL32.@]
01340  *
01341  * Draws an image using various parameters specified in pimldp.
01342  *
01343  * PARAMS
01344  *     pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
01345  *
01346  * RETURNS
01347  *     Success: TRUE
01348  *     Failure: FALSE
01349  */
01350 
01351 BOOL WINAPI
01352 ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
01353 {
01354     INT cx, cy, nOvlIdx;
01355     DWORD fState, dwRop;
01356     UINT fStyle;
01357     COLORREF oldImageBk, oldImageFg;
01358     HDC hImageDC, hImageListDC, hMaskListDC;
01359     HBITMAP hImageBmp, hOldImageBmp, hBlendMaskBmp;
01360     BOOL bIsTransparent, bBlend, bResult = FALSE, bMask;
01361     HIMAGELIST himl;
01362     HBRUSH hOldBrush;
01363     POINT pt;
01364     BOOL has_alpha;
01365 
01366     if (!pimldp || !(himl = pimldp->himl)) return FALSE;
01367     if (!is_valid(himl)) return FALSE;
01368     if ((pimldp->i < 0) || (pimldp->i >= himl->cCurImage)) return FALSE;
01369 
01370     imagelist_point_from_index( himl, pimldp->i, &pt );
01371     pt.x += pimldp->xBitmap;
01372     pt.y += pimldp->yBitmap;
01373 
01374     fState = pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS) ? ILS_NORMAL : pimldp->fState;
01375     fStyle = pimldp->fStyle & ~ILD_OVERLAYMASK;
01376     cx = (pimldp->cx == 0) ? himl->cx : pimldp->cx;
01377     cy = (pimldp->cy == 0) ? himl->cy : pimldp->cy;
01378 
01379     bIsTransparent = (fStyle & ILD_TRANSPARENT);
01380     if( pimldp->rgbBk == CLR_NONE )
01381         bIsTransparent = TRUE;
01382     if( ( pimldp->rgbBk == CLR_DEFAULT ) && ( himl->clrBk == CLR_NONE ) )
01383         bIsTransparent = TRUE;
01384     bMask = (himl->flags & ILC_MASK) && (fStyle & ILD_MASK) ;
01385     bBlend = (fStyle & (ILD_BLEND25 | ILD_BLEND50) ) && !bMask;
01386 
01387     TRACE("himl(%p) hbmMask(%p) iImage(%d) x(%d) y(%d) cx(%d) cy(%d)\n",
01388           himl, himl->hbmMask, pimldp->i, pimldp->x, pimldp->y, cx, cy);
01389 
01390     /* we will use these DCs to access the images and masks in the ImageList */
01391     hImageListDC = himl->hdcImage;
01392     hMaskListDC  = himl->hdcMask;
01393 
01394     /* these will accumulate the image and mask for the image we're drawing */
01395     hImageDC = CreateCompatibleDC( pimldp->hdcDst );
01396     hImageBmp = CreateCompatibleBitmap( pimldp->hdcDst, cx, cy );
01397     hBlendMaskBmp = bBlend ? CreateBitmap(cx, cy, 1, 1, NULL) : 0;
01398 
01399     /* Create a compatible DC. */
01400     if (!hImageListDC || !hImageDC || !hImageBmp ||
01401     (bBlend && !hBlendMaskBmp) || (himl->hbmMask && !hMaskListDC))
01402     goto cleanup;
01403     
01404     hOldImageBmp = SelectObject(hImageDC, hImageBmp);
01405   
01406     /*
01407      * To obtain a transparent look, background color should be set
01408      * to white and foreground color to black when blitting the
01409      * monochrome mask.
01410      */
01411     oldImageFg = SetTextColor( hImageDC, RGB( 0, 0, 0 ) );
01412     oldImageBk = SetBkColor( hImageDC, RGB( 0xff, 0xff, 0xff ) );
01413 
01414     has_alpha = (himl->has_alpha && himl->has_alpha[pimldp->i]);
01415     if (!bMask && (has_alpha || (fState & ILS_ALPHA)))
01416     {
01417         COLORREF colour, blend_col = CLR_NONE;
01418         BLENDFUNCTION func;
01419 
01420         if (bBlend)
01421         {
01422             blend_col = pimldp->rgbFg;
01423             if (blend_col == CLR_DEFAULT) blend_col = GetSysColor( COLOR_HIGHLIGHT );
01424             else if (blend_col == CLR_NONE) blend_col = GetTextColor( pimldp->hdcDst );
01425         }
01426 
01427         func.BlendOp = AC_SRC_OVER;
01428         func.BlendFlags = 0;
01429         func.SourceConstantAlpha = (fState & ILS_ALPHA) ? pimldp->Frame : 255;
01430         func.AlphaFormat = AC_SRC_ALPHA;
01431 
01432         if (bIsTransparent)
01433         {
01434             bResult = alpha_blend_image( himl, pimldp->hdcDst, pimldp->x, pimldp->y,
01435                                          pt.x, pt.y, cx, cy, func, fStyle, blend_col );
01436             goto end;
01437         }
01438         colour = pimldp->rgbBk;
01439         if (colour == CLR_DEFAULT) colour = himl->clrBk;
01440         if (colour == CLR_NONE) colour = GetBkColor( pimldp->hdcDst );
01441 
01442         hOldBrush = SelectObject (hImageDC, CreateSolidBrush (colour));
01443         PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY );
01444         alpha_blend_image( himl, hImageDC, 0, 0, pt.x, pt.y, cx, cy, func, fStyle, blend_col );
01445         DeleteObject (SelectObject (hImageDC, hOldBrush));
01446         bResult = BitBlt( pimldp->hdcDst, pimldp->x,  pimldp->y, cx, cy, hImageDC, 0, 0, SRCCOPY );
01447         goto end;
01448     }
01449 
01450     /*
01451      * Draw the initial image
01452      */
01453     if( bMask ) {
01454     if (himl->hbmMask) {
01455             hOldBrush = SelectObject (hImageDC, CreateSolidBrush (GetTextColor(pimldp->hdcDst)));
01456             PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY );
01457             BitBlt(hImageDC, 0, 0, cx, cy, hMaskListDC, pt.x, pt.y, SRCPAINT);
01458             DeleteObject (SelectObject (hImageDC, hOldBrush));
01459             if( bIsTransparent )
01460             {
01461                 BitBlt ( pimldp->hdcDst, pimldp->x,  pimldp->y, cx, cy, hImageDC, 0, 0, SRCAND);
01462                 bResult = TRUE;
01463                 goto end;
01464             }
01465     } else {
01466         hOldBrush = SelectObject (hImageDC, GetStockObject(BLACK_BRUSH));
01467         PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY);
01468         SelectObject(hImageDC, hOldBrush);
01469     }
01470     } else {
01471     /* blend the image with the needed solid background */
01472         COLORREF colour = RGB(0,0,0);
01473 
01474         if( !bIsTransparent )
01475         {
01476             colour = pimldp->rgbBk;
01477             if( colour == CLR_DEFAULT )
01478                 colour = himl->clrBk;
01479             if( colour == CLR_NONE )
01480                 colour = GetBkColor(pimldp->hdcDst);
01481         }
01482 
01483         hOldBrush = SelectObject (hImageDC, CreateSolidBrush (colour));
01484         PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY );
01485         if (himl->hbmMask)
01486         {
01487             BitBlt( hImageDC, 0, 0, cx, cy, hMaskListDC, pt.x, pt.y, SRCAND );
01488             BitBlt( hImageDC, 0, 0, cx, cy, hImageListDC, pt.x, pt.y, SRCPAINT );
01489         }
01490         else
01491             BitBlt( hImageDC, 0, 0, cx, cy, hImageListDC, pt.x, pt.y, SRCCOPY);
01492         DeleteObject (SelectObject (hImageDC, hOldBrush));
01493     }
01494 
01495     /* Time for blending, if required */
01496     if (bBlend) {
01497     HBRUSH hBlendBrush;
01498         COLORREF clrBlend = pimldp->rgbFg;
01499     HDC hBlendMaskDC = hImageListDC;
01500     HBITMAP hOldBitmap;
01501 
01502     /* Create the blend Mask */
01503         hOldBitmap = SelectObject(hBlendMaskDC, hBlendMaskBmp);
01504     hBlendBrush = fStyle & ILD_BLEND50 ? himl->hbrBlend50 : himl->hbrBlend25;
01505         hOldBrush = SelectObject(hBlendMaskDC, hBlendBrush);
01506         PatBlt(hBlendMaskDC, 0, 0, cx, cy, PATCOPY);
01507         SelectObject(hBlendMaskDC, hOldBrush);
01508 
01509         /* Modify the blend mask if an Image Mask exist */
01510         if(himl->hbmMask) {
01511         BitBlt(hBlendMaskDC, 0, 0, cx, cy, hMaskListDC, pt.x, pt.y, 0x220326); /* NOTSRCAND */
01512         BitBlt(hBlendMaskDC, 0, 0, cx, cy, hBlendMaskDC, 0, 0, NOTSRCCOPY);
01513     }
01514 
01515     /* now apply blend to the current image given the BlendMask */
01516         if (clrBlend == CLR_DEFAULT) clrBlend = GetSysColor (COLOR_HIGHLIGHT);
01517         else if (clrBlend == CLR_NONE) clrBlend = GetTextColor (pimldp->hdcDst);
01518     hOldBrush = SelectObject (hImageDC, CreateSolidBrush(clrBlend));
01519     BitBlt (hImageDC, 0, 0, cx, cy, hBlendMaskDC, 0, 0, 0xB8074A); /* PSDPxax */
01520     DeleteObject(SelectObject(hImageDC, hOldBrush));
01521     SelectObject(hBlendMaskDC, hOldBitmap);
01522     }
01523 
01524     /* Now do the overlay image, if any */
01525     nOvlIdx = (pimldp->fStyle & ILD_OVERLAYMASK) >> 8;
01526     if ( (nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE)) {
01527     nOvlIdx = himl->nOvlIdx[nOvlIdx - 1];
01528     if ((nOvlIdx >= 0) && (nOvlIdx < himl->cCurImage)) {
01529             POINT ptOvl;
01530             imagelist_point_from_index( himl, nOvlIdx, &ptOvl );
01531             ptOvl.x += pimldp->xBitmap;
01532         if (himl->hbmMask && !(fStyle & ILD_IMAGE))
01533         BitBlt (hImageDC, 0, 0, cx, cy, hMaskListDC, ptOvl.x, ptOvl.y, SRCAND);
01534         BitBlt (hImageDC, 0, 0, cx, cy, hImageListDC, ptOvl.x, ptOvl.y, SRCPAINT);
01535     }
01536     }
01537 
01538     if (fState & ILS_SATURATE) FIXME("ILS_SATURATE: unimplemented!\n");
01539     if (fState & ILS_GLOW) FIXME("ILS_GLOW: unimplemented!\n");
01540     if (fState & ILS_SHADOW) FIXME("ILS_SHADOW: unimplemented!\n");
01541 
01542     if (fStyle & ILD_PRESERVEALPHA) FIXME("ILD_PRESERVEALPHA: unimplemented!\n");
01543     if (fStyle & ILD_SCALE) FIXME("ILD_SCALE: unimplemented!\n");
01544     if (fStyle & ILD_DPISCALE) FIXME("ILD_DPISCALE: unimplemented!\n");
01545 
01546     /* now copy the image to the screen */
01547     dwRop = SRCCOPY;
01548     if (himl->hbmMask && bIsTransparent ) {
01549     COLORREF oldDstFg = SetTextColor(pimldp->hdcDst, RGB( 0, 0, 0 ) );
01550     COLORREF oldDstBk = SetBkColor(pimldp->hdcDst, RGB( 0xff, 0xff, 0xff ));
01551         BitBlt (pimldp->hdcDst, pimldp->x,  pimldp->y, cx, cy, hMaskListDC, pt.x, pt.y, SRCAND);
01552     SetBkColor(pimldp->hdcDst, oldDstBk);
01553     SetTextColor(pimldp->hdcDst, oldDstFg);
01554     dwRop = SRCPAINT;
01555     }
01556     if (fStyle & ILD_ROP) dwRop = pimldp->dwRop;
01557     BitBlt (pimldp->hdcDst, pimldp->x,  pimldp->y, cx, cy, hImageDC, 0, 0, dwRop);
01558 
01559     bResult = TRUE;
01560 end:
01561     /* cleanup the mess */
01562     SetBkColor(hImageDC, oldImageBk);
01563     SetTextColor(hImageDC, oldImageFg);
01564     SelectObject(hImageDC, hOldImageBmp);
01565 cleanup:
01566     DeleteObject(hBlendMaskBmp);
01567     DeleteObject(hImageBmp);
01568     DeleteDC(hImageDC);
01569 
01570     return bResult;
01571 }
01572 
01573 
01574 /*************************************************************************
01575  * ImageList_Duplicate [COMCTL32.@]
01576  *
01577  * Duplicates an image list.
01578  *
01579  * PARAMS
01580  *     himlSrc [I] source image list handle
01581  *
01582  * RETURNS
01583  *     Success: Handle of duplicated image list.
01584  *     Failure: NULL
01585  */
01586 
01587 HIMAGELIST WINAPI
01588 ImageList_Duplicate (HIMAGELIST himlSrc)
01589 {
01590     HIMAGELIST himlDst;
01591 
01592     if (!is_valid(himlSrc)) {
01593         ERR("Invalid image list handle!\n");
01594         return NULL;
01595     }
01596 
01597     himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
01598                                 himlSrc->cCurImage, himlSrc->cGrow);
01599 
01600     if (himlDst)
01601     {
01602         SIZE sz;
01603 
01604         imagelist_get_bitmap_size(himlSrc, himlSrc->cCurImage, &sz);
01605         BitBlt (himlDst->hdcImage, 0, 0, sz.cx, sz.cy,
01606                 himlSrc->hdcImage, 0, 0, SRCCOPY);
01607 
01608         if (himlDst->hbmMask)
01609             BitBlt (himlDst->hdcMask, 0, 0, sz.cx, sz.cy,
01610                     himlSrc->hdcMask, 0, 0, SRCCOPY);
01611 
01612     himlDst->cCurImage = himlSrc->cCurImage;
01613         if (himlSrc->has_alpha && himlDst->has_alpha)
01614             memcpy( himlDst->has_alpha, himlSrc->has_alpha, himlDst->cCurImage );
01615     }
01616     return himlDst;
01617 }
01618 
01619 
01620 /*************************************************************************
01621  * ImageList_EndDrag [COMCTL32.@]
01622  *
01623  * Finishes a drag operation.
01624  *
01625  * PARAMS
01626  *     no Parameters
01627  *
01628  * RETURNS
01629  *     Success: TRUE
01630  *     Failure: FALSE
01631  */
01632 
01633 VOID WINAPI
01634 ImageList_EndDrag (void)
01635 {
01636     /* cleanup the InternalDrag struct */
01637     InternalDrag.hwnd = 0;
01638     ImageList_Destroy (InternalDrag.himl);
01639     InternalDrag.himl = 0;
01640     InternalDrag.x= 0;
01641     InternalDrag.y= 0;
01642     InternalDrag.dxHotspot = 0;
01643     InternalDrag.dyHotspot = 0;
01644     InternalDrag.bShow = FALSE;
01645     DeleteObject(InternalDrag.hbmBg);
01646     InternalDrag.hbmBg = 0;
01647 }
01648 
01649 
01650 /*************************************************************************
01651  * ImageList_GetBkColor [COMCTL32.@]
01652  *
01653  * Returns the background color of an image list.
01654  *
01655  * PARAMS
01656  *     himl [I] Image list handle.
01657  *
01658  * RETURNS
01659  *     Success: background color
01660  *     Failure: CLR_NONE
01661  */
01662 
01663 COLORREF WINAPI
01664 ImageList_GetBkColor (HIMAGELIST himl)
01665 {
01666     return himl ? himl->clrBk : CLR_NONE;
01667 }
01668 
01669 
01670 /*************************************************************************
01671  * ImageList_GetDragImage [COMCTL32.@]
01672  *
01673  * Returns the handle to the internal drag image list.
01674  *
01675  * PARAMS
01676  *     ppt        [O] Pointer to the drag position. Can be NULL.
01677  *     pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
01678  *
01679  * RETURNS
01680  *     Success: Handle of the drag image list.
01681  *     Failure: NULL.
01682  */
01683 
01684 HIMAGELIST WINAPI
01685 ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot)
01686 {
01687     if (is_valid(InternalDrag.himl)) {
01688     if (ppt) {
01689         ppt->x = InternalDrag.x;
01690         ppt->y = InternalDrag.y;
01691     }
01692     if (pptHotspot) {
01693         pptHotspot->x = InternalDrag.dxHotspot;
01694         pptHotspot->y = InternalDrag.dyHotspot;
01695     }
01696         return (InternalDrag.himl);
01697     }
01698 
01699     return NULL;
01700 }
01701 
01702 
01703 /*************************************************************************
01704  * ImageList_GetFlags [COMCTL32.@]
01705  *
01706  * Gets the flags of the specified image list.
01707  *
01708  * PARAMS
01709  *     himl [I] Handle to image list
01710  *
01711  * RETURNS
01712  *     Image list flags.
01713  *
01714  * BUGS
01715  *    Stub.
01716  */
01717 
01718 DWORD WINAPI
01719 ImageList_GetFlags(HIMAGELIST himl)
01720 {
01721     TRACE("%p\n", himl);
01722 
01723     return is_valid(himl) ? himl->flags : 0;
01724 }
01725 
01726 
01727 /*************************************************************************
01728  * ImageList_GetIcon [COMCTL32.@]
01729  *
01730  * Creates an icon from a masked image of an image list.
01731  *
01732  * PARAMS
01733  *     himl  [I] handle to image list
01734  *     i     [I] image index
01735  *     flags [I] drawing style flags
01736  *
01737  * RETURNS
01738  *     Success: icon handle
01739  *     Failure: NULL
01740  */
01741 
01742 HICON WINAPI
01743 ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle)
01744 {
01745     ICONINFO ii;
01746     HICON hIcon;
01747     HBITMAP hOldDstBitmap;
01748     HDC hdcDst;
01749     POINT pt;
01750 
01751     TRACE("%p %d %d\n", himl, i, fStyle);
01752     if (!is_valid(himl) || (i < 0) || (i >= himl->cCurImage)) return NULL;
01753 
01754     ii.fIcon = TRUE;
01755     ii.xHotspot = 0;
01756     ii.yHotspot = 0;
01757 
01758     /* create colour bitmap */
01759     hdcDst = GetDC(0);
01760     ii.hbmColor = CreateCompatibleBitmap(hdcDst, himl->cx, himl->cy);
01761     ReleaseDC(0, hdcDst);
01762 
01763     hdcDst = CreateCompatibleDC(0);
01764 
01765     imagelist_point_from_index( himl, i, &pt );
01766 
01767     /* draw mask*/
01768     ii.hbmMask  = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
01769     hOldDstBitmap = SelectObject (hdcDst, ii.hbmMask);
01770     if (himl->hbmMask) {
01771         BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
01772                 himl->hdcMask, pt.x, pt.y, SRCCOPY);
01773     }
01774     else
01775         PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS);
01776 
01777     /* draw image*/
01778     SelectObject (hdcDst, ii.hbmColor);
01779     BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
01780             himl->hdcImage, pt.x, pt.y, SRCCOPY);
01781 
01782     /*
01783      * CreateIconIndirect requires us to deselect the bitmaps from
01784      * the DCs before calling
01785      */
01786     SelectObject(hdcDst, hOldDstBitmap);
01787 
01788     hIcon = CreateIconIndirect (&ii);
01789 
01790     DeleteObject (ii.hbmMask);
01791     DeleteObject (ii.hbmColor);
01792     DeleteDC (hdcDst);
01793 
01794     return hIcon;
01795 }
01796 
01797 
01798 /*************************************************************************
01799  * ImageList_GetIconSize [COMCTL32.@]
01800  *
01801  * Retrieves the size of an image in an image list.
01802  *
01803  * PARAMS
01804  *     himl [I] handle to image list
01805  *     cx   [O] pointer to the image width.
01806  *     cy   [O] pointer to the image height.
01807  *
01808  * RETURNS
01809  *     Success: TRUE
01810  *     Failure: FALSE
01811  *
01812  * NOTES
01813  *     All images in an image list have the same size.
01814  */
01815 
01816 BOOL WINAPI
01817 ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy)
01818 {
01819     if (!is_valid(himl) || !cx || !cy)
01820     return FALSE;
01821     if ((himl->cx <= 0) || (himl->cy <= 0))
01822     return FALSE;
01823 
01824     *cx = himl->cx;
01825     *cy = himl->cy;
01826 
01827     return TRUE;
01828 }
01829 
01830 
01831 /*************************************************************************
01832  * ImageList_GetImageCount [COMCTL32.@]
01833  *
01834  * Returns the number of images in an image list.
01835  *
01836  * PARAMS
01837  *     himl [I] handle to image list
01838  *
01839  * RETURNS
01840  *     Success: Number of images.
01841  *     Failure: 0
01842  */
01843 
01844 INT WINAPI
01845 ImageList_GetImageCount (HIMAGELIST himl)
01846 {
01847     if (!is_valid(himl))
01848     return 0;
01849 
01850     return himl->cCurImage;
01851 }
01852 
01853 
01854 /*************************************************************************
01855  * ImageList_GetImageInfo [COMCTL32.@]
01856  *
01857  * Returns information about an image in an image list.
01858  *
01859  * PARAMS
01860  *     himl       [I] handle to image list
01861  *     i          [I] image index
01862  *     pImageInfo [O] pointer to the image information
01863  *
01864  * RETURNS
01865  *     Success: TRUE
01866  *     Failure: FALSE
01867  */
01868 
01869 BOOL WINAPI
01870 ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
01871 {
01872     POINT pt;
01873 
01874     if (!is_valid(himl) || (pImageInfo == NULL))
01875     return FALSE;
01876     if ((i < 0) || (i >= himl->cCurImage))
01877     return FALSE;
01878 
01879     pImageInfo->hbmImage = himl->hbmImage;
01880     pImageInfo->hbmMask  = himl->hbmMask;
01881 
01882     imagelist_point_from_index( himl, i, &pt );
01883     pImageInfo->rcImage.top    = pt.y;
01884     pImageInfo->rcImage.bottom = pt.y + himl->cy;
01885     pImageInfo->rcImage.left   = pt.x;
01886     pImageInfo->rcImage.right  = pt.x + himl->cx;
01887 
01888     return TRUE;
01889 }
01890 
01891 
01892 /*************************************************************************
01893  * ImageList_GetImageRect [COMCTL32.@]
01894  *
01895  * Retrieves the rectangle of the specified image in an image list.
01896  *
01897  * PARAMS
01898  *     himl   [I] handle to image list
01899  *     i      [I] image index
01900  *     lpRect [O] pointer to the image rectangle
01901  *
01902  * RETURNS
01903  *    Success: TRUE
01904  *    Failure: FALSE
01905  *
01906  * NOTES
01907  *    This is an UNDOCUMENTED function!!!
01908  */
01909 
01910 BOOL WINAPI
01911 ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect)
01912 {
01913     POINT pt;
01914 
01915     if (!is_valid(himl) || (lpRect == NULL))
01916     return FALSE;
01917     if ((i < 0) || (i >= himl->cCurImage))
01918     return FALSE;
01919 
01920     imagelist_point_from_index( himl, i, &pt );
01921     lpRect->left   = pt.x;
01922     lpRect->top    = pt.y;
01923     lpRect->right  = pt.x + himl->cx;
01924     lpRect->bottom = pt.y + himl->cy;
01925 
01926     return TRUE;
01927 }
01928 
01929 
01930 /*************************************************************************
01931  * ImageList_LoadImage  [COMCTL32.@]
01932  * ImageList_LoadImageA [COMCTL32.@]
01933  *
01934  * Creates an image list from a bitmap, icon or cursor.
01935  *
01936  * See ImageList_LoadImageW.
01937  */
01938 
01939 HIMAGELIST WINAPI
01940 ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx, INT cGrow,
01941             COLORREF clrMask, UINT uType, UINT uFlags)
01942 {
01943     HIMAGELIST himl;
01944     LPWSTR lpbmpW;
01945     DWORD len;
01946 
01947     if (IS_INTRESOURCE(lpbmp))
01948         return ImageList_LoadImageW(hi, (LPCWSTR)lpbmp, cx, cGrow, clrMask,
01949                                     uType, uFlags);
01950 
01951     len = MultiByteToWideChar(CP_ACP, 0, lpbmp, -1, NULL, 0);
01952     lpbmpW = Alloc(len * sizeof(WCHAR));
01953     MultiByteToWideChar(CP_ACP, 0, lpbmp, -1, lpbmpW, len);
01954 
01955     himl = ImageList_LoadImageW(hi, lpbmpW, cx, cGrow, clrMask, uType, uFlags);
01956     Free (lpbmpW);
01957     return himl;
01958 }
01959 
01960 
01961 /*************************************************************************
01962  * ImageList_LoadImageW [COMCTL32.@]
01963  *
01964  * Creates an image list from a bitmap, icon or cursor.
01965  *
01966  * PARAMS
01967  *     hi      [I] instance handle
01968  *     lpbmp   [I] name or id of the image
01969  *     cx      [I] width of each image
01970  *     cGrow   [I] number of images to expand
01971  *     clrMask [I] mask color
01972  *     uType   [I] type of image to load
01973  *     uFlags  [I] loading flags
01974  *
01975  * RETURNS
01976  *     Success: handle to the loaded image list
01977  *     Failure: NULL
01978  *
01979  * SEE
01980  *     LoadImage ()
01981  */
01982 
01983 HIMAGELIST WINAPI
01984 ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow,
01985                       COLORREF clrMask, UINT uType, UINT uFlags)
01986 {
01987     HIMAGELIST himl = NULL;
01988     HANDLE   handle;
01989     INT      nImageCount;
01990 
01991     handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags);
01992     if (!handle) {
01993         WARN("Couldn't load image\n");
01994         return NULL;
01995     }
01996 
01997     if (uType == IMAGE_BITMAP) {
01998         DIBSECTION dib;
01999         UINT color;
02000 
02001         if (GetObjectW (handle, sizeof(dib), &dib) == sizeof(BITMAP)) color = ILC_COLOR;
02002         else color = dib.dsBm.bmBitsPixel;
02003 
02004         /* To match windows behavior, if cx is set to zero and
02005          the flag DI_DEFAULTSIZE is specified, cx becomes the
02006          system metric value for icons. If the flag is not specified
02007          the function sets the size to the height of the bitmap */
02008         if (cx == 0)
02009         {
02010             if (uFlags & DI_DEFAULTSIZE)
02011                 cx = GetSystemMetrics (SM_CXICON);
02012             else
02013                 cx = dib.dsBm.bmHeight;
02014         }
02015 
02016         nImageCount = dib.dsBm.bmWidth / cx;
02017 
02018         himl = ImageList_Create (cx, dib.dsBm.bmHeight, ILC_MASK | color, nImageCount, cGrow);
02019         if (!himl) {
02020             DeleteObject (handle);
02021             return NULL;
02022         }
02023         ImageList_AddMasked (himl, handle, clrMask);
02024     }
02025     else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
02026         ICONINFO ii;
02027         BITMAP bmp;
02028 
02029         GetIconInfo (handle, &ii);
02030         GetObjectW (ii.hbmColor, sizeof(BITMAP), &bmp);
02031         himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
02032                                  ILC_MASK | ILC_COLOR, 1, cGrow);
02033         if (!himl) {
02034             DeleteObject (ii.hbmColor);
02035             DeleteObject (ii.hbmMask);
02036             DeleteObject (handle);
02037             return NULL;
02038         }
02039         ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
02040         DeleteObject (ii.hbmColor);
02041         DeleteObject (ii.hbmMask);
02042     }
02043 
02044     DeleteObject (handle);
02045 
02046     return himl;
02047 }
02048 
02049 
02050 /*************************************************************************
02051  * ImageList_Merge [COMCTL32.@]
02052  *
02053  * Create an image list containing a merged image from two image lists.
02054  *
02055  * PARAMS
02056  *     himl1 [I] handle to first image list
02057  *     i1    [I] first image index
02058  *     himl2 [I] handle to second image list
02059  *     i2    [I] second image index
02060  *     dx    [I] X offset of the second image relative to the first.
02061  *     dy    [I] Y offset of the second image relative to the first.
02062  *
02063  * RETURNS
02064  *     Success: The newly created image list. It contains a single image
02065  *              consisting of the second image merged with the first.
02066  *     Failure: NULL, if either himl1 or himl2 are invalid.
02067  *
02068  * NOTES
02069  *   - The returned image list should be deleted by the caller using
02070  *     ImageList_Destroy() when it is no longer required.
02071  *   - If either i1 or i2 are not valid image indices they will be treated
02072  *     as a blank image.
02073  */
02074 HIMAGELIST WINAPI
02075 ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
02076          INT dx, INT dy)
02077 {
02078     HIMAGELIST himlDst = NULL;
02079     INT      cxDst, cyDst;
02080     INT      xOff1, yOff1, xOff2, yOff2;
02081     POINT    pt1, pt2;
02082 
02083     TRACE("(himl1=%p i1=%d himl2=%p i2=%d dx=%d dy=%d)\n", himl1, i1, himl2,
02084        i2, dx, dy);
02085 
02086     if (!is_valid(himl1) || !is_valid(himl2))
02087     return NULL;
02088 
02089     if (dx > 0) {
02090         cxDst = max (himl1->cx, dx + himl2->cx);
02091         xOff1 = 0;
02092         xOff2 = dx;
02093     }
02094     else if (dx < 0) {
02095         cxDst = max (himl2->cx, himl1->cx - dx);
02096         xOff1 = -dx;
02097         xOff2 = 0;
02098     }
02099     else {
02100         cxDst = max (himl1->cx, himl2->cx);
02101         xOff1 = 0;
02102         xOff2 = 0;
02103     }
02104 
02105     if (dy > 0) {
02106         cyDst = max (himl1->cy, dy + himl2->cy);
02107         yOff1 = 0;
02108         yOff2 = dy;
02109     }
02110     else if (dy < 0) {
02111         cyDst = max (himl2->cy, himl1->cy - dy);
02112         yOff1 = -dy;
02113         yOff2 = 0;
02114     }
02115     else {
02116         cyDst = max (himl1->cy, himl2->cy);
02117         yOff1 = 0;
02118         yOff2 = 0;
02119     }
02120 
02121     himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
02122 
02123     if (himlDst)
02124     {
02125         imagelist_point_from_index( himl1, i1, &pt1 );
02126         imagelist_point_from_index( himl2, i2, &pt2 );
02127 
02128         /* copy image */
02129         BitBlt (himlDst->hdcImage, 0, 0, cxDst, cyDst, himl1->hdcImage, 0, 0, BLACKNESS);
02130         if (i1 >= 0 && i1 < himl1->cCurImage)
02131             BitBlt (himlDst->hdcImage, xOff1, yOff1, himl1->cx, himl1->cy, himl1->hdcImage, pt1.x, pt1.y, SRCCOPY);
02132         if (i2 >= 0 && i2 < himl2->cCurImage)
02133         {
02134             BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcMask , pt2.x, pt2.y, SRCAND);
02135             BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcImage, pt2.x, pt2.y, SRCPAINT);
02136         }
02137 
02138         /* copy mask */
02139         BitBlt (himlDst->hdcMask, 0, 0, cxDst, cyDst, himl1->hdcMask, 0, 0, WHITENESS);
02140         if (i1 >= 0 && i1 < himl1->cCurImage)
02141             BitBlt (himlDst->hdcMask,  xOff1, yOff1, himl1->cx, himl1->cy, himl1->hdcMask,  pt1.x, pt1.y, SRCCOPY);
02142         if (i2 >= 0 && i2 < himl2->cCurImage)
02143             BitBlt (himlDst->hdcMask,  xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcMask,  pt2.x, pt2.y, SRCAND);
02144 
02145     himlDst->cCurImage = 1;
02146     }
02147 
02148     return himlDst;
02149 }
02150 
02151 
02152 /* helper for ImageList_Read, see comments below */
02153 static void *read_bitmap(LPSTREAM pstm, BITMAPINFO *bmi)
02154 {
02155     BITMAPFILEHEADER    bmfh;
02156     int bitsperpixel, palspace;
02157     void *bits;
02158 
02159     if (FAILED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL)))
02160         return NULL;
02161 
02162     if (bmfh.bfType != (('M'<<8)|'B'))
02163         return NULL;
02164 
02165     if (FAILED(IStream_Read ( pstm, &bmi->bmiHeader, sizeof(bmi->bmiHeader), NULL)))
02166         return NULL;
02167 
02168     if ((bmi->bmiHeader.biSize != sizeof(bmi->bmiHeader)))
02169         return NULL;
02170 
02171     TRACE("width %u, height %u, planes %u, bpp %u\n",
02172           bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
02173           bmi->bmiHeader.biPlanes, bmi->bmiHeader.biBitCount);
02174 
02175     bitsperpixel = bmi->bmiHeader.biPlanes * bmi->bmiHeader.biBitCount;
02176     if (bitsperpixel<=8)
02177         palspace = (1<<bitsperpixel)*sizeof(RGBQUAD);
02178     else
02179         palspace = 0;
02180 
02181     bmi->bmiHeader.biSizeImage = get_dib_image_size( bmi );
02182 
02183     /* read the palette right after the end of the bitmapinfoheader */
02184     if (palspace && FAILED(IStream_Read(pstm, bmi->bmiColors, palspace, NULL)))
02185         return NULL;
02186 
02187     bits = Alloc(bmi->bmiHeader.biSizeImage);
02188     if (!bits) return NULL;
02189 
02190     if (FAILED(IStream_Read(pstm, bits, bmi->bmiHeader.biSizeImage, NULL)))
02191     {
02192         Free(bits);
02193         return NULL;
02194     }
02195     return bits;
02196 }
02197 
02198 /*************************************************************************
02199  * ImageList_Read [COMCTL32.@]
02200  *
02201  * Reads an image list from a stream.
02202  *
02203  * PARAMS
02204  *     pstm [I] pointer to a stream
02205  *
02206  * RETURNS
02207  *     Success: handle to image list
02208  *     Failure: NULL
02209  *
02210  * The format is like this:
02211  *  ILHEAD          ilheadstruct;
02212  *
02213  * for the color image part:
02214  *  BITMAPFILEHEADER    bmfh;
02215  *  BITMAPINFOHEADER    bmih;
02216  * only if it has a palette:
02217  *  RGBQUAD     rgbs[nr_of_paletted_colors];
02218  *
02219  *  BYTE            colorbits[imagesize];
02220  *
02221  * the following only if the ILC_MASK bit is set in ILHEAD.ilFlags:
02222  *  BITMAPFILEHEADER    bmfh_mask;
02223  *  BITMAPINFOHEADER    bmih_mask;
02224  * only if it has a palette (it usually does not):
02225  *  RGBQUAD     rgbs[nr_of_paletted_colors];
02226  *
02227  *  BYTE            maskbits[imagesize];
02228  */
02229 HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
02230 {
02231     char image_buf[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256];
02232     char mask_buf[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256];
02233     BITMAPINFO *image_info = (BITMAPINFO *)image_buf;
02234     BITMAPINFO *mask_info = (BITMAPINFO *)mask_buf;
02235     void *image_bits, *mask_bits = NULL;
02236     ILHEAD  ilHead;
02237     HIMAGELIST  himl;
02238     int     i;
02239 
02240     TRACE("%p\n", pstm);
02241 
02242     if (FAILED(IStream_Read (pstm, &ilHead, sizeof(ILHEAD), NULL)))
02243     return NULL;
02244     if (ilHead.usMagic != (('L' << 8) | 'I'))
02245     return NULL;
02246     if (ilHead.usVersion != 0x101) /* probably version? */
02247     return NULL;
02248 
02249     TRACE("cx %u, cy %u, flags 0x%04x, cCurImage %u, cMaxImage %u\n",
02250           ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage);
02251 
02252     himl = ImageList_Create(ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage);
02253     if (!himl)
02254     return NULL;
02255 
02256     if (!(image_bits = read_bitmap(pstm, image_info)))
02257     {
02258     WARN("failed to read bitmap from stream\n");
02259     return NULL;
02260     }
02261     if (ilHead.flags & ILC_MASK)
02262     {
02263         if (!(mask_bits = read_bitmap(pstm, mask_info)))
02264         {
02265             WARN("failed to read mask bitmap from stream\n");
02266         return NULL;
02267     }
02268     }
02269     else mask_info = NULL;
02270 
02271     if (himl->has_alpha && image_info->bmiHeader.biBitCount == 32)
02272     {
02273         DWORD *ptr = image_bits;
02274         BYTE *mask_ptr = mask_bits;
02275         int stride = himl->cy * image_info->bmiHeader.biWidth;
02276 
02277         if (image_info->bmiHeader.biHeight > 0)  /* bottom-up */
02278         {
02279             ptr += image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride;
02280             mask_ptr += (image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride) / 8;
02281             stride = -stride;
02282             image_info->bmiHeader.biHeight = himl->cy;
02283         }
02284         else image_info->bmiHeader.biHeight = -himl->cy;
02285 
02286         for (i = 0; i < ilHead.cCurImage; i += TILE_COUNT)
02287         {
02288             add_dib_bits( himl, i, min( ilHead.cCurImage - i, TILE_COUNT ),
02289                           himl->cx, himl->cy, image_info, mask_info, ptr, mask_ptr );
02290             ptr += stride;
02291             mask_ptr += stride / 8;
02292         }
02293     }
02294     else
02295     {
02296         StretchDIBits( himl->hdcImage, 0, 0, image_info->bmiHeader.biWidth, image_info->bmiHeader.biHeight,
02297                        0, 0, image_info->bmiHeader.biWidth, image_info->bmiHeader.biHeight,
02298                        image_bits, image_info, DIB_RGB_COLORS, SRCCOPY);
02299         if (mask_info)
02300             StretchDIBits( himl->hdcMask, 0, 0, mask_info->bmiHeader.biWidth, mask_info->bmiHeader.biHeight,
02301                            0, 0, mask_info->bmiHeader.biWidth, mask_info->bmiHeader.biHeight,
02302                            mask_bits, mask_info, DIB_RGB_COLORS, SRCCOPY);
02303     }
02304     Free( image_bits );
02305     Free( mask_bits );
02306 
02307     himl->cCurImage = ilHead.cCurImage;
02308     himl->cMaxImage = ilHead.cMaxImage;
02309 
02310     ImageList_SetBkColor(himl,ilHead.bkcolor);
02311     for (i=0;i<4;i++)
02312     ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1);
02313     return himl;
02314 }
02315 
02316 
02317 /*************************************************************************
02318  * ImageList_Remove [COMCTL32.@]
02319  *
02320  * Removes an image from an image list
02321  *
02322  * PARAMS
02323  *     himl [I] image list handle
02324  *     i    [I] image index
02325  *
02326  * RETURNS
02327  *     Success: TRUE
02328  *     Failure: FALSE
02329  *
02330  * FIXME: as the image list storage test shows, native comctl32 simply shifts
02331  * images without creating a new bitmap.
02332  */
02333 BOOL WINAPI
02334 ImageList_Remove (HIMAGELIST himl, INT i)
02335 {
02336     HBITMAP hbmNewImage, hbmNewMask;
02337     HDC     hdcBmp;
02338     SIZE    sz;
02339 
02340     TRACE("(himl=%p i=%d)\n", himl, i);
02341 
02342     if (!is_valid(himl)) {
02343         ERR("Invalid image list handle!\n");
02344         return FALSE;
02345     }
02346 
02347     if ((i < -1) || (i >= himl->cCurImage)) {
02348         TRACE("index out of range! %d\n", i);
02349         return FALSE;
02350     }
02351 
02352     if (i == -1) {
02353         INT nCount;
02354 
02355         /* remove all */
02356     if (himl->cCurImage == 0) {
02357         /* remove all on empty ImageList is allowed */
02358         TRACE("remove all on empty ImageList!\n");
02359         return TRUE;
02360     }
02361 
02362         himl->cMaxImage = himl->cGrow;
02363         himl->cCurImage = 0;
02364         for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
02365              himl->nOvlIdx[nCount] = -1;
02366 
02367         hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage);
02368         SelectObject (himl->hdcImage, hbmNewImage);
02369         DeleteObject (himl->hbmImage);
02370         himl->hbmImage = hbmNewImage;
02371 
02372         if (himl->hbmMask) {
02373 
02374             imagelist_get_bitmap_size(himl, himl->cMaxImage, &sz);
02375             hbmNewMask = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
02376             SelectObject (himl->hdcMask, hbmNewMask);
02377             DeleteObject (himl->hbmMask);
02378             himl->hbmMask = hbmNewMask;
02379         }
02380     }
02381     else {
02382         /* delete one image */
02383         TRACE("Remove single image! %d\n", i);
02384 
02385         /* create new bitmap(s) */
02386         TRACE(" - Number of images: %d / %d (Old/New)\n",
02387                  himl->cCurImage, himl->cCurImage - 1);
02388 
02389         hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage);
02390 
02391         imagelist_get_bitmap_size(himl, himl->cMaxImage, &sz );
02392         if (himl->hbmMask)
02393             hbmNewMask = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
02394         else
02395             hbmNewMask = 0;  /* Just to keep compiler happy! */
02396 
02397         hdcBmp = CreateCompatibleDC (0);
02398 
02399         /* copy all images and masks prior to the "removed" image */
02400         if (i > 0) {
02401             TRACE("Pre image copy: Copy %d images\n", i);
02402 
02403             SelectObject (hdcBmp, hbmNewImage);
02404             imagelist_copy_images( himl, himl->hdcImage, hdcBmp, 0, i, 0 );
02405 
02406             if (himl->hbmMask) {
02407                 SelectObject (hdcBmp, hbmNewMask);
02408                 imagelist_copy_images( himl, himl->hdcMask, hdcBmp, 0, i, 0 );
02409             }
02410         }
02411 
02412         /* copy all images and masks behind the removed image */
02413         if (i < himl->cCurImage - 1) {
02414             TRACE("Post image copy!\n");
02415 
02416             SelectObject (hdcBmp, hbmNewImage);
02417             imagelist_copy_images( himl, himl->hdcImage, hdcBmp, i + 1,
02418                                    (himl->cCurImage - i), i );
02419 
02420             if (himl->hbmMask) {
02421                 SelectObject (hdcBmp, hbmNewMask);
02422                 imagelist_copy_images( himl, himl->hdcMask, hdcBmp, i + 1,
02423                                        (himl->cCurImage - i), i );
02424             }
02425         }
02426 
02427         DeleteDC (hdcBmp);
02428 
02429         /* delete old images and insert new ones */
02430         SelectObject (himl->hdcImage, hbmNewImage);
02431         DeleteObject (himl->hbmImage);
02432         himl->hbmImage = hbmNewImage;
02433         if (himl->hbmMask) {
02434             SelectObject (himl->hdcMask, hbmNewMask);
02435             DeleteObject (himl->hbmMask);
02436             himl->hbmMask = hbmNewMask;
02437         }
02438 
02439         himl->cCurImage--;
02440     }
02441 
02442     return TRUE;
02443 }
02444 
02445 
02446 /*************************************************************************
02447  * ImageList_Replace [COMCTL32.@]
02448  *
02449  * Replaces an image in an image list with a new image.
02450  *
02451  * PARAMS
02452  *     himl     [I] handle to image list
02453  *     i        [I] image index
02454  *     hbmImage [I] handle to image bitmap
02455  *     hbmMask  [I] handle to mask bitmap. Can be NULL.
02456  *
02457  * RETURNS
02458  *     Success: TRUE
02459  *     Failure: FALSE
02460  */
02461 
02462 BOOL WINAPI
02463 ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage,
02464            HBITMAP hbmMask)
02465 {
02466     HDC hdcImage;
02467     BITMAP bmp;
02468     POINT pt;
02469 
02470     TRACE("%p %d %p %p\n", himl, i, hbmImage, hbmMask);
02471 
02472     if (!is_valid(himl)) {
02473         ERR("Invalid image list handle!\n");
02474         return FALSE;
02475     }
02476 
02477     if ((i >= himl->cMaxImage) || (i < 0)) {
02478         ERR("Invalid image index!\n");
02479         return FALSE;
02480     }
02481 
02482     if (!GetObjectW(hbmImage, sizeof(BITMAP), &bmp))
02483         return FALSE;
02484 
02485     hdcImage = CreateCompatibleDC (0);
02486 
02487     /* Replace Image */
02488     SelectObject (hdcImage, hbmImage);
02489 
02490     if (add_with_alpha( himl, hdcImage, i, 1, bmp.bmWidth, bmp.bmHeight, hbmImage, hbmMask ))
02491         goto done;
02492 
02493     imagelist_point_from_index(himl, i, &pt);
02494     StretchBlt (himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy,
02495                   hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
02496 
02497     if (himl->hbmMask)
02498     {
02499         HDC hdcTemp;
02500         HBITMAP hOldBitmapTemp;
02501 
02502         hdcTemp   = CreateCompatibleDC(0);
02503         hOldBitmapTemp = SelectObject(hdcTemp, hbmMask);
02504 
02505         StretchBlt (himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy,
02506                       hdcTemp, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
02507         SelectObject(hdcTemp, hOldBitmapTemp);
02508         DeleteDC(hdcTemp);
02509 
02510         /* Remove the background from the image
02511         */
02512         BitBlt (himl->hdcImage, pt.x, pt.y, bmp.bmWidth, bmp.bmHeight,
02513                 himl->hdcMask, pt.x, pt.y, 0x220326); /* NOTSRCAND */
02514     }
02515 
02516 done:
02517     DeleteDC (hdcImage);
02518 
02519     return TRUE;
02520 }
02521 
02522 
02523 /*************************************************************************
02524  * ImageList_ReplaceIcon [COMCTL32.@]
02525  *
02526  * Replaces an image in an image list using an icon.
02527  *
02528  * PARAMS
02529  *     himl  [I] handle to image list
02530  *     i     [I] image index
02531  *     hIcon [I] handle to icon
02532  *
02533  * RETURNS
02534  *     Success: index of the replaced image
02535  *     Failure: -1
02536  */
02537 
02538 INT WINAPI
02539 ImageList_ReplaceIcon (HIMAGELIST himl, INT nIndex, HICON hIcon)
02540 {
02541     HICON   hBestFitIcon;
02542     ICONINFO  ii;
02543     BITMAP  bmp;
02544     BOOL    ret;
02545     POINT   pt;
02546 
02547     TRACE("(%p %d %p)\n", himl, nIndex, hIcon);
02548 
02549     if (!is_valid(himl)) {
02550         ERR("invalid image list\n");
02551         return -1;
02552     }
02553     if ((nIndex >= himl->cMaxImage) || (nIndex < -1)) {
02554         ERR("invalid image index %d / %d\n", nIndex, himl->cMaxImage);
02555         return -1;
02556     }
02557 
02558     hBestFitIcon = CopyImage(
02559         hIcon, IMAGE_ICON,
02560         himl->cx, himl->cy,
02561         LR_COPYFROMRESOURCE);
02562     /* the above will fail if the icon wasn't loaded from a resource, so try
02563      * again without LR_COPYFROMRESOURCE flag */
02564     if (!hBestFitIcon)
02565         hBestFitIcon = CopyImage(
02566             hIcon, IMAGE_ICON,
02567             himl->cx, himl->cy,
02568             0);
02569     if (!hBestFitIcon)
02570         return -1;
02571 
02572     if (nIndex == -1) {
02573         if (himl->cCurImage + 1 >= himl->cMaxImage)
02574             IMAGELIST_InternalExpandBitmaps(himl, 1);
02575 
02576         nIndex = himl->cCurImage;
02577         himl->cCurImage++;
02578     }
02579 
02580     if (himl->has_alpha && GetIconInfo (hBestFitIcon, &ii))
02581     {
02582         HDC hdcImage = CreateCompatibleDC( 0 );
02583         GetObjectW (ii.hbmMask, sizeof(BITMAP), &bmp);
02584 
02585         if (!ii.hbmColor)
02586         {
02587             UINT height = bmp.bmHeight / 2;
02588             HDC hdcMask = CreateCompatibleDC( 0 );
02589             HBITMAP color = CreateBitmap( bmp.bmWidth, height, 1, 1, NULL );
02590             SelectObject( hdcImage, color );
02591             SelectObject( hdcMask, ii.hbmMask );
02592             BitBlt( hdcImage, 0, 0, bmp.bmWidth, height, hdcMask, 0, height, SRCCOPY );
02593             ret = add_with_alpha( himl, hdcImage, nIndex, 1, bmp.bmWidth, height, color, ii.hbmMask );
02594             DeleteDC( hdcMask );
02595             DeleteObject( color );
02596         }
02597         else ret = add_with_alpha( himl, hdcImage, nIndex, 1, bmp.bmWidth, bmp.bmHeight,
02598                                    ii.hbmColor, ii.hbmMask );
02599 
02600         DeleteDC( hdcImage );
02601         DeleteObject (ii.hbmMask);
02602         if (ii.hbmColor) DeleteObject (ii.hbmColor);
02603         if (ret) goto done;
02604     }
02605 
02606     imagelist_point_from_index(himl, nIndex, &pt);
02607 
02608     if (himl->hbmMask)
02609     {
02610         DrawIconEx( himl->hdcImage, pt.x, pt.y, hBestFitIcon, himl->cx, himl->cy, 0, 0, DI_IMAGE );
02611         PatBlt( himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy, WHITENESS );
02612         DrawIconEx( himl->hdcMask, pt.x, pt.y, hBestFitIcon, himl->cx, himl->cy, 0, 0, DI_MASK );
02613     }
02614     else
02615     {
02616         COLORREF color = himl->clrBk != CLR_NONE ? himl->clrBk : comctl32_color.clrWindow;
02617         HBRUSH brush = CreateSolidBrush( GetNearestColor( himl->hdcImage, color ));
02618 
02619         SelectObject( himl->hdcImage, brush );
02620         PatBlt( himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy, PATCOPY );
02621         SelectObject( himl->hdcImage, GetStockObject(BLACK_BRUSH) );
02622         DeleteObject( brush );
02623         DrawIconEx( himl->hdcImage, pt.x, pt.y, hBestFitIcon, himl->cx, himl->cy, 0, 0, DI_NORMAL );
02624     }
02625 
02626 done:
02627     DestroyIcon(hBestFitIcon);
02628 
02629     TRACE("Insert index = %d, himl->cCurImage = %d\n", nIndex, himl->cCurImage);
02630     return nIndex;
02631 }
02632 
02633 
02634 /*************************************************************************
02635  * ImageList_SetBkColor [COMCTL32.@]
02636  *
02637  * Sets the background color of an image list.
02638  *
02639  * PARAMS
02640  *     himl  [I] handle to image list
02641  *     clrBk [I] background color
02642  *
02643  * RETURNS
02644  *     Success: previous background color
02645  *     Failure: CLR_NONE
02646  */
02647 
02648 COLORREF WINAPI
02649 ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
02650 {
02651     COLORREF clrOldBk;
02652 
02653     if (!is_valid(himl))
02654     return CLR_NONE;
02655 
02656     clrOldBk = himl->clrBk;
02657     himl->clrBk = clrBk;
02658     return clrOldBk;
02659 }
02660 
02661 
02662 /*************************************************************************
02663  * ImageList_SetDragCursorImage [COMCTL32.@]
02664  *
02665  * Combines the specified image with the current drag image
02666  *
02667  * PARAMS
02668  *     himlDrag  [I] handle to drag image list
02669  *     iDrag     [I] drag image index
02670  *     dxHotspot [I] X position of the hot spot
02671  *     dyHotspot [I] Y position of the hot spot
02672  *
02673  * RETURNS
02674  *     Success: TRUE
02675  *     Failure: FALSE
02676  *
02677  * NOTES
02678  *   - The names dxHotspot, dyHotspot are misleading because they have nothing
02679  *     to do with a hotspot but are only the offset of the origin of the new
02680  *     image relative to the origin of the old image.
02681  *
02682  *   - When this function is called and the drag image is visible, a
02683  *     short flickering occurs but this matches the Win9x behavior. It is
02684  *     possible to fix the flickering using code like in ImageList_DragMove.
02685  */
02686 
02687 BOOL WINAPI
02688 ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag,
02689                   INT dxHotspot, INT dyHotspot)
02690 {
02691     HIMAGELIST himlTemp;
02692     BOOL visible;
02693 
02694     if (!is_valid(InternalDrag.himl) || !is_valid(himlDrag))
02695     return FALSE;
02696 
02697     TRACE(" dxH=%d dyH=%d nX=%d nY=%d\n",
02698        dxHotspot, dyHotspot, InternalDrag.dxHotspot, InternalDrag.dyHotspot);
02699 
02700     visible = InternalDrag.bShow;
02701 
02702     himlTemp = ImageList_Merge (InternalDrag.himl, 0, himlDrag, iDrag,
02703                                 dxHotspot, dyHotspot);
02704 
02705     if (visible) {
02706     /* hide the drag image */
02707     ImageList_DragShowNolock(FALSE);
02708     }
02709     if ((InternalDrag.himl->cx != himlTemp->cx) ||
02710        (InternalDrag.himl->cy != himlTemp->cy)) {
02711     /* the size of the drag image changed, invalidate the buffer */
02712     DeleteObject(InternalDrag.hbmBg);
02713     InternalDrag.hbmBg = 0;
02714     }
02715 
02716     ImageList_Destroy (InternalDrag.himl);
02717     InternalDrag.himl = himlTemp;
02718 
02719     if (visible) {
02720     /* show the drag image */
02721     ImageList_DragShowNolock(TRUE);
02722     }
02723 
02724     return TRUE;
02725 }
02726 
02727 
02728 /*************************************************************************
02729  * ImageList_SetFilter [COMCTL32.@]
02730  *
02731  * Sets a filter (or does something completely different)!!???
02732  * It removes 12 Bytes from the stack (3 Parameters).
02733  *
02734  * PARAMS
02735  *     himl     [I] SHOULD be a handle to image list
02736  *     i        [I] COULD be an index?
02737  *     dwFilter [I] ???
02738  *
02739  * RETURNS
02740  *     Success: TRUE ???
02741  *     Failure: FALSE ???
02742  *
02743  * BUGS
02744  *     This is an UNDOCUMENTED function!!!!
02745  *     empty stub.
02746  */
02747 
02748 BOOL WINAPI
02749 ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter)
02750 {
02751     FIXME("(%p 0x%x 0x%x):empty stub!\n", himl, i, dwFilter);
02752 
02753     return FALSE;
02754 }
02755 
02756 
02757 /*************************************************************************
02758  * ImageList_SetFlags [COMCTL32.@]
02759  *
02760  * Sets the image list flags.
02761  *
02762  * PARAMS
02763  *     himl  [I] Handle to image list
02764  *     flags [I] Flags to set
02765  *
02766  * RETURNS
02767  *     Old flags?
02768  *
02769  * BUGS
02770  *    Stub.
02771  */
02772 
02773 DWORD WINAPI
02774 ImageList_SetFlags(HIMAGELIST himl, DWORD flags)
02775 {
02776     FIXME("(%p %08x):empty stub\n", himl, flags);
02777     return 0;
02778 }
02779 
02780 
02781 /*************************************************************************
02782  * ImageList_SetIconSize [COMCTL32.@]
02783  *
02784  * Sets the image size of the bitmap and deletes all images.
02785  *
02786  * PARAMS
02787  *     himl [I] handle to image list
02788  *     cx   [I] image width
02789  *     cy   [I] image height
02790  *
02791  * RETURNS
02792  *     Success: TRUE
02793  *     Failure: FALSE
02794  */
02795 
02796 BOOL WINAPI
02797 ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy)
02798 {
02799     INT nCount;
02800     HBITMAP hbmNew;
02801 
02802     if (!is_valid(himl))
02803     return FALSE;
02804 
02805     /* remove all images */
02806     himl->cMaxImage = himl->cInitial + 1;
02807     himl->cCurImage = 0;
02808     himl->cx        = cx;
02809     himl->cy        = cy;
02810 
02811     /* initialize overlay mask indices */
02812     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
02813         himl->nOvlIdx[nCount] = -1;
02814 
02815     hbmNew = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage);
02816     SelectObject (himl->hdcImage, hbmNew);
02817     DeleteObject (himl->hbmImage);
02818     himl->hbmImage = hbmNew;
02819 
02820     if (himl->hbmMask) {
02821         SIZE sz;
02822         imagelist_get_bitmap_size(himl, himl->cMaxImage, &sz);
02823         hbmNew = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
02824         SelectObject (himl->hdcMask, hbmNew);
02825         DeleteObject (himl->hbmMask);
02826         himl->hbmMask = hbmNew;
02827     }
02828 
02829     return TRUE;
02830 }
02831 
02832 
02833 /*************************************************************************
02834  * ImageList_SetImageCount [COMCTL32.@]
02835  *
02836  * Resizes an image list to the specified number of images.
02837  *
02838  * PARAMS
02839  *     himl        [I] handle to image list
02840  *     iImageCount [I] number of images in the image list
02841  *
02842  * RETURNS
02843  *     Success: TRUE
02844  *     Failure: FALSE
02845  */
02846 
02847 BOOL WINAPI
02848 ImageList_SetImageCount (HIMAGELIST himl, UINT iImageCount)
02849 {
02850     HDC     hdcBitmap;
02851     HBITMAP hbmNewBitmap, hbmOld;
02852     INT     nNewCount, nCopyCount;
02853 
02854     TRACE("%p %d\n",himl,iImageCount);
02855 
02856     if (!is_valid(himl))
02857     return FALSE;
02858 
02859     nNewCount = iImageCount + 1;
02860     nCopyCount = min(himl->cCurImage, iImageCount);
02861 
02862     hdcBitmap = CreateCompatibleDC (0);
02863 
02864     hbmNewBitmap = ImageList_CreateImage(hdcBitmap, himl, nNewCount);
02865 
02866     if (hbmNewBitmap != 0)
02867     {
02868         hbmOld = SelectObject (hdcBitmap, hbmNewBitmap);
02869         imagelist_copy_images( himl, himl->hdcImage, hdcBitmap, 0, nCopyCount, 0 );
02870         SelectObject (hdcBitmap, hbmOld);
02871 
02872     /* FIXME: delete 'empty' image space? */
02873 
02874         SelectObject (himl->hdcImage, hbmNewBitmap);
02875     DeleteObject (himl->hbmImage);
02876     himl->hbmImage = hbmNewBitmap;
02877     }
02878     else
02879     ERR("Could not create new image bitmap !\n");
02880 
02881     if (himl->hbmMask)
02882     {
02883         SIZE sz;
02884         imagelist_get_bitmap_size( himl, nNewCount, &sz );
02885         hbmNewBitmap = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
02886         if (hbmNewBitmap != 0)
02887         {
02888             hbmOld = SelectObject (hdcBitmap, hbmNewBitmap);
02889             imagelist_copy_images( himl, himl->hdcMask, hdcBitmap, 0, nCopyCount, 0 );
02890             SelectObject (hdcBitmap, hbmOld);
02891 
02892         /* FIXME: delete 'empty' image space? */
02893 
02894             SelectObject (himl->hdcMask, hbmNewBitmap);
02895             DeleteObject (himl->hbmMask);
02896             himl->hbmMask = hbmNewBitmap;
02897         }
02898         else
02899             ERR("Could not create new mask bitmap!\n");
02900     }
02901 
02902     DeleteDC (hdcBitmap);
02903 
02904     if (himl->has_alpha)
02905     {
02906         char *new_alpha = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, himl->has_alpha, nNewCount );
02907         if (new_alpha) himl->has_alpha = new_alpha;
02908         else
02909         {
02910             HeapFree( GetProcessHeap(), 0, himl->has_alpha );
02911             himl->has_alpha = NULL;
02912         }
02913     }
02914 
02915     /* Update max image count and current image count */
02916     himl->cMaxImage = nNewCount;
02917     himl->cCurImage = iImageCount;
02918 
02919     return TRUE;
02920 }
02921 
02922 
02923 /*************************************************************************
02924  * ImageList_SetOverlayImage [COMCTL32.@]
02925  *
02926  * Assigns an overlay mask index to an existing image in an image list.
02927  *
02928  * PARAMS
02929  *     himl     [I] handle to image list
02930  *     iImage   [I] image index
02931  *     iOverlay [I] overlay mask index
02932  *
02933  * RETURNS
02934  *     Success: TRUE
02935  *     Failure: FALSE
02936  */
02937 
02938 BOOL WINAPI
02939 ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay)
02940 {
02941     if (!is_valid(himl))
02942     return FALSE;
02943     if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
02944     return FALSE;
02945     if ((iImage!=-1) && ((iImage < 0) || (iImage > himl->cCurImage)))
02946     return FALSE;
02947     himl->nOvlIdx[iOverlay - 1] = iImage;
02948     return TRUE;
02949 }
02950 
02951 
02952 
02953 /* helper for ImageList_Write - write bitmap to pstm
02954  * currently everything is written as 24 bit RGB, except masks
02955  */
02956 static BOOL
02957 _write_bitmap(HBITMAP hBitmap, LPSTREAM pstm)
02958 {
02959     LPBITMAPFILEHEADER bmfh;
02960     LPBITMAPINFOHEADER bmih;
02961     LPBYTE data = NULL, lpBits;
02962     BITMAP bm;
02963     INT bitCount, sizeImage, offBits, totalSize;
02964     HDC xdc;
02965     BOOL result = FALSE;
02966 
02967     if (!GetObjectW(hBitmap, sizeof(BITMAP), &bm))
02968         return FALSE;
02969 
02970     bitCount = bm.bmBitsPixel;
02971     sizeImage = get_dib_stride(bm.bmWidth, bitCount) * bm.bmHeight;
02972 
02973     totalSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
02974     if(bitCount <= 8)
02975     totalSize += (1 << bitCount) * sizeof(RGBQUAD);
02976     offBits = totalSize;
02977     totalSize += sizeImage;
02978 
02979     data = Alloc(totalSize);
02980     bmfh = (LPBITMAPFILEHEADER)data;
02981     bmih = (LPBITMAPINFOHEADER)(data + sizeof(BITMAPFILEHEADER));
02982     lpBits = data + offBits;
02983 
02984     /* setup BITMAPFILEHEADER */
02985     bmfh->bfType      = (('M' << 8) | 'B');
02986     bmfh->bfSize      = offBits;
02987     bmfh->bfReserved1 = 0;
02988     bmfh->bfReserved2 = 0;
02989     bmfh->bfOffBits   = offBits;
02990 
02991     /* setup BITMAPINFOHEADER */
02992     bmih->biSize          = sizeof(BITMAPINFOHEADER);
02993     bmih->biWidth         = bm.bmWidth;
02994     bmih->biHeight        = bm.bmHeight;
02995     bmih->biPlanes        = 1;
02996     bmih->biBitCount      = bitCount;
02997     bmih->biCompression   = BI_RGB;
02998     bmih->biSizeImage     = sizeImage;
02999     bmih->biXPelsPerMeter = 0;
03000     bmih->biYPelsPerMeter = 0;
03001     bmih->biClrUsed       = 0;
03002     bmih->biClrImportant  = 0;
03003 
03004     xdc = GetDC(0);
03005     result = GetDIBits(xdc, hBitmap, 0, bm.bmHeight, lpBits, (BITMAPINFO *)bmih, DIB_RGB_COLORS) == bm.bmHeight;
03006     ReleaseDC(0, xdc);
03007     if (!result)
03008     goto failed;
03009 
03010     TRACE("width %u, height %u, planes %u, bpp %u\n",
03011           bmih->biWidth, bmih->biHeight,
03012           bmih->biPlanes, bmih->biBitCount);
03013 
03014     if(FAILED(IStream_Write(pstm, data, totalSize, NULL)))
03015     goto failed;
03016 
03017     result = TRUE;
03018 
03019 failed:
03020     Free(data);
03021 
03022     return result;
03023 }
03024 
03025 
03026 /*************************************************************************
03027  * ImageList_Write [COMCTL32.@]
03028  *
03029  * Writes an image list to a stream.
03030  *
03031  * PARAMS
03032  *     himl [I] handle to image list
03033  *     pstm [O] Pointer to a stream.
03034  *
03035  * RETURNS
03036  *     Success: TRUE
03037  *     Failure: FALSE
03038  *
03039  * BUGS
03040  *     probably.
03041  */
03042 
03043 BOOL WINAPI
03044 ImageList_Write (HIMAGELIST himl, LPSTREAM pstm)
03045 {
03046     ILHEAD ilHead;
03047     int i;
03048 
03049     TRACE("%p %p\n", himl, pstm);
03050 
03051     if (!is_valid(himl))
03052     return FALSE;
03053 
03054     ilHead.usMagic   = (('L' << 8) | 'I');
03055     ilHead.usVersion = 0x101;
03056     ilHead.cCurImage = himl->cCurImage;
03057     ilHead.cMaxImage = himl->cMaxImage;
03058     ilHead.cGrow     = himl->cGrow;
03059     ilHead.cx        = himl->cx;
03060     ilHead.cy        = himl->cy;
03061     ilHead.bkcolor   = himl->clrBk;
03062     ilHead.flags     = himl->flags;
03063     for(i = 0; i < 4; i++) {
03064     ilHead.ovls[i] = himl->nOvlIdx[i];
03065     }
03066 
03067     TRACE("cx %u, cy %u, flags 0x04%x, cCurImage %u, cMaxImage %u\n",
03068           ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage);
03069 
03070     if(FAILED(IStream_Write(pstm, &ilHead, sizeof(ILHEAD), NULL)))
03071     return FALSE;
03072 
03073     /* write the bitmap */
03074     if(!_write_bitmap(himl->hbmImage, pstm))
03075     return FALSE;
03076 
03077     /* write the mask if we have one */
03078     if(himl->flags & ILC_MASK) {
03079     if(!_write_bitmap(himl->hbmMask, pstm))
03080         return FALSE;
03081     }
03082 
03083     return TRUE;
03084 }
03085 
03086 
03087 static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT count)
03088 {
03089     HBITMAP hbmNewBitmap;
03090     UINT ilc = (himl->flags & 0xFE);
03091     SIZE sz;
03092 
03093     imagelist_get_bitmap_size( himl, count, &sz );
03094 
03095     if ((ilc >= ILC_COLOR4 && ilc <= ILC_COLOR32) || ilc == ILC_COLOR)
03096     {
03097         char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
03098         BITMAPINFO *bmi = (BITMAPINFO *)buffer;
03099 
03100         TRACE("Creating DIBSection %d x %d, %d Bits per Pixel\n",
03101               sz.cx, sz.cy, himl->uBitsPixel);
03102 
03103         memset( buffer, 0, sizeof(buffer) );
03104     bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
03105     bmi->bmiHeader.biWidth = sz.cx;
03106     bmi->bmiHeader.biHeight = sz.cy;
03107     bmi->bmiHeader.biPlanes = 1;
03108     bmi->bmiHeader.biBitCount = himl->uBitsPixel;
03109     bmi->bmiHeader.biCompression = BI_RGB;
03110 
03111     if (himl->uBitsPixel <= ILC_COLOR8)
03112     {
03113             /* retrieve the default color map */
03114             HBITMAP tmp = CreateBitmap( 1, 1, 1, 1, NULL );
03115             GetDIBits( hdc, tmp, 0, 0, NULL, bmi, DIB_RGB_COLORS );
03116             DeleteObject( tmp );
03117     }
03118     hbmNewBitmap = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, 0, 0);
03119     }
03120     else /*if (ilc == ILC_COLORDDB)*/
03121     {
03122         TRACE("Creating Bitmap: %d Bits per Pixel\n", himl->uBitsPixel);
03123 
03124         hbmNewBitmap = CreateBitmap (sz.cx, sz.cy, 1, himl->uBitsPixel, NULL);
03125     }
03126     TRACE("returning %p\n", hbmNewBitmap);
03127     return hbmNewBitmap;
03128 }
03129 
03130 /*************************************************************************
03131  * ImageList_SetColorTable [COMCTL32.@]
03132  *
03133  * Sets the color table of an image list.
03134  *
03135  * PARAMS
03136  *     himl        [I] Handle to the image list.
03137  *     uStartIndex [I] The first index to set.
03138  *     cEntries    [I] Number of entries to set.
03139  *     prgb        [I] New color information for color table for the image list.
03140  *
03141  * RETURNS
03142  *     Success: Number of entries in the table that were set.
03143  *     Failure: Zero.
03144  *
03145  * SEE
03146  *     ImageList_Create(), SetDIBColorTable()
03147  */
03148 
03149 UINT WINAPI
03150 ImageList_SetColorTable (HIMAGELIST himl, UINT uStartIndex, UINT cEntries, CONST RGBQUAD * prgb)
03151 {
03152     return SetDIBColorTable(himl->hdcImage, uStartIndex, cEntries, prgb);
03153 }
03154 
03155 /*************************************************************************
03156  * ImageList_CoCreateInstance [COMCTL32.@]
03157  *
03158  * Creates a new imagelist instance and returns an interface pointer to it.
03159  *
03160  * PARAMS
03161  *     rclsid      [I] A reference to the CLSID (CLSID_ImageList).
03162  *     punkOuter   [I] Pointer to IUnknown interface for aggregation, if desired
03163  *     riid        [I] Identifier of the requested interface.
03164  *     ppv         [O] Returns the address of the pointer requested, or NULL.
03165  *
03166  * RETURNS
03167  *     Success: S_OK.
03168  *     Failure: Error value.
03169  */
03170 HRESULT WINAPI
03171 ImageList_CoCreateInstance (REFCLSID rclsid, const IUnknown *punkOuter, REFIID riid, void **ppv)
03172 {
03173     TRACE("(%s,%p,%s,%p)\n", debugstr_guid(rclsid), punkOuter, debugstr_guid(riid), ppv);
03174 
03175     if (!IsEqualCLSID(&CLSID_ImageList, rclsid))
03176         return E_NOINTERFACE;
03177 
03178     return ImageListImpl_CreateInstance(punkOuter, riid, ppv);
03179 }
03180 
03181 
03182 /*************************************************************************
03183  * IImageList implementation
03184  */
03185 
03186 static HRESULT WINAPI ImageListImpl_QueryInterface(IImageList *iface,
03187     REFIID iid, void **ppv)
03188 {
03189     HIMAGELIST This = (HIMAGELIST) iface;
03190     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
03191 
03192     if (!ppv) return E_INVALIDARG;
03193 
03194     if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IImageList, iid))
03195         *ppv = This;
03196     else
03197     {
03198         *ppv = NULL;
03199         return E_NOINTERFACE;
03200     }
03201 
03202     IUnknown_AddRef((IUnknown*)*ppv);
03203     return S_OK;
03204 }
03205 
03206 static ULONG WINAPI ImageListImpl_AddRef(IImageList *iface)
03207 {
03208     HIMAGELIST This = (HIMAGELIST) iface;
03209     ULONG ref = InterlockedIncrement(&This->ref);
03210 
03211     TRACE("(%p) refcount=%u\n", iface, ref);
03212     return ref;
03213 }
03214 
03215 static ULONG WINAPI ImageListImpl_Release(IImageList *iface)
03216 {
03217     HIMAGELIST This = (HIMAGELIST) iface;
03218     ULONG ref = InterlockedDecrement(&This->ref);
03219 
03220     TRACE("(%p) refcount=%u\n", iface, ref);
03221 
03222     if (ref == 0)
03223     {
03224         /* delete image bitmaps */
03225         if (This->hbmImage) DeleteObject (This->hbmImage);
03226         if (This->hbmMask)  DeleteObject (This->hbmMask);
03227 
03228         /* delete image & mask DCs */
03229         if (This->hdcImage) DeleteDC (This->hdcImage);
03230         if (This->hdcMask)  DeleteDC (This->hdcMask);
03231 
03232         /* delete blending brushes */
03233         if (This->hbrBlend25) DeleteObject (This->hbrBlend25);
03234         if (This->hbrBlend50) DeleteObject (This->hbrBlend50);
03235 
03236         This->lpVtbl = NULL;
03237         HeapFree(GetProcessHeap(), 0, This->has_alpha);
03238         HeapFree(GetProcessHeap(), 0, This);
03239     }
03240 
03241     return ref;
03242 }
03243 
03244 static HRESULT WINAPI ImageListImpl_Add(IImageList *iface, HBITMAP hbmImage,
03245     HBITMAP hbmMask, int *pi)
03246 {
03247     HIMAGELIST This = (HIMAGELIST) iface;
03248     int ret;
03249 
03250     if (!pi)
03251         return E_FAIL;
03252 
03253     ret = ImageList_Add(This, hbmImage, hbmMask);
03254 
03255     if (ret == -1)
03256         return E_FAIL;
03257 
03258     *pi = ret;
03259     return S_OK;
03260 }
03261 
03262 static HRESULT WINAPI ImageListImpl_ReplaceIcon(IImageList *iface, int i,
03263     HICON hicon, int *pi)
03264 {
03265     HIMAGELIST This = (HIMAGELIST) iface;
03266     int ret;
03267 
03268     if (!pi)
03269         return E_FAIL;
03270 
03271     ret = ImageList_ReplaceIcon(This, i, hicon);
03272 
03273     if (ret == -1)
03274         return E_FAIL;
03275 
03276     *pi = ret;
03277     return S_OK;
03278 }
03279 
03280 static HRESULT WINAPI ImageListImpl_SetOverlayImage(IImageList *iface,
03281     int iImage, int iOverlay)
03282 {
03283     return ImageList_SetOverlayImage((HIMAGELIST) iface, iImage, iOverlay)
03284         ? S_OK : E_FAIL;
03285 }
03286 
03287 static HRESULT WINAPI ImageListImpl_Replace(IImageList *iface, int i,
03288     HBITMAP hbmImage, HBITMAP hbmMask)
03289 {
03290     return ImageList_Replace((HIMAGELIST) iface, i, hbmImage, hbmMask) ? S_OK :
03291         E_FAIL;
03292 }
03293 
03294 static HRESULT WINAPI ImageListImpl_AddMasked(IImageList *iface, HBITMAP hbmImage,
03295     COLORREF crMask, int *pi)
03296 {
03297     HIMAGELIST This = (HIMAGELIST) iface;
03298     int ret;
03299 
03300     if (!pi)
03301         return E_FAIL;
03302 
03303     ret = ImageList_AddMasked(This, hbmImage, crMask);
03304 
03305     if (ret == -1)
03306         return E_FAIL;
03307 
03308     *pi = ret;
03309     return S_OK;
03310 }
03311 
03312 static HRESULT WINAPI ImageListImpl_Draw(IImageList *iface,
03313     IMAGELISTDRAWPARAMS *pimldp)
03314 {
03315     HIMAGELIST This = (HIMAGELIST) iface;
03316     HIMAGELIST old_himl;
03317     int ret;
03318 
03319     /* As far as I can tell, Windows simply ignores the contents of pimldp->himl
03320        so we shall simulate the same */
03321     old_himl = pimldp->himl;
03322     pimldp->himl = This;
03323 
03324     ret = ImageList_DrawIndirect(pimldp);
03325 
03326     pimldp->himl = old_himl;
03327     return ret ? S_OK : E_INVALIDARG;
03328 }
03329 
03330 static HRESULT WINAPI ImageListImpl_Remove(IImageList *iface, int i)
03331 {
03332     return (ImageList_Remove((HIMAGELIST) iface, i) == 0) ? E_INVALIDARG : S_OK;
03333 }
03334 
03335 static HRESULT WINAPI ImageListImpl_GetIcon(IImageList *iface, int i, UINT flags,
03336     HICON *picon)
03337 {
03338     HICON hIcon;
03339 
03340     if (!picon)
03341         return E_FAIL;
03342 
03343     hIcon = ImageList_GetIcon((HIMAGELIST) iface, i, flags);
03344 
03345     if (hIcon == NULL)
03346         return E_FAIL;
03347 
03348     *picon = hIcon;
03349     return S_OK;
03350 }
03351 
03352 static HRESULT WINAPI ImageListImpl_GetImageInfo(IImageList *iface, int i,
03353     IMAGEINFO *pImageInfo)
03354 {
03355     return ImageList_GetImageInfo((HIMAGELIST) iface, i, pImageInfo) ? S_OK : E_FAIL;
03356 }
03357 
03358 static HRESULT WINAPI ImageListImpl_Copy(IImageList *iface, int iDst,
03359     IUnknown *punkSrc, int iSrc, UINT uFlags)
03360 {
03361     HIMAGELIST This = (HIMAGELIST) iface;
03362     IImageList *src = NULL;
03363     HRESULT ret;
03364 
03365     if (!punkSrc)
03366         return E_FAIL;
03367 
03368     /* TODO: Add test for IID_ImageList2 too */
03369     if (FAILED(IImageList_QueryInterface(punkSrc, &IID_IImageList,
03370             (void **) &src)))
03371         return E_FAIL;
03372 
03373     if (ImageList_Copy(This, iDst, (HIMAGELIST) src, iSrc, uFlags))
03374         ret = S_OK;
03375     else
03376         ret = E_FAIL;
03377 
03378     IImageList_Release(src);
03379     return ret;
03380 }
03381 
03382 static HRESULT WINAPI ImageListImpl_Merge(IImageList *iface, int i1,
03383     IUnknown *punk2, int i2, int dx, int dy, REFIID riid, void **ppv)
03384 {
03385     HIMAGELIST This = (HIMAGELIST) iface;
03386     IImageList *iml2 = NULL;
03387     HIMAGELIST hNew;
03388     HRESULT ret = E_FAIL;
03389 
03390     TRACE("(%p)->(%d %p %d %d %d %s %p)\n", iface, i1, punk2, i2, dx, dy, debugstr_guid(riid), ppv);
03391 
03392     /* TODO: Add test for IID_ImageList2 too */
03393     if (FAILED(IImageList_QueryInterface(punk2, &IID_IImageList,
03394             (void **) &iml2)))
03395         return E_FAIL;
03396 
03397     hNew = ImageList_Merge(This, i1, (HIMAGELIST) iml2, i2, dx, dy);
03398 
03399     /* Get the interface for the new image list */
03400     if (hNew)
03401     {
03402         IImageList *imerge = (IImageList*)hNew;
03403 
03404         ret = HIMAGELIST_QueryInterface(hNew, riid, ppv);
03405         IImageList_Release(imerge);
03406     }
03407 
03408     IImageList_Release(iml2);
03409     return ret;
03410 }
03411 
03412 static HRESULT WINAPI ImageListImpl_Clone(IImageList *iface, REFIID riid, void **ppv)
03413 {
03414     HIMAGELIST This = (HIMAGELIST) iface;
03415     HIMAGELIST clone;
03416     HRESULT ret = E_FAIL;
03417 
03418     TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
03419 
03420     clone = ImageList_Duplicate(This);
03421 
03422     /* Get the interface for the new image list */
03423     if (clone)
03424     {
03425         IImageList *iclone = (IImageList*)clone;
03426 
03427         ret = HIMAGELIST_QueryInterface(clone, riid, ppv);
03428         IImageList_Release(iclone);
03429     }
03430 
03431     return ret;
03432 }
03433 
03434 static HRESULT WINAPI ImageListImpl_GetImageRect(IImageList *iface, int i,
03435     RECT *prc)
03436 {
03437     HIMAGELIST This = (HIMAGELIST) iface;
03438     IMAGEINFO info;
03439 
03440     if (!prc)
03441         return E_FAIL;
03442 
03443     if (!ImageList_GetImageInfo(This, i, &info))
03444         return E_FAIL;
03445 
03446     return CopyRect(prc, &info.rcImage) ? S_OK : E_FAIL;
03447 }
03448 
03449 static HRESULT WINAPI ImageListImpl_GetIconSize(IImageList *iface, int *cx,
03450     int *cy)
03451 {
03452     HIMAGELIST This = (HIMAGELIST) iface;
03453 
03454     return ImageList_GetIconSize(This, cx, cy) ? S_OK : E_INVALIDARG;
03455 }
03456 
03457 static HRESULT WINAPI ImageListImpl_SetIconSize(IImageList *iface, int cx,
03458     int cy)
03459 {
03460     return ImageList_SetIconSize((HIMAGELIST) iface, cx, cy) ? S_OK : E_FAIL;
03461 }
03462 
03463 static HRESULT WINAPI ImageListImpl_GetImageCount(IImageList *iface, int *pi)
03464 {
03465     *pi = ImageList_GetImageCount((HIMAGELIST) iface);
03466     return S_OK;
03467 }
03468 
03469 static HRESULT WINAPI ImageListImpl_SetImageCount(IImageList *iface,
03470     UINT uNewCount)
03471 {
03472     return ImageList_SetImageCount((HIMAGELIST) iface, uNewCount) ? S_OK : E_FAIL;
03473 }
03474 
03475 static HRESULT WINAPI ImageListImpl_SetBkColor(IImageList *iface, COLORREF clrBk,
03476     COLORREF *pclr)
03477 {
03478     *pclr = ImageList_SetBkColor((HIMAGELIST) iface, clrBk);
03479     return S_OK;
03480 }
03481 
03482 static HRESULT WINAPI ImageListImpl_GetBkColor(IImageList *iface, COLORREF *pclr)
03483 {
03484     *pclr = ImageList_GetBkColor((HIMAGELIST) iface);
03485     return S_OK;
03486 }
03487 
03488 static HRESULT WINAPI ImageListImpl_BeginDrag(IImageList *iface, int iTrack,
03489     int dxHotspot, int dyHotspot)
03490 {
03491     return ImageList_BeginDrag((HIMAGELIST) iface, iTrack, dxHotspot, dyHotspot) ? S_OK : E_FAIL;
03492 }
03493 
03494 static HRESULT WINAPI ImageListImpl_EndDrag(IImageList *iface)
03495 {
03496     ImageList_EndDrag();
03497     return S_OK;
03498 }
03499 
03500 static HRESULT WINAPI ImageListImpl_DragEnter(IImageList *iface, HWND hwndLock,
03501     int x, int y)
03502 {
03503     return ImageList_DragEnter(hwndLock, x, y) ? S_OK : E_FAIL;
03504 }
03505 
03506 static HRESULT WINAPI ImageListImpl_DragLeave(IImageList *iface, HWND hwndLock)
03507 {
03508     return ImageList_DragLeave(hwndLock) ? S_OK : E_FAIL;
03509 }
03510 
03511 static HRESULT WINAPI ImageListImpl_DragMove(IImageList *iface, int x, int y)
03512 {
03513     return ImageList_DragMove(x, y) ? S_OK : E_FAIL;
03514 }
03515 
03516 static HRESULT WINAPI ImageListImpl_SetDragCursorImage(IImageList *iface,
03517     IUnknown *punk, int iDrag, int dxHotspot, int dyHotspot)
03518 {
03519     IImageList *iml2 = NULL;
03520     HRESULT ret;
03521 
03522     if (!punk)
03523         return E_FAIL;
03524 
03525     /* TODO: Add test for IID_ImageList2 too */
03526     if (FAILED(IImageList_QueryInterface(punk, &IID_IImageList,
03527             (void **) &iml2)))
03528         return E_FAIL;
03529 
03530     ret = ImageList_SetDragCursorImage((HIMAGELIST) iml2, iDrag, dxHotspot,
03531         dyHotspot);
03532 
03533     IImageList_Release(iml2);
03534 
03535     return ret ? S_OK : E_FAIL;
03536 }
03537 
03538 static HRESULT WINAPI ImageListImpl_DragShowNolock(IImageList *iface, BOOL fShow)
03539 {
03540     return ImageList_DragShowNolock(fShow) ? S_OK : E_FAIL;
03541 }
03542 
03543 static HRESULT WINAPI ImageListImpl_GetDragImage(IImageList *iface, POINT *ppt,
03544     POINT *pptHotspot, REFIID riid, PVOID *ppv)
03545 {
03546     HRESULT ret = E_FAIL;
03547     HIMAGELIST hNew;
03548 
03549     if (!ppv)
03550         return E_FAIL;
03551 
03552     hNew = ImageList_GetDragImage(ppt, pptHotspot);
03553 
03554     /* Get the interface for the new image list */
03555     if (hNew)
03556     {
03557         IImageList *idrag = (IImageList*)hNew;
03558 
03559         ret = HIMAGELIST_QueryInterface(hNew, riid, ppv);
03560         IImageList_Release(idrag);
03561     }
03562 
03563     return ret;
03564 }
03565 
03566 static HRESULT WINAPI ImageListImpl_GetItemFlags(IImageList *iface, int i,
03567     DWORD *dwFlags)
03568 {
03569     FIXME("STUB: %p %d %p\n", iface, i, dwFlags);
03570     return E_NOTIMPL;
03571 }
03572 
03573 static HRESULT WINAPI ImageListImpl_GetOverlayImage(IImageList *iface, int iOverlay,
03574     int *piIndex)
03575 {
03576     HIMAGELIST This = (HIMAGELIST) iface;
03577     int i;
03578 
03579     if ((iOverlay < 0) || (iOverlay > This->cCurImage))
03580         return E_FAIL;
03581 
03582     for (i = 0; i < MAX_OVERLAYIMAGE; i++)
03583     {
03584         if (This->nOvlIdx[i] == iOverlay)
03585         {
03586             *piIndex = i + 1;
03587             return S_OK;
03588         }
03589     }
03590 
03591     return E_FAIL;
03592 }
03593 
03594 
03595 static const IImageListVtbl ImageListImpl_Vtbl = {
03596     ImageListImpl_QueryInterface,
03597     ImageListImpl_AddRef,
03598     ImageListImpl_Release,
03599     ImageListImpl_Add,
03600     ImageListImpl_ReplaceIcon,
03601     ImageListImpl_SetOverlayImage,
03602     ImageListImpl_Replace,
03603     ImageListImpl_AddMasked,
03604     ImageListImpl_Draw,
03605     ImageListImpl_Remove,
03606     ImageListImpl_GetIcon,
03607     ImageListImpl_GetImageInfo,
03608     ImageListImpl_Copy,
03609     ImageListImpl_Merge,
03610     ImageListImpl_Clone,
03611     ImageListImpl_GetImageRect,
03612     ImageListImpl_GetIconSize,
03613     ImageListImpl_SetIconSize,
03614     ImageListImpl_GetImageCount,
03615     ImageListImpl_SetImageCount,
03616     ImageListImpl_SetBkColor,
03617     ImageListImpl_GetBkColor,
03618     ImageListImpl_BeginDrag,
03619     ImageListImpl_EndDrag,
03620     ImageListImpl_DragEnter,
03621     ImageListImpl_DragLeave,
03622     ImageListImpl_DragMove,
03623     ImageListImpl_SetDragCursorImage,
03624     ImageListImpl_DragShowNolock,
03625     ImageListImpl_GetDragImage,
03626     ImageListImpl_GetItemFlags,
03627     ImageListImpl_GetOverlayImage
03628 };
03629 
03630 static BOOL is_valid(HIMAGELIST himl)
03631 {
03632     BOOL valid;
03633     __TRY
03634     {
03635         valid = himl && himl->lpVtbl == &ImageListImpl_Vtbl;
03636     }
03637     __EXCEPT_PAGE_FAULT
03638     {
03639         valid = FALSE;
03640     }
03641     __ENDTRY
03642     return valid;
03643 }
03644 
03645 /*************************************************************************
03646  * HIMAGELIST_QueryInterface [COMCTL32.@]
03647  *
03648  * Returns a pointer to an IImageList or IImageList2 object for the given
03649  * HIMAGELIST.
03650  *
03651  * PARAMS
03652  *     himl        [I] Image list handle.
03653  *     riid        [I] Identifier of the requested interface.
03654  *     ppv         [O] Returns the address of the pointer requested, or NULL.
03655  *
03656  * RETURNS
03657  *     Success: S_OK.
03658  *     Failure: Error value.
03659  */
03660 HRESULT WINAPI
03661 HIMAGELIST_QueryInterface (HIMAGELIST himl, REFIID riid, void **ppv)
03662 {
03663     TRACE("(%p,%s,%p)\n", himl, debugstr_guid(riid), ppv);
03664     return IImageList_QueryInterface((IImageList *) himl, riid, ppv);
03665 }
03666 
03667 static HRESULT ImageListImpl_CreateInstance(const IUnknown *pUnkOuter, REFIID iid, void** ppv)
03668 {
03669     HIMAGELIST This;
03670     HRESULT ret;
03671 
03672     TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
03673 
03674     *ppv = NULL;
03675 
03676     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
03677 
03678     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct _IMAGELIST));
03679     if (!This) return E_OUTOFMEMORY;
03680 
03681     This->lpVtbl = &ImageListImpl_Vtbl;
03682     This->ref = 1;
03683 
03684     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
03685     IUnknown_Release((IUnknown*)This);
03686 
03687     return ret;
03688 }

Generated on Sun May 27 2012 04:23:01 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.