2 * Unit test suite for imagelist control.
4 * Copyright 2004 Michael Stefaniuc
5 * Copyright 2002 Mike McCormack for CodeWeavers
6 * Copyright 2007 Dmitry Timoshkov
7 * Copyright 2009 Owen Rudge for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
36 #include "commctrl.h" /* must be included after objbase.h to get ImageList_Write */
38 #include "commoncontrols.h"
41 #include "wine/test.h"
47 #define WAIT Sleep (1000)
48 #define REDRAW(hwnd) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW)
54 #define IMAGELIST_MAGIC (('L' << 8) | 'I')
57 /* Header used by ImageList_Read() and ImageList_Write() */
58 typedef struct _ILHEAD
73 static HIMAGELIST (WINAPI *pImageList_Create)(int, int, UINT, int, int);
74 static int (WINAPI *pImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP);
75 static BOOL (WINAPI *pImageList_DrawIndirect)(IMAGELISTDRAWPARAMS*);
76 static BOOL (WINAPI *pImageList_SetImageCount)(HIMAGELIST,UINT);
77 static HRESULT (WINAPI *pImageList_CoCreateInstance)(REFCLSID,const IUnknown *,
79 static HRESULT (WINAPI *pHIMAGELIST_QueryInterface)(HIMAGELIST,REFIID,void **);
81 static HINSTANCE hinst;
83 /* These macros build cursor/bitmap data in 4x4 pixel blocks */
84 #define B(x,y) ((x?0xf0:0)|(y?0xf:0))
85 #define ROW1(a,b,c,d,e,f,g,h) B(a,b),B(c,d),B(e,f),B(g,h)
86 #define ROW32(a,b,c,d,e,f,g,h) ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h), \
87 ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h)
88 #define ROW2(a,b,c,d,e,f,g,h,i,j,k,l) ROW1(a,b,c,d,e,f,g,h),B(i,j),B(k,l)
89 #define ROW48(a,b,c,d,e,f,g,h,i,j,k,l) ROW2(a,b,c,d,e,f,g,h,i,j,k,l), \
90 ROW2(a,b,c,d,e,f,g,h,i,j,k,l), ROW2(a,b,c,d,e,f,g,h,i,j,k,l), \
91 ROW2(a,b,c,d,e,f,g,h,i,j,k,l)
93 static const BYTE empty_bits[48*48/8];
95 static const BYTE icon_bits[32*32/8] =
97 ROW32(0,0,0,0,0,0,0,0),
98 ROW32(0,0,1,1,1,1,0,0),
99 ROW32(0,1,1,1,1,1,1,0),
100 ROW32(0,1,1,0,0,1,1,0),
101 ROW32(0,1,1,0,0,1,1,0),
102 ROW32(0,1,1,1,1,1,1,0),
103 ROW32(0,0,1,1,1,1,0,0),
104 ROW32(0,0,0,0,0,0,0,0)
107 static const BYTE bitmap_bits[48*48/8] =
109 ROW48(0,0,0,0,0,0,0,0,0,0,0,0),
110 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
111 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
112 ROW48(0,1,0,0,0,0,0,0,1,0,1,0),
113 ROW48(0,1,0,0,0,0,0,1,0,0,1,0),
114 ROW48(0,1,0,0,0,0,1,0,0,0,1,0),
115 ROW48(0,1,0,0,0,1,0,0,0,0,1,0),
116 ROW48(0,1,0,0,1,0,0,0,0,0,1,0),
117 ROW48(0,1,0,1,0,0,0,0,0,0,1,0),
118 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
119 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
120 ROW48(0,0,0,0,0,0,0,0,0,0,0,0)
123 static HIMAGELIST createImageList(int cx, int cy)
125 /* Create an ImageList and put an image into it */
126 HIMAGELIST himl = ImageList_Create(cx, cy, ILC_COLOR, 1, 1);
127 HBITMAP hbm = CreateBitmap(48, 48, 1, 1, bitmap_bits);
128 ImageList_Add(himl, hbm, NULL);
133 static HWND create_a_window(void)
135 char className[] = "bmwnd";
136 char winName[] = "Test Bitmap";
138 static int registered = 0;
144 cls.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
145 cls.lpfnWndProc = DefWindowProcA;
149 cls.hIcon = LoadIconA (0, IDI_APPLICATION);
150 cls.hCursor = LoadCursorA (0, IDC_ARROW);
151 cls.hbrBackground = GetStockObject (WHITE_BRUSH);
152 cls.lpszMenuName = 0;
153 cls.lpszClassName = className;
155 RegisterClassA (&cls);
160 hWnd = CreateWindowA (className, winName,
161 WS_OVERLAPPEDWINDOW ,
162 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
166 ShowWindow (hWnd, SW_SHOW);
174 static HDC show_image(HWND hwnd, HIMAGELIST himl, int idx, int size,
175 LPCSTR loc, BOOL clear)
179 if (!himl) return NULL;
181 SetWindowText(hwnd, loc);
183 ImageList_Draw(himl, idx, hdc, 0, 0, ILD_TRANSPARENT);
190 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
191 ReleaseDC(hwnd, hdc);
198 /* Useful for checking differences */
200 static void dump_bits(const BYTE *p, const BYTE *q, int size)
206 for (i = 0; i < size * 2; i++)
209 for (j = 0; j < size; j++)
210 printf("%c%c", p[j] & 0xf0 ? 'X' : ' ', p[j] & 0xf ? 'X' : ' ');
212 for (j = 0; j < size; j++)
213 printf("%c%c", q[j] & 0xf0 ? 'X' : ' ', q[j] & 0xf ? 'X' : ' ');
222 static void check_bits(HWND hwnd, HIMAGELIST himl, int idx, int size,
223 const BYTE *checkbits, LPCSTR loc)
226 BYTE bits[100*100/8];
233 memset(bits, 0, sizeof(bits));
234 hdc = show_image(hwnd, himl, idx, size, loc, FALSE);
236 c = GetPixel(hdc, 0, 0);
238 for (y = 0; y < size; y ++)
240 for (x = 0; x < size; x++)
243 if (GetPixel(hdc, x, y) != c) bits[i] |= (0x80 >> (x & 0x7));
247 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
248 ReleaseDC(hwnd, hdc);
250 ok (memcmp(bits, checkbits, (size * size)/8) == 0,
251 "%s: bits different\n", loc);
252 if (memcmp(bits, checkbits, (size * size)/8))
253 dump_bits(bits, checkbits, size);
257 static void test_hotspot(void)
268 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
269 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
276 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
277 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
278 HWND hwnd = create_a_window();
281 for (i = 0; i < HOTSPOTS_MAX; i++) {
282 for (j = 0; j < HOTSPOTS_MAX; j++) {
283 int dx1 = hotspots[i].dx;
284 int dy1 = hotspots[i].dy;
285 int dx2 = hotspots[j].dx;
286 int dy2 = hotspots[j].dy;
287 int correctx, correcty, newx, newy;
292 ret = ImageList_BeginDrag(himl1, 0, dx1, dy1);
293 ok(ret != 0, "BeginDrag failed for { %d, %d }\n", dx1, dy1);
294 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
295 show_image(hwnd, himl1, 0, max(SIZEX1, SIZEY1), loc, TRUE);
297 /* check merging the dragged image with a second image */
298 ret = ImageList_SetDragCursorImage(himl2, 0, dx2, dy2);
299 ok(ret != 0, "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
301 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
302 show_image(hwnd, himl2, 0, max(SIZEX2, SIZEY2), loc, TRUE);
304 /* check new hotspot, it should be the same like the old one */
305 himlNew = ImageList_GetDragImage(NULL, &ppt);
306 ok(ppt.x == dx1 && ppt.y == dy1,
307 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
308 dx1, dy1, ppt.x, ppt.y);
309 /* check size of new dragged image */
310 ImageList_GetIconSize(himlNew, &newx, &newy);
311 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
312 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
313 ok(newx == correctx && newy == correcty,
314 "Expected drag image size [%d,%d] got [%d,%d]\n",
315 correctx, correcty, newx, newy);
316 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
317 show_image(hwnd, himlNew, 0, max(correctx, correcty), loc, TRUE);
326 ImageList_Destroy(himl2);
327 ImageList_Destroy(himl1);
331 static void test_add_remove(void)
339 /* create an imagelist to play with */
340 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
341 ok(himl!=0,"failed to create imagelist\n");
343 /* load the icons to add to the image list */
344 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
345 ok(hicon1 != 0, "no hicon1\n");
346 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
347 ok(hicon2 != 0, "no hicon2\n");
348 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
349 ok(hicon3 != 0, "no hicon3\n");
351 /* remove when nothing exists */
352 ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
353 /* removing everything from an empty imagelist should succeed */
354 ok(ImageList_RemoveAll(himl),"removed nonexistent icon\n");
357 ok(0==ImageList_AddIcon(himl, hicon1),"failed to add icon1\n");
358 ok(1==ImageList_AddIcon(himl, hicon2),"failed to add icon2\n");
359 ok(2==ImageList_AddIcon(himl, hicon3),"failed to add icon3\n");
361 /* remove an index out of range */
362 ok(!ImageList_Remove(himl,4711),"removed nonexistent icon\n");
365 ok(ImageList_Remove(himl,0),"can't remove 0\n");
366 ok(ImageList_Remove(himl,0),"can't remove 0\n");
367 ok(ImageList_Remove(himl,0),"can't remove 0\n");
369 /* remove one extra */
370 ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
373 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
375 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
376 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
377 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
380 static void test_imagecount(void)
384 if (!pImageList_SetImageCount)
386 win_skip("ImageList_SetImageCount not available\n");
390 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
391 ok(himl!=0,"failed to create imagelist\n");
393 ok(pImageList_SetImageCount(himl, 3), "couldn't increase image count\n");
394 ok(ImageList_GetImageCount(himl) == 3, "invalid image count after increase\n");
395 ok(pImageList_SetImageCount(himl, 1), "couldn't decrease image count\n");
396 ok(ImageList_GetImageCount(himl) == 1, "invalid image count after decrease to 1\n");
397 ok(pImageList_SetImageCount(himl, 0), "couldn't decrease image count\n");
398 ok(ImageList_GetImageCount(himl) == 0, "invalid image count after decrease to 0\n");
400 ok(ImageList_Destroy(himl), "destroy imagelist failed\n");
403 static void test_DrawIndirect(void)
411 IMAGELISTDRAWPARAMS imldp;
415 if (!pImageList_DrawIndirect)
417 win_skip("ImageList_DrawIndirect not available, skipping test\n");
421 hwndfortest = create_a_window();
422 hdc = GetDC(hwndfortest);
423 ok(hdc!=NULL, "couldn't get DC\n");
425 /* create an imagelist to play with */
426 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
427 ok(himl!=0,"failed to create imagelist\n");
429 /* load the icons to add to the image list */
430 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
431 ok(hbm1 != 0, "no bitmap 1\n");
432 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
433 ok(hbm2 != 0, "no bitmap 2\n");
434 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
435 ok(hbm3 != 0, "no bitmap 3\n");
438 ok(0==ImageList_Add(himl, hbm1, 0),"failed to add bitmap 1\n");
439 ok(1==ImageList_Add(himl, hbm2, 0),"failed to add bitmap 2\n");
441 if (pImageList_SetImageCount)
443 ok(pImageList_SetImageCount(himl,3),"Setimage count failed\n");
444 /*ok(2==ImageList_Add(himl, hbm3, NULL),"failed to add bitmap 3\n"); */
445 ok(ImageList_Replace(himl, 2, hbm3, 0),"failed to replace bitmap 3\n");
448 memset(&imldp, 0, sizeof (imldp));
449 ok(!pImageList_DrawIndirect(&imldp), "zero data succeeded!\n");
450 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
451 ok(!pImageList_DrawIndirect(&imldp), "zero hdc succeeded!\n");
453 ok(!pImageList_DrawIndirect(&imldp),"zero himl succeeded!\n");
459 imldp.fStyle = SRCCOPY;
460 imldp.rgbBk = CLR_DEFAULT;
461 imldp.rgbFg = CLR_DEFAULT;
464 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
466 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
468 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
470 ok(!pImageList_DrawIndirect(&imldp),"should fail\n");
473 ok(ImageList_Remove(himl, 0), "removing 1st bitmap\n");
474 ok(ImageList_Remove(himl, 0), "removing 2nd bitmap\n");
475 ok(ImageList_Remove(himl, 0), "removing 3rd bitmap\n");
478 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
480 /* bitmaps should not be deleted by the imagelist */
481 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
482 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
483 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
485 ReleaseDC(hwndfortest, hdc);
486 DestroyWindow(hwndfortest);
489 static void test_merge(void)
491 HIMAGELIST himl1, himl2, hmerge;
493 HWND hwnd = create_a_window();
495 himl1 = ImageList_Create(32,32,0,0,3);
496 ok(himl1 != NULL,"failed to create himl1\n");
498 himl2 = ImageList_Create(32,32,0,0,3);
499 ok(himl2 != NULL,"failed to create himl2\n");
501 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
502 ok(hicon1 != NULL, "failed to create hicon1\n");
504 if (!himl1 || !himl2 || !hicon1)
507 ok(0==ImageList_AddIcon(himl2, hicon1),"add icon1 to himl2 failed\n");
508 check_bits(hwnd, himl2, 0, 32, icon_bits, "add icon1 to himl2");
510 /* If himl1 has no images, merge still succeeds */
511 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
512 ok(hmerge != NULL, "merge himl1,-1 failed\n");
513 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,-1");
514 if (hmerge) ImageList_Destroy(hmerge);
516 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
517 ok(hmerge != NULL,"merge himl1,0 failed\n");
518 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,0");
519 if (hmerge) ImageList_Destroy(hmerge);
521 /* Same happens if himl2 is empty */
522 ImageList_Destroy(himl2);
523 himl2 = ImageList_Create(32,32,0,0,3);
524 ok(himl2 != NULL,"failed to recreate himl2\n");
528 hmerge = ImageList_Merge(himl1, -1, himl2, -1, 0, 0);
529 ok(hmerge != NULL, "merge himl2,-1 failed\n");
530 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,-1");
531 if (hmerge) ImageList_Destroy(hmerge);
533 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
534 ok(hmerge != NULL, "merge himl2,0 failed\n");
535 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,0");
536 if (hmerge) ImageList_Destroy(hmerge);
538 /* Now try merging an image with itself */
539 ok(0==ImageList_AddIcon(himl2, hicon1),"re-add icon1 to himl2 failed\n");
541 hmerge = ImageList_Merge(himl2, 0, himl2, 0, 0, 0);
542 ok(hmerge != NULL, "merge himl2 with itself failed\n");
543 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2 with itself");
544 if (hmerge) ImageList_Destroy(hmerge);
546 /* Try merging 2 different image lists */
547 ok(0==ImageList_AddIcon(himl1, hicon1),"add icon1 to himl1 failed\n");
549 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
550 ok(hmerge != NULL, "merge himl1 with himl2 failed\n");
551 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2");
552 if (hmerge) ImageList_Destroy(hmerge);
554 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 8, 16);
555 ok(hmerge != NULL, "merge himl1 with himl2 8,16 failed\n");
556 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2, 8,16");
557 if (hmerge) ImageList_Destroy(hmerge);
559 ImageList_Destroy(himl1);
560 ImageList_Destroy(himl2);
565 /*********************** imagelist storage test ***************************/
572 char *iml_data; /* written imagelist data */
576 static HRESULT STDMETHODCALLTYPE Test_Stream_QueryInterface(
585 static ULONG STDMETHODCALLTYPE Test_Stream_AddRef(
592 static ULONG STDMETHODCALLTYPE Test_Stream_Release(
599 static HRESULT STDMETHODCALLTYPE Test_Stream_Read(
609 static BOOL allocate_storage(struct my_IStream *my_is, ULONG add)
611 my_is->iml_data_size += add;
613 if (!my_is->iml_data)
614 my_is->iml_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data_size);
616 my_is->iml_data = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data, my_is->iml_data_size);
618 return my_is->iml_data ? TRUE : FALSE;
621 static HRESULT STDMETHODCALLTYPE Test_Stream_Write(
627 struct my_IStream *my_is = (struct my_IStream *)This;
628 ULONG current_iml_data_size = my_is->iml_data_size;
630 if (!allocate_storage(my_is, cb)) return E_FAIL;
632 memcpy(my_is->iml_data + current_iml_data_size, pv, cb);
633 if (pcbWritten) *pcbWritten = cb;
638 static HRESULT STDMETHODCALLTYPE Test_Stream_Seek(
640 LARGE_INTEGER dlibMove,
642 ULARGE_INTEGER* plibNewPosition)
648 static HRESULT STDMETHODCALLTYPE Test_Stream_SetSize(
650 ULARGE_INTEGER libNewSize)
656 static HRESULT STDMETHODCALLTYPE Test_Stream_CopyTo(
660 ULARGE_INTEGER* pcbRead,
661 ULARGE_INTEGER* pcbWritten)
667 static HRESULT STDMETHODCALLTYPE Test_Stream_Commit(
669 DWORD grfCommitFlags)
675 static HRESULT STDMETHODCALLTYPE Test_Stream_Revert(
682 static HRESULT STDMETHODCALLTYPE Test_Stream_LockRegion(
684 ULARGE_INTEGER libOffset,
692 static HRESULT STDMETHODCALLTYPE Test_Stream_UnlockRegion(
694 ULARGE_INTEGER libOffset,
702 static HRESULT STDMETHODCALLTYPE Test_Stream_Stat(
711 static HRESULT STDMETHODCALLTYPE Test_Stream_Clone(
719 static const IStreamVtbl Test_Stream_Vtbl =
721 Test_Stream_QueryInterface,
731 Test_Stream_LockRegion,
732 Test_Stream_UnlockRegion,
737 static struct my_IStream Test_Stream = { { &Test_Stream_Vtbl }, 0, 0 };
739 static INT DIB_GetWidthBytes( int width, int bpp )
745 case 1: words = (width + 31) / 32; break;
746 case 4: words = (width + 7) / 8; break;
747 case 8: words = (width + 3) / 4; break;
749 case 16: words = (width + 1) / 2; break;
750 case 24: words = (width * 3 + 3)/4; break;
751 case 32: words = width; break;
754 trace("Unknown depth %d, please report.\n", bpp );
761 static void check_bitmap_data(const char *bm_data, ULONG bm_data_size,
762 INT width, INT height, INT bpp,
765 const BITMAPFILEHEADER *bmfh = (const BITMAPFILEHEADER *)bm_data;
766 const BITMAPINFOHEADER *bmih = (const BITMAPINFOHEADER *)(bm_data + sizeof(*bmfh));
767 ULONG hdr_size, image_size;
769 hdr_size = sizeof(*bmfh) + sizeof(*bmih);
770 if (bmih->biBitCount <= 8) hdr_size += (1 << bpp) * sizeof(RGBQUAD);
772 ok(bmfh->bfType == (('M' << 8) | 'B'), "wrong bfType 0x%02x\n", bmfh->bfType);
773 ok(bmfh->bfSize == hdr_size, "wrong bfSize 0x%02x\n", bmfh->bfSize);
774 ok(bmfh->bfReserved1 == 0, "wrong bfReserved1 0x%02x\n", bmfh->bfReserved1);
775 ok(bmfh->bfReserved2 == 0, "wrong bfReserved2 0x%02x\n", bmfh->bfReserved2);
776 ok(bmfh->bfOffBits == hdr_size, "wrong bfOffBits 0x%02x\n", bmfh->bfOffBits);
778 ok(bmih->biSize == sizeof(*bmih), "wrong biSize %d\n", bmih->biSize);
779 ok(bmih->biWidth == width, "wrong biWidth %d (expected %d)\n", bmih->biWidth, width);
780 ok(bmih->biHeight == height, "wrong biHeight %d (expected %d)\n", bmih->biHeight, height);
781 ok(bmih->biPlanes == 1, "wrong biPlanes %d\n", bmih->biPlanes);
782 ok(bmih->biBitCount == bpp, "wrong biBitCount %d\n", bmih->biBitCount);
784 image_size = DIB_GetWidthBytes(bmih->biWidth, bmih->biBitCount) * bmih->biHeight;
785 ok(bmih->biSizeImage == image_size, "wrong biSizeImage %u\n", bmih->biSizeImage);
790 sprintf(fname, "bmp_%s.bmp", comment);
791 f = fopen(fname, "wb");
792 fwrite(bm_data, 1, bm_data_size, f);
798 static void check_ilhead_data(const char *ilh_data, INT cx, INT cy, INT cur, INT max, INT grow)
800 const ILHEAD *ilh = (const ILHEAD *)ilh_data;
802 ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
803 ok(ilh->usVersion == 0x101, "wrong usVersion %x (expected 0x101)\n", ilh->usVersion);
804 ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
805 ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
806 ok(ilh->cGrow == grow, "wrong cGrow %d (expected %d)\n", ilh->cGrow, grow);
807 ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
808 ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
809 ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
810 ok(ilh->flags == ILC_COLOR24, "wrong flags %04x\n", ilh->flags);
811 ok(ilh->ovls[0] == -1 ||
812 ilh->ovls[0] == 0, /* win95 */
813 "wrong ovls[0] %04x\n", ilh->ovls[0]);
814 ok(ilh->ovls[1] == -1 ||
815 ilh->ovls[1] == 0, /* win95 */
816 "wrong ovls[1] %04x\n", ilh->ovls[1]);
817 ok(ilh->ovls[2] == -1 ||
818 ilh->ovls[2] == 0, /* win95 */
819 "wrong ovls[2] %04x\n", ilh->ovls[2]);
820 ok(ilh->ovls[3] == -1 ||
821 ilh->ovls[3] == 0, /* win95 */
822 "wrong ovls[3] %04x\n", ilh->ovls[3]);
825 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
828 char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
829 BITMAPINFO *bmi = (BITMAPINFO *)bmibuf;
830 HBITMAP hbmp, hbmp_old;
832 RECT rc = { 0, 0, cx, cy };
834 hdc = CreateCompatibleDC(0);
836 memset(bmi, 0, sizeof(*bmi));
837 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
838 bmi->bmiHeader.biHeight = cx;
839 bmi->bmiHeader.biWidth = cy;
840 bmi->bmiHeader.biBitCount = 24;
841 bmi->bmiHeader.biPlanes = 1;
842 bmi->bmiHeader.biCompression = BI_RGB;
843 hbmp = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
845 hbmp_old = SelectObject(hdc, hbmp);
847 hbrush = CreateSolidBrush(color);
848 FillRect(hdc, &rc, hbrush);
849 DeleteObject(hbrush);
851 DrawText(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
853 SelectObject(hdc, hbmp_old);
859 #define iml_clear_stream_data() \
860 HeapFree(GetProcessHeap(), 0, Test_Stream.iml_data); \
861 Test_Stream.iml_data = NULL; \
862 Test_Stream.iml_data_size = 0;
864 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, INT grow,
865 INT width, INT height, INT bpp, const char *comment)
869 trace("%s\n", comment);
871 ret = ImageList_GetImageCount(himl);
872 ok(ret == cur, "expected image count %d got %d\n", cur, ret);
874 ret = ImageList_GetIconSize(himl, &cxx, &cyy);
875 ok(ret, "ImageList_GetIconSize failed\n");
876 ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx);
877 ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy);
879 iml_clear_stream_data();
880 ret = ImageList_Write(himl, &Test_Stream.is);
881 ok(ret, "ImageList_Write failed\n");
883 ok(Test_Stream.iml_data != 0, "ImageList_Write didn't write any data\n");
884 ok(Test_Stream.iml_data_size > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n");
886 check_ilhead_data(Test_Stream.iml_data, cx, cy, cur, max, grow);
887 check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD),
888 Test_Stream.iml_data_size - sizeof(ILHEAD),
889 width, height, bpp, comment);
892 static void image_list_init(HIMAGELIST himl)
897 static const struct test_data
900 INT cx, cy, cur, max, grow, width, height, bpp;
904 { 255, BMP_CX, BMP_CX, 1, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 1" },
905 { 170, BMP_CX, BMP_CX, 2, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 2" },
906 { 85, BMP_CX, BMP_CX, 3, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 3" },
907 { 0, BMP_CX, BMP_CX, 4, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 4" },
908 { 0, BMP_CX, BMP_CX, 5, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 5" },
909 { 85, BMP_CX, BMP_CX, 6, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 6" },
910 { 170, BMP_CX, BMP_CX, 7, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 7" },
911 { 255, BMP_CX, BMP_CX, 8, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 8" },
912 { 255, BMP_CX, BMP_CX, 9, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 9" },
913 { 170, BMP_CX, BMP_CX, 10, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 10" },
914 { 85, BMP_CX, BMP_CX, 11, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 11" },
915 { 0, BMP_CX, BMP_CX, 12, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 12" },
916 { 0, BMP_CX, BMP_CX, 13, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 13" },
917 { 85, BMP_CX, BMP_CX, 14, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 14" },
918 { 170, BMP_CX, BMP_CX, 15, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 15" },
919 { 255, BMP_CX, BMP_CX, 16, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 16" },
920 { 255, BMP_CX, BMP_CX, 17, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 17" },
921 { 170, BMP_CX, BMP_CX, 18, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 18" },
922 { 85, BMP_CX, BMP_CX, 19, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 19" },
923 { 0, BMP_CX, BMP_CX, 20, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 20" },
924 { 0, BMP_CX, BMP_CX, 21, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 21" },
925 { 85, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 22" },
926 { 170, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 23" },
927 { 255, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 24" }
930 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 0");
932 #define add_bitmap(grey) \
933 sprintf(comment, "%d", n++); \
934 hbm = create_bitmap(BMP_CX, BMP_CX, RGB((grey),(grey),(grey)), comment); \
935 ImageList_Add(himl, hbm, NULL); \
938 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
940 add_bitmap(td[i].grey);
941 check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, td[i].grow,
942 td[i].width, td[i].height, td[i].bpp, td[i].comment);
947 static void test_imagelist_storage(void)
953 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
954 ok(himl != 0, "ImageList_Create failed\n");
956 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "empty");
958 image_list_init(himl);
959 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "orig");
961 ret = ImageList_Remove(himl, 4);
962 ok(ret, "ImageList_Remove failed\n");
963 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "1");
965 ret = ImageList_Remove(himl, 5);
966 ok(ret, "ImageList_Remove failed\n");
967 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "2");
969 ret = ImageList_Remove(himl, 6);
970 ok(ret, "ImageList_Remove failed\n");
971 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "3");
973 ret = ImageList_Remove(himl, 7);
974 ok(ret, "ImageList_Remove failed\n");
975 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "4");
977 ret = ImageList_Remove(himl, -2);
978 ok(!ret, "ImageList_Remove(-2) should fail\n");
979 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "5");
981 ret = ImageList_Remove(himl, 20);
982 ok(!ret, "ImageList_Remove(20) should fail\n");
983 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "6");
985 ret = ImageList_Remove(himl, -1);
986 ok(ret, "ImageList_Remove(-1) failed\n");
987 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, 4, BMP_CX * 4, BMP_CX * 1, 24, "7");
989 ret = ImageList_Destroy(himl);
990 ok(ret, "ImageList_Destroy failed\n");
992 iml_clear_stream_data();
994 /* test ImageList_Create storage allocation */
996 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 0, 32);
997 ok(himl != 0, "ImageList_Create failed\n");
998 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 32, BMP_CX * 4, BMP_CX * 1, 24, "init 0 grow 32");
999 hbm = create_bitmap(BMP_CX * 9, BMP_CX, 0, "9");
1000 ret = ImageList_Add(himl, hbm, NULL);
1001 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1002 check_iml_data(himl, BMP_CX, BMP_CX, 1, 34, 32, BMP_CX * 4, BMP_CX * 9, 24, "add 1 x 9");
1004 ret = ImageList_Destroy(himl);
1005 ok(ret, "ImageList_Destroy failed\n");
1006 iml_clear_stream_data();
1008 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 4);
1009 ok(himl != 0, "ImageList_Create failed\n");
1010 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, 24, "init 4 grow 4");
1011 hbm = create_bitmap(BMP_CX, BMP_CX * 9, 0, "9");
1012 ret = ImageList_Add(himl, hbm, NULL);
1013 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1014 check_iml_data(himl, BMP_CX, BMP_CX, 9, 15, 4, BMP_CX * 4, BMP_CX * 4, 24, "add 9 x 1");
1015 ret = ImageList_Add(himl, hbm, NULL);
1016 ok(ret == 9, "ImageList_Add returned %d, expected 9\n", ret);
1017 check_iml_data(himl, BMP_CX, BMP_CX, 18, 25, 4, BMP_CX * 4, BMP_CX * 7, 24, "add 9 x 1");
1019 ret = ImageList_Destroy(himl);
1020 ok(ret, "ImageList_Destroy failed\n");
1021 iml_clear_stream_data();
1023 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 207, 209);
1024 ok(himl != 0, "ImageList_Create failed\n");
1025 check_iml_data(himl, BMP_CX, BMP_CX, 0, 208, 212, BMP_CX * 4, BMP_CX * 52, 24, "init 207 grow 209");
1026 ret = ImageList_Destroy(himl);
1027 ok(ret, "ImageList_Destroy failed\n");
1028 iml_clear_stream_data();
1030 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 209, 207);
1031 ok(himl != 0, "ImageList_Create failed\n");
1032 check_iml_data(himl, BMP_CX, BMP_CX, 0, 210, 208, BMP_CX * 4, BMP_CX * 53, 24, "init 209 grow 207");
1033 ret = ImageList_Destroy(himl);
1034 ok(ret, "ImageList_Destroy failed\n");
1035 iml_clear_stream_data();
1037 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 14, 4);
1038 ok(himl != 0, "ImageList_Create failed\n");
1039 check_iml_data(himl, BMP_CX, BMP_CX, 0, 15, 4, BMP_CX * 4, BMP_CX * 4, 24, "init 14 grow 4");
1040 ret = ImageList_Destroy(himl);
1041 ok(ret, "ImageList_Destroy failed\n");
1042 iml_clear_stream_data();
1044 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 5, 9);
1045 ok(himl != 0, "ImageList_Create failed\n");
1046 check_iml_data(himl, BMP_CX, BMP_CX, 0, 6, 12, BMP_CX * 4, BMP_CX * 2, 24, "init 5 grow 9");
1047 ret = ImageList_Destroy(himl);
1048 ok(ret, "ImageList_Destroy failed\n");
1049 iml_clear_stream_data();
1051 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 9, 5);
1052 ok(himl != 0, "ImageList_Create failed\n");
1053 check_iml_data(himl, BMP_CX, BMP_CX, 0, 10, 8, BMP_CX * 4, BMP_CX * 3, 24, "init 9 grow 5");
1054 ret = ImageList_Destroy(himl);
1055 ok(ret, "ImageList_Destroy failed\n");
1056 iml_clear_stream_data();
1058 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 2, 4);
1059 ok(himl != 0, "ImageList_Create failed\n");
1060 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX * 1, 24, "init 2 grow 4");
1061 ret = ImageList_Destroy(himl);
1062 ok(ret, "ImageList_Destroy failed\n");
1063 iml_clear_stream_data();
1065 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 2);
1066 ok(himl != 0, "ImageList_Create failed\n");
1067 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, 24, "init 4 grow 2");
1068 ret = ImageList_Destroy(himl);
1069 ok(ret, "ImageList_Destroy failed\n");
1070 iml_clear_stream_data();
1073 static void test_shell_imagelist(void)
1075 BOOL (WINAPI *pSHGetImageList)(INT, REFIID, void**);
1076 IImageList *iml = NULL;
1083 /* Try to load function from shell32 */
1084 hShell32 = LoadLibrary("shell32.dll");
1085 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1087 if (!pSHGetImageList)
1089 win_skip("SHGetImageList not available, skipping test\n");
1093 /* Get system image list */
1094 hr = (pSHGetImageList)(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1096 ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1101 IImageList_GetImageCount(iml, &out);
1102 ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1104 /* Fetch the small icon size */
1105 cx = GetSystemMetrics(SM_CXSMICON);
1106 cy = GetSystemMetrics(SM_CYSMICON);
1108 /* Check icon size matches */
1109 IImageList_GetImageRect(iml, 0, &rect);
1110 ok(((rect.right == cx) && (rect.bottom == cy)),
1111 "IImageList_GetImageRect returned r:%d,b:%d\n",
1112 rect.right, rect.bottom);
1114 IImageList_Release(iml);
1115 FreeLibrary(hShell32);
1118 static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
1121 UINT32 *buffer = NULL;
1122 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
1125 hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1126 ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1128 if(!hBitmap || !buffer)
1130 DeleteObject(hBitmap);
1140 static BOOL colour_match(UINT32 x, UINT32 y)
1142 const INT32 tolerance = 8;
1144 const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1145 const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1146 const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1148 return (dr <= tolerance && dg <= tolerance && db <= tolerance);
1151 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1152 UINT32 expected, int line)
1154 bits[0] = 0x00FFFFFF;
1155 pImageList_DrawIndirect(ildp);
1156 ok(colour_match(bits[0], expected),
1157 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1158 bits[0] & 0x00FFFFFF, expected, line);
1162 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1163 UINT fStyle, UINT32 expected, int line)
1165 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1166 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1167 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1170 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1171 DWORD dwRop, UINT32 expected, int line)
1173 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1174 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1175 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1178 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1179 UINT fState, DWORD Frame, UINT32 expected, int line)
1181 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1182 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1183 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1186 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1187 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1188 UINT32 broken_expected, int line)
1190 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1191 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1192 bits[0] = 0x00FFFFFF;
1193 pImageList_DrawIndirect(&ildp);
1194 ok(colour_match(bits[0], expected) ||
1195 broken(colour_match(bits[0], broken_expected)),
1196 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1197 bits[0] & 0x00FFFFFF, expected, line);
1200 static void test_ImageList_DrawIndirect(void)
1202 HIMAGELIST himl = NULL;
1205 HBITMAP hbmOld = NULL, hbmDst = NULL;
1206 HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1207 HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
1208 int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1210 UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1211 int bpp, broken_value;
1213 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1216 hdcDst = CreateCompatibleDC(0);
1217 ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1220 bpp = GetDeviceCaps(hdcDst, BITSPIXEL);
1222 hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1223 ok(hbmMask != 0, "CreateBitmap failed\n");
1224 if(!hbmMask) goto cleanup;
1226 hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1227 ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1228 if(!hbmInverseMask) goto cleanup;
1230 himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1231 ok(himl != 0, "ImageList_Create failed\n");
1232 if(!himl) goto cleanup;
1234 /* Add a no-alpha image */
1235 hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
1236 if(!hbmImage) goto cleanup;
1238 iImage = pImageList_Add(himl, hbmImage, hbmMask);
1239 ok(iImage != -1, "ImageList_Add failed\n");
1240 if(iImage == -1) goto cleanup;
1242 /* Add an alpha image */
1243 hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
1244 if(!hbmAlphaImage) goto cleanup;
1246 iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1247 ok(iAlphaImage != -1, "ImageList_Add failed\n");
1248 if(iAlphaImage == -1) goto cleanup;
1250 /* Add a transparent alpha image */
1251 hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
1252 if(!hbmTransparentImage) goto cleanup;
1254 iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1255 ok(iTransparentImage != -1, "ImageList_Add failed\n");
1256 if(iTransparentImage == -1) goto cleanup;
1259 bitmapInfo.bmiHeader.biBitCount = 32;
1260 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1261 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1262 if (!hbmDst || !bits)
1264 hbmOld = SelectObject(hdcDst, hbmDst);
1266 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1267 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1268 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
1269 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1270 else broken_value = 0x00B4BDC4;
1271 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1272 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1273 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1274 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1276 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
1277 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
1279 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1280 else broken_value = 0x009DA8B1;
1281 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1282 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1283 else broken_value = 0x008C99A3;
1284 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1285 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
1286 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
1287 todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
1289 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
1291 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1292 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
1294 /* ILD_ROP is ignored when the image has an alpha channel */
1295 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
1296 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
1298 todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
1299 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
1301 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
1302 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
1304 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
1305 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
1306 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
1311 SelectObject(hdcDst, hbmOld);
1313 DeleteObject(hbmDst);
1319 DeleteObject(hbmMask);
1321 DeleteObject(hbmInverseMask);
1324 DeleteObject(hbmImage);
1326 DeleteObject(hbmAlphaImage);
1327 if(hbmTransparentImage)
1328 DeleteObject(hbmTransparentImage);
1332 ret = ImageList_Destroy(himl);
1333 ok(ret, "ImageList_Destroy failed\n");
1337 static void test_iimagelist(void)
1339 IImageList *imgl, *imgl2;
1344 if (!pHIMAGELIST_QueryInterface)
1346 win_skip("XP imagelist functions not available\n");
1350 /* test reference counting on destruction */
1351 imgl = (IImageList*)createImageList(32, 32);
1352 ret = IUnknown_AddRef(imgl);
1353 ok(ret == 2, "Expected 2, got %d\n", ret);
1354 ret = ImageList_Destroy((HIMAGELIST)imgl);
1355 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1356 ret = ImageList_Destroy((HIMAGELIST)imgl);
1357 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1358 ret = ImageList_Destroy((HIMAGELIST)imgl);
1359 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1361 imgl = (IImageList*)createImageList(32, 32);
1362 ret = IUnknown_AddRef(imgl);
1363 ok(ret == 2, "Expected 2, got %d\n", ret);
1364 ret = ImageList_Destroy((HIMAGELIST)imgl);
1365 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1366 ret = IImageList_Release(imgl);
1367 ok(ret == 0, "Expected 0, got %d\n", ret);
1368 ret = ImageList_Destroy((HIMAGELIST)imgl);
1369 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1371 /* ref counting, HIMAGELIST_QueryInterface adds a reference */
1372 imgl = (IImageList*)createImageList(32, 32);
1373 hr = pHIMAGELIST_QueryInterface((HIMAGELIST)imgl, &IID_IImageList, (void**)&imgl2);
1374 ok(hr == S_OK, "got 0x%08x\n", hr);
1375 ok(imgl2 == imgl, "got different pointer\n");
1376 ret = IImageList_Release(imgl);
1377 ok(ret == 1, "got %u\n", ret);
1378 IImageList_Release(imgl);
1380 if (!pImageList_CoCreateInstance)
1382 win_skip("Vista imagelist functions not available\n");
1386 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1387 ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
1390 IImageList_Release(imgl);
1392 himl = createImageList(32, 32);
1397 hr = (pHIMAGELIST_QueryInterface)(himl, &IID_IImageList, (void **) &imgl);
1398 ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
1401 IImageList_Release(imgl);
1403 ImageList_Destroy(himl);
1406 static void test_hotspot_v6(void)
1417 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
1418 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
1425 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
1426 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
1427 IImageList *imgl1, *imgl2;
1430 /* cast to IImageList */
1431 imgl1 = (IImageList *) himl1;
1432 imgl2 = (IImageList *) himl2;
1434 for (i = 0; i < HOTSPOTS_MAX; i++) {
1435 for (j = 0; j < HOTSPOTS_MAX; j++) {
1436 int dx1 = hotspots[i].dx;
1437 int dy1 = hotspots[i].dy;
1438 int dx2 = hotspots[j].dx;
1439 int dy2 = hotspots[j].dy;
1440 int correctx, correcty, newx, newy;
1442 IImageList *imglNew;
1445 hr = IImageList_BeginDrag(imgl1, 0, dx1, dy1);
1446 ok(SUCCEEDED(hr), "BeginDrag failed for { %d, %d }\n", dx1, dy1);
1447 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
1449 /* check merging the dragged image with a second image */
1450 hr = IImageList_SetDragCursorImage(imgl2, (IUnknown *) imgl2, 0, dx2, dy2);
1451 ok(SUCCEEDED(hr), "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
1452 dx1, dy1, dx2, dy2);
1453 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
1455 /* check new hotspot, it should be the same like the old one */
1456 hr = IImageList_GetDragImage(imgl2, NULL, &ppt, &IID_IImageList, (PVOID *) &imglNew);
1457 ok(SUCCEEDED(hr), "GetDragImage failed\n");
1458 ok(ppt.x == dx1 && ppt.y == dy1,
1459 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
1460 dx1, dy1, ppt.x, ppt.y);
1461 /* check size of new dragged image */
1462 IImageList_GetIconSize(imglNew, &newx, &newy);
1463 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
1464 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
1465 ok(newx == correctx && newy == correcty,
1466 "Expected drag image size [%d,%d] got [%d,%d]\n",
1467 correctx, correcty, newx, newy);
1468 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
1469 IImageList_EndDrag(imgl2);
1477 IImageList_Release(imgl2);
1478 IImageList_Release(imgl1);
1481 static void test_IImageList_Add_Remove(void)
1493 /* create an imagelist to play with */
1494 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1495 ok(himl != 0,"failed to create imagelist\n");
1497 imgl = (IImageList *) himl;
1499 /* load the icons to add to the image list */
1500 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1501 ok(hicon1 != 0, "no hicon1\n");
1502 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1503 ok(hicon2 != 0, "no hicon2\n");
1504 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1505 ok(hicon3 != 0, "no hicon3\n");
1507 /* remove when nothing exists */
1508 hr = IImageList_Remove(imgl, 0);
1509 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1511 /* removing everything from an empty imagelist should succeed */
1512 hr = IImageList_Remove(imgl, -1);
1513 ok(hr == S_OK, "removed nonexistent icon\n");
1517 ok( IImageList_ReplaceIcon(imgl, -1, hicon1, &ret) == S_OK && (ret == 0),"failed to add icon1\n");
1519 ok( IImageList_ReplaceIcon(imgl, -1, hicon2, &ret) == S_OK && (ret == 1),"failed to add icon2\n");
1521 ok( IImageList_ReplaceIcon(imgl, -1, hicon3, &ret) == S_OK && (ret == 2),"failed to add icon3\n");
1523 /* remove an index out of range */
1524 ok( IImageList_Remove(imgl, 4711) == E_INVALIDARG, "got 0x%08x\n", hr);
1527 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1528 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1529 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1531 /* remove one extra */
1532 ok( IImageList_Remove(imgl, 0) == E_INVALIDARG, "got 0x%08x\n", hr);
1534 IImageList_Release(imgl);
1535 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1536 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1537 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1540 static void test_IImageList_Get_SetImageCount(void)
1547 /* create an imagelist to play with */
1548 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1549 ok(himl != 0,"failed to create imagelist\n");
1551 imgl = (IImageList *) himl;
1553 /* check SetImageCount/GetImageCount */
1554 hr = IImageList_SetImageCount(imgl, 3);
1555 ok(hr == S_OK, "got 0x%08x\n", hr);
1557 hr = IImageList_GetImageCount(imgl, &ret);
1558 ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
1559 hr = IImageList_SetImageCount(imgl, 1);
1560 ok(hr == S_OK, "got 0x%08x\n", hr);
1562 hr = IImageList_GetImageCount(imgl, &ret);
1563 ok(hr == S_OK && ret == 1, "invalid image count after decrease to 1\n");
1564 hr = IImageList_SetImageCount(imgl, 0);
1565 ok(hr == S_OK, "got 0x%08x\n", hr);
1567 hr = IImageList_GetImageCount(imgl, &ret);
1568 ok(hr == S_OK && ret == 0, "invalid image count after decrease to 0\n");
1570 IImageList_Release(imgl);
1573 static void test_IImageList_Draw(void)
1582 IMAGELISTDRAWPARAMS imldp;
1588 hwndfortest = create_a_window();
1589 hdc = GetDC(hwndfortest);
1590 ok(hdc!=NULL, "couldn't get DC\n");
1592 /* create an imagelist to play with */
1593 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1594 ok(himl!=0,"failed to create imagelist\n");
1596 imgl = (IImageList *) himl;
1598 /* load the icons to add to the image list */
1599 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1600 ok(hbm1 != 0, "no bitmap 1\n");
1601 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1602 ok(hbm2 != 0, "no bitmap 2\n");
1603 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1604 ok(hbm3 != 0, "no bitmap 3\n");
1608 ok( IImageList_Add(imgl, hbm1, 0, &ret) == S_OK && (ret == 0), "failed to add bitmap 1\n");
1610 ok( IImageList_Add(imgl, hbm2, 0, &ret) == S_OK && (ret == 1), "failed to add bitmap 2\n");
1612 ok( IImageList_SetImageCount(imgl, 3) == S_OK, "Setimage count failed\n");
1613 ok( IImageList_Replace(imgl, 2, hbm3, 0) == S_OK, "failed to replace bitmap 3\n");
1617 /* crashes on native */
1618 IImageList_Draw(imgl, NULL);
1621 memset(&imldp, 0, sizeof (imldp));
1622 hr = IImageList_Draw(imgl, &imldp);
1623 ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
1625 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
1629 REDRAW(hwndfortest);
1632 imldp.fStyle = SRCCOPY;
1633 imldp.rgbBk = CLR_DEFAULT;
1634 imldp.rgbFg = CLR_DEFAULT;
1637 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1639 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1641 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1643 ok( IImageList_Draw(imgl, &imldp) == E_INVALIDARG, "should fail\n");
1646 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 1st bitmap\n");
1647 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 2nd bitmap\n");
1648 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 3rd bitmap\n");
1651 IImageList_Release(imgl);
1653 /* bitmaps should not be deleted by the imagelist */
1654 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1655 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1656 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1658 ReleaseDC(hwndfortest, hdc);
1659 DestroyWindow(hwndfortest);
1662 static void test_IImageList_Merge(void)
1664 HIMAGELIST himl1, himl2;
1665 IImageList *imgl1, *imgl2, *merge;
1667 HWND hwnd = create_a_window();
1671 himl1 = ImageList_Create(32,32,0,0,3);
1672 ok(himl1 != NULL,"failed to create himl1\n");
1674 himl2 = ImageList_Create(32,32,0,0,3);
1675 ok(himl2 != NULL,"failed to create himl2\n");
1677 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1678 ok(hicon1 != NULL, "failed to create hicon1\n");
1680 if (!himl1 || !himl2 || !hicon1)
1683 /* cast to IImageList */
1684 imgl1 = (IImageList *) himl1;
1685 imgl2 = (IImageList *) himl2;
1688 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl2 failed\n");
1692 /* null cases that crash on native */
1693 IImageList_Merge(imgl1, -1, NULL, 0, 0, 0, &IID_IImageList, (void**)&merge);
1694 IImageList_Merge(imgl1, -1, (IUnknown*) imgl2, 0, 0, 0, &IID_IImageList, NULL);
1697 /* If himl1 has no images, merge still succeeds */
1698 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1699 ok(hr == S_OK, "merge himl1,-1 failed\n");
1700 if (hr == S_OK) IImageList_Release(merge);
1702 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1703 ok(hr == S_OK, "merge himl1,0 failed\n");
1704 if (hr == S_OK) IImageList_Release(merge);
1706 /* Same happens if himl2 is empty */
1707 IImageList_Release(imgl2);
1708 himl2 = ImageList_Create(32,32,0,0,3);
1709 ok(himl2 != NULL,"failed to recreate himl2\n");
1711 imgl2 = (IImageList *) himl2;
1713 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
1714 ok(hr == S_OK, "merge himl2,-1 failed\n");
1715 if (hr == S_OK) IImageList_Release(merge);
1717 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1718 ok(hr == S_OK, "merge himl2,0 failed\n");
1719 if (hr == S_OK) IImageList_Release(merge);
1721 /* Now try merging an image with itself */
1723 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"re-add icon1 to himl2 failed\n");
1725 hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1726 ok(hr == S_OK, "merge himl2 with itself failed\n");
1727 if (hr == S_OK) IImageList_Release(merge);
1729 /* Try merging 2 different image lists */
1731 ok( IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl1 failed\n");
1733 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1734 ok(hr == S_OK, "merge himl1 with himl2 failed\n");
1735 if (hr == S_OK) IImageList_Release(merge);
1737 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
1738 ok(hr == S_OK, "merge himl1 with himl2 8,16 failed\n");
1739 if (hr == S_OK) IImageList_Release(merge);
1741 IImageList_Release(imgl1);
1742 IImageList_Release(imgl2);
1744 DestroyIcon(hicon1);
1745 DestroyWindow(hwnd);
1748 static void test_iconsize(void)
1754 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1755 /* null pointers, not zero imagelist dimensions */
1756 ret = ImageList_GetIconSize(himl, NULL, NULL);
1757 ok(!ret, "got %d\n", ret);
1759 /* doesn't touch return pointers */
1761 ret = ImageList_GetIconSize(himl, &cx, NULL);
1762 ok(!ret, "got %d\n", ret);
1763 ok(cx == 0xdeadbeef, "got %d\n", cx);
1766 ret = ImageList_GetIconSize(himl, NULL, &cy);
1767 ok(!ret, "got %d\n", ret);
1768 ok(cy == 0xdeadbeef, "got %d\n", cy);
1770 ImageList_Destroy(himl);
1773 static void test_create(void)
1777 /* list with zero or negative image dimensions */
1778 himl = ImageList_Create(0, 0, ILC_COLOR16, 0, 3);
1779 ok(himl == NULL, "got %p\n", himl);
1781 himl = ImageList_Create(0, 16, ILC_COLOR16, 0, 3);
1782 ok(himl == NULL, "got %p\n", himl);
1784 himl = ImageList_Create(16, 0, ILC_COLOR16, 0, 3);
1785 ok(himl == NULL, "got %p\n", himl);
1787 himl = ImageList_Create(16, -1, ILC_COLOR16, 0, 3);
1788 ok(himl == NULL, "got %p\n", himl);
1790 himl = ImageList_Create(-1, 16, ILC_COLOR16, 0, 3);
1791 ok(himl == NULL, "got %p\n", himl);
1794 static void test_IImageList_Clone(void)
1796 IImageList *imgl, *imgl2;
1801 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1802 imgl = (IImageList*)himl;
1806 /* crashes on native */
1807 IImageList_Clone(imgl, &IID_IImageList, NULL);
1810 hr = IImageList_Clone(imgl, &IID_IImageList, (void**)&imgl2);
1811 ok(hr == S_OK, "got 0x%08x\n", hr);
1812 ref = IImageList_Release(imgl2);
1813 ok(ref == 0, "got %u\n", ref);
1815 IImageList_Release(imgl);
1818 static void test_IImageList_GetBkColor(void)
1825 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1826 imgl = (IImageList*)himl;
1830 /* crashes on native */
1831 IImageList_GetBkColor(imgl, NULL);
1834 hr = IImageList_GetBkColor(imgl, &color);
1835 ok(hr == S_OK, "got 0x%08x\n", hr);
1837 IImageList_Release(imgl);
1840 static void test_IImageList_SetBkColor(void)
1847 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1848 imgl = (IImageList*)himl;
1852 /* crashes on native */
1853 IImageList_SetBkColor(imgl, RGB(0, 0, 0), NULL);
1856 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1857 ok(hr == S_OK, "got 0x%08x\n", hr);
1859 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1860 ok(hr == S_OK, "got 0x%08x\n", hr);
1863 hr = IImageList_GetBkColor(imgl, &color);
1864 ok(hr == S_OK, "got 0x%08x\n", hr);
1865 ok(color == CLR_NONE, "got %x\n", color);
1867 IImageList_Release(imgl);
1870 static void test_IImageList_GetImageCount(void)
1877 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1878 imgl = (IImageList*)himl;
1882 /* crashes on native */
1883 IImageList_GetImageCount(imgl, NULL);
1887 hr = IImageList_GetImageCount(imgl, &count);
1888 ok(hr == S_OK, "got 0x%08x\n", hr);
1889 ok(count == 0, "got %d\n", count);
1891 IImageList_Release(imgl);
1894 static void test_IImageList_GetIconSize(void)
1901 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1902 imgl = (IImageList*)himl;
1904 hr = IImageList_GetIconSize(imgl, NULL, NULL);
1905 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1907 hr = IImageList_GetIconSize(imgl, &cx, NULL);
1908 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1910 hr = IImageList_GetIconSize(imgl, NULL, &cy);
1911 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1913 IImageList_Release(imgl);
1916 START_TEST(imagelist)
1918 ULONG_PTR ctx_cookie;
1921 HMODULE hComCtl32 = GetModuleHandle("comctl32.dll");
1922 pImageList_Create = NULL; /* These are not needed for non-v6.0 tests*/
1923 pImageList_Add = NULL;
1924 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1925 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1927 hinst = GetModuleHandleA(NULL);
1929 InitCommonControls();
1935 test_DrawIndirect();
1937 test_imagelist_storage();
1940 FreeLibrary(hComCtl32);
1942 /* Now perform v6 tests */
1944 if (!load_v6_module(&ctx_cookie, &hCtx))
1947 /* Reload comctl32 */
1948 hComCtl32 = LoadLibraryA("comctl32.dll");
1949 pImageList_Create = (void*)GetProcAddress(hComCtl32, "ImageList_Create");
1950 pImageList_Add = (void*)GetProcAddress(hComCtl32, "ImageList_Add");
1951 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1952 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1953 pImageList_CoCreateInstance = (void*)GetProcAddress(hComCtl32, "ImageList_CoCreateInstance");
1954 pHIMAGELIST_QueryInterface = (void*)GetProcAddress(hComCtl32, "HIMAGELIST_QueryInterface");
1956 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1959 test_ImageList_DrawIndirect();
1960 test_shell_imagelist();
1964 test_IImageList_Add_Remove();
1965 test_IImageList_Get_SetImageCount();
1966 test_IImageList_Draw();
1967 test_IImageList_Merge();
1968 test_IImageList_Clone();
1969 test_IImageList_GetBkColor();
1970 test_IImageList_SetBkColor();
1971 test_IImageList_GetImageCount();
1972 test_IImageList_GetIconSize();
1976 unload_v6_module(ctx_cookie, hCtx);