Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenimagelist.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
1.7.6.1
|