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