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