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