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