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(-1==ImageList_AddIcon((HIMAGELIST)0xdeadbeef, hicon1),"don't crash on bad handle\n");
377 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
378 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
379 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
382 static void test_imagecount(void)
386 ok(0==ImageList_GetImageCount((HIMAGELIST)0xdeadbeef),"don't crash on bad handle\n");
388 if (!pImageList_SetImageCount)
390 win_skip("ImageList_SetImageCount not available\n");
394 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
395 ok(himl!=0,"failed to create imagelist\n");
397 ok(pImageList_SetImageCount(himl, 3), "couldn't increase image count\n");
398 ok(ImageList_GetImageCount(himl) == 3, "invalid image count after increase\n");
399 ok(pImageList_SetImageCount(himl, 1), "couldn't decrease image count\n");
400 ok(ImageList_GetImageCount(himl) == 1, "invalid image count after decrease to 1\n");
401 ok(pImageList_SetImageCount(himl, 0), "couldn't decrease image count\n");
402 ok(ImageList_GetImageCount(himl) == 0, "invalid image count after decrease to 0\n");
404 ok(ImageList_Destroy(himl), "destroy imagelist failed\n");
407 static void test_DrawIndirect(void)
415 IMAGELISTDRAWPARAMS imldp;
419 if (!pImageList_DrawIndirect)
421 win_skip("ImageList_DrawIndirect not available, skipping test\n");
425 hwndfortest = create_a_window();
426 hdc = GetDC(hwndfortest);
427 ok(hdc!=NULL, "couldn't get DC\n");
429 /* create an imagelist to play with */
430 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
431 ok(himl!=0,"failed to create imagelist\n");
433 /* load the icons to add to the image list */
434 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
435 ok(hbm1 != 0, "no bitmap 1\n");
436 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
437 ok(hbm2 != 0, "no bitmap 2\n");
438 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
439 ok(hbm3 != 0, "no bitmap 3\n");
442 ok(0==ImageList_Add(himl, hbm1, 0),"failed to add bitmap 1\n");
443 ok(1==ImageList_Add(himl, hbm2, 0),"failed to add bitmap 2\n");
445 if (pImageList_SetImageCount)
447 ok(pImageList_SetImageCount(himl,3),"Setimage count failed\n");
448 /*ok(2==ImageList_Add(himl, hbm3, NULL),"failed to add bitmap 3\n"); */
449 ok(ImageList_Replace(himl, 2, hbm3, 0),"failed to replace bitmap 3\n");
452 memset(&imldp, 0, sizeof (imldp));
453 ok(!pImageList_DrawIndirect(&imldp), "zero data succeeded!\n");
454 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
455 ok(!pImageList_DrawIndirect(&imldp), "zero hdc succeeded!\n");
457 ok(!pImageList_DrawIndirect(&imldp),"zero himl succeeded!\n");
458 imldp.himl = (HIMAGELIST)0xdeadbeef;
459 ok(!pImageList_DrawIndirect(&imldp),"bad himl succeeded!\n");
465 imldp.fStyle = SRCCOPY;
466 imldp.rgbBk = CLR_DEFAULT;
467 imldp.rgbFg = CLR_DEFAULT;
470 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
472 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
474 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
476 ok(!pImageList_DrawIndirect(&imldp),"should fail\n");
479 ok(ImageList_Remove(himl, 0), "removing 1st bitmap\n");
480 ok(ImageList_Remove(himl, 0), "removing 2nd bitmap\n");
481 ok(ImageList_Remove(himl, 0), "removing 3rd bitmap\n");
484 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
486 /* bitmaps should not be deleted by the imagelist */
487 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
488 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
489 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
491 ReleaseDC(hwndfortest, hdc);
492 DestroyWindow(hwndfortest);
495 static void test_merge(void)
497 HIMAGELIST himl1, himl2, hmerge;
499 HWND hwnd = create_a_window();
501 himl1 = ImageList_Create(32,32,0,0,3);
502 ok(himl1 != NULL,"failed to create himl1\n");
504 himl2 = ImageList_Create(32,32,0,0,3);
505 ok(himl2 != NULL,"failed to create himl2\n");
507 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
508 ok(hicon1 != NULL, "failed to create hicon1\n");
510 if (!himl1 || !himl2 || !hicon1)
513 ok(0==ImageList_AddIcon(himl2, hicon1),"add icon1 to himl2 failed\n");
514 check_bits(hwnd, himl2, 0, 32, icon_bits, "add icon1 to himl2");
516 /* If himl1 has no images, merge still succeeds */
517 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
518 ok(hmerge != NULL, "merge himl1,-1 failed\n");
519 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,-1");
520 if (hmerge) ImageList_Destroy(hmerge);
522 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
523 ok(hmerge != NULL,"merge himl1,0 failed\n");
524 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,0");
525 if (hmerge) ImageList_Destroy(hmerge);
527 /* Same happens if himl2 is empty */
528 ImageList_Destroy(himl2);
529 himl2 = ImageList_Create(32,32,0,0,3);
530 ok(himl2 != NULL,"failed to recreate himl2\n");
534 hmerge = ImageList_Merge(himl1, -1, himl2, -1, 0, 0);
535 ok(hmerge != NULL, "merge himl2,-1 failed\n");
536 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,-1");
537 if (hmerge) ImageList_Destroy(hmerge);
539 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
540 ok(hmerge != NULL, "merge himl2,0 failed\n");
541 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,0");
542 if (hmerge) ImageList_Destroy(hmerge);
544 /* Now try merging an image with itself */
545 ok(0==ImageList_AddIcon(himl2, hicon1),"re-add icon1 to himl2 failed\n");
547 hmerge = ImageList_Merge(himl2, 0, himl2, 0, 0, 0);
548 ok(hmerge != NULL, "merge himl2 with itself failed\n");
549 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2 with itself");
550 if (hmerge) ImageList_Destroy(hmerge);
552 /* Try merging 2 different image lists */
553 ok(0==ImageList_AddIcon(himl1, hicon1),"add icon1 to himl1 failed\n");
555 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
556 ok(hmerge != NULL, "merge himl1 with himl2 failed\n");
557 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2");
558 if (hmerge) ImageList_Destroy(hmerge);
560 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 8, 16);
561 ok(hmerge != NULL, "merge himl1 with himl2 8,16 failed\n");
562 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2, 8,16");
563 if (hmerge) ImageList_Destroy(hmerge);
565 ImageList_Destroy(himl1);
566 ImageList_Destroy(himl2);
571 /*********************** imagelist storage test ***************************/
578 char *iml_data; /* written imagelist data */
582 static HRESULT STDMETHODCALLTYPE Test_Stream_QueryInterface(
591 static ULONG STDMETHODCALLTYPE Test_Stream_AddRef(
598 static ULONG STDMETHODCALLTYPE Test_Stream_Release(
605 static HRESULT STDMETHODCALLTYPE Test_Stream_Read(
615 static BOOL allocate_storage(struct my_IStream *my_is, ULONG add)
617 my_is->iml_data_size += add;
619 if (!my_is->iml_data)
620 my_is->iml_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data_size);
622 my_is->iml_data = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data, my_is->iml_data_size);
624 return my_is->iml_data ? TRUE : FALSE;
627 static HRESULT STDMETHODCALLTYPE Test_Stream_Write(
633 struct my_IStream *my_is = (struct my_IStream *)This;
634 ULONG current_iml_data_size = my_is->iml_data_size;
636 if (!allocate_storage(my_is, cb)) return E_FAIL;
638 memcpy(my_is->iml_data + current_iml_data_size, pv, cb);
639 if (pcbWritten) *pcbWritten = cb;
644 static HRESULT STDMETHODCALLTYPE Test_Stream_Seek(
646 LARGE_INTEGER dlibMove,
648 ULARGE_INTEGER* plibNewPosition)
654 static HRESULT STDMETHODCALLTYPE Test_Stream_SetSize(
656 ULARGE_INTEGER libNewSize)
662 static HRESULT STDMETHODCALLTYPE Test_Stream_CopyTo(
666 ULARGE_INTEGER* pcbRead,
667 ULARGE_INTEGER* pcbWritten)
673 static HRESULT STDMETHODCALLTYPE Test_Stream_Commit(
675 DWORD grfCommitFlags)
681 static HRESULT STDMETHODCALLTYPE Test_Stream_Revert(
688 static HRESULT STDMETHODCALLTYPE Test_Stream_LockRegion(
690 ULARGE_INTEGER libOffset,
698 static HRESULT STDMETHODCALLTYPE Test_Stream_UnlockRegion(
700 ULARGE_INTEGER libOffset,
708 static HRESULT STDMETHODCALLTYPE Test_Stream_Stat(
717 static HRESULT STDMETHODCALLTYPE Test_Stream_Clone(
725 static const IStreamVtbl Test_Stream_Vtbl =
727 Test_Stream_QueryInterface,
737 Test_Stream_LockRegion,
738 Test_Stream_UnlockRegion,
743 static struct my_IStream Test_Stream = { { &Test_Stream_Vtbl }, 0, 0 };
745 static INT DIB_GetWidthBytes( int width, int bpp )
747 return ((width * bpp + 31) / 8) & ~3;
750 static void check_bitmap_data(const char *bm_data, ULONG bm_data_size,
751 INT width, INT height, INT bpp,
754 const BITMAPFILEHEADER *bmfh = (const BITMAPFILEHEADER *)bm_data;
755 const BITMAPINFOHEADER *bmih = (const BITMAPINFOHEADER *)(bm_data + sizeof(*bmfh));
756 ULONG hdr_size, image_size;
758 hdr_size = sizeof(*bmfh) + sizeof(*bmih);
759 if (bmih->biBitCount <= 8) hdr_size += (1 << bpp) * sizeof(RGBQUAD);
761 ok(bmfh->bfType == (('M' << 8) | 'B'), "wrong bfType 0x%02x\n", bmfh->bfType);
762 ok(bmfh->bfSize == hdr_size, "wrong bfSize 0x%02x\n", bmfh->bfSize);
763 ok(bmfh->bfReserved1 == 0, "wrong bfReserved1 0x%02x\n", bmfh->bfReserved1);
764 ok(bmfh->bfReserved2 == 0, "wrong bfReserved2 0x%02x\n", bmfh->bfReserved2);
765 ok(bmfh->bfOffBits == hdr_size, "wrong bfOffBits 0x%02x\n", bmfh->bfOffBits);
767 ok(bmih->biSize == sizeof(*bmih), "wrong biSize %d\n", bmih->biSize);
768 ok(bmih->biWidth == width, "wrong biWidth %d (expected %d)\n", bmih->biWidth, width);
769 ok(bmih->biHeight == height, "wrong biHeight %d (expected %d)\n", bmih->biHeight, height);
770 ok(bmih->biPlanes == 1, "wrong biPlanes %d\n", bmih->biPlanes);
771 ok(bmih->biBitCount == bpp, "wrong biBitCount %d\n", bmih->biBitCount);
773 image_size = DIB_GetWidthBytes(bmih->biWidth, bmih->biBitCount) * bmih->biHeight;
774 ok(bmih->biSizeImage == image_size, "wrong biSizeImage %u\n", bmih->biSizeImage);
779 sprintf(fname, "bmp_%s.bmp", comment);
780 f = fopen(fname, "wb");
781 fwrite(bm_data, 1, bm_data_size, f);
787 static void check_ilhead_data(const char *ilh_data, INT cx, INT cy, INT cur, INT max, INT grow)
789 const ILHEAD *ilh = (const ILHEAD *)ilh_data;
791 ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
792 ok(ilh->usVersion == 0x101, "wrong usVersion %x (expected 0x101)\n", ilh->usVersion);
793 ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
794 ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
795 ok(ilh->cGrow == grow, "wrong cGrow %d (expected %d)\n", ilh->cGrow, grow);
796 ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
797 ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
798 ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
799 ok(ilh->flags == ILC_COLOR24, "wrong flags %04x\n", ilh->flags);
800 ok(ilh->ovls[0] == -1 ||
801 ilh->ovls[0] == 0, /* win95 */
802 "wrong ovls[0] %04x\n", ilh->ovls[0]);
803 ok(ilh->ovls[1] == -1 ||
804 ilh->ovls[1] == 0, /* win95 */
805 "wrong ovls[1] %04x\n", ilh->ovls[1]);
806 ok(ilh->ovls[2] == -1 ||
807 ilh->ovls[2] == 0, /* win95 */
808 "wrong ovls[2] %04x\n", ilh->ovls[2]);
809 ok(ilh->ovls[3] == -1 ||
810 ilh->ovls[3] == 0, /* win95 */
811 "wrong ovls[3] %04x\n", ilh->ovls[3]);
814 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
817 char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
818 BITMAPINFO *bmi = (BITMAPINFO *)bmibuf;
819 HBITMAP hbmp, hbmp_old;
821 RECT rc = { 0, 0, cx, cy };
823 hdc = CreateCompatibleDC(0);
825 memset(bmi, 0, sizeof(*bmi));
826 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
827 bmi->bmiHeader.biHeight = cx;
828 bmi->bmiHeader.biWidth = cy;
829 bmi->bmiHeader.biBitCount = 24;
830 bmi->bmiHeader.biPlanes = 1;
831 bmi->bmiHeader.biCompression = BI_RGB;
832 hbmp = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
834 hbmp_old = SelectObject(hdc, hbmp);
836 hbrush = CreateSolidBrush(color);
837 FillRect(hdc, &rc, hbrush);
838 DeleteObject(hbrush);
840 DrawText(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
842 SelectObject(hdc, hbmp_old);
848 #define iml_clear_stream_data() \
849 HeapFree(GetProcessHeap(), 0, Test_Stream.iml_data); \
850 Test_Stream.iml_data = NULL; \
851 Test_Stream.iml_data_size = 0;
853 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, INT grow,
854 INT width, INT height, INT bpp, const char *comment)
858 trace("%s\n", comment);
860 ret = ImageList_GetImageCount(himl);
861 ok(ret == cur, "expected image count %d got %d\n", cur, ret);
863 ret = ImageList_GetIconSize(himl, &cxx, &cyy);
864 ok(ret, "ImageList_GetIconSize failed\n");
865 ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx);
866 ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy);
868 iml_clear_stream_data();
869 ret = ImageList_Write(himl, &Test_Stream.is);
870 ok(ret, "ImageList_Write failed\n");
872 ok(Test_Stream.iml_data != 0, "ImageList_Write didn't write any data\n");
873 ok(Test_Stream.iml_data_size > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n");
875 check_ilhead_data(Test_Stream.iml_data, cx, cy, cur, max, grow);
876 check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD),
877 Test_Stream.iml_data_size - sizeof(ILHEAD),
878 width, height, bpp, comment);
881 static void image_list_init(HIMAGELIST himl)
887 static const struct test_data
890 INT cx, cy, cur, max, grow, width, height, bpp;
894 { 255, BMP_CX, BMP_CX, 1, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 1" },
895 { 170, BMP_CX, BMP_CX, 2, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 2" },
896 { 85, BMP_CX, BMP_CX, 3, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 3" },
897 { 0, BMP_CX, BMP_CX, 4, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 4" },
898 { 0, BMP_CX, BMP_CX, 5, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 5" },
899 { 85, BMP_CX, BMP_CX, 6, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 6" },
900 { 170, BMP_CX, BMP_CX, 7, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 7" },
901 { 255, BMP_CX, BMP_CX, 8, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 8" },
902 { 255, BMP_CX, BMP_CX, 9, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 9" },
903 { 170, BMP_CX, BMP_CX, 10, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 10" },
904 { 85, BMP_CX, BMP_CX, 11, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 11" },
905 { 0, BMP_CX, BMP_CX, 12, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 12" },
906 { 0, BMP_CX, BMP_CX, 13, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 13" },
907 { 85, BMP_CX, BMP_CX, 14, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 14" },
908 { 170, BMP_CX, BMP_CX, 15, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 15" },
909 { 255, BMP_CX, BMP_CX, 16, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 16" },
910 { 255, BMP_CX, BMP_CX, 17, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 17" },
911 { 170, BMP_CX, BMP_CX, 18, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 18" },
912 { 85, BMP_CX, BMP_CX, 19, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 19" },
913 { 0, BMP_CX, BMP_CX, 20, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 20" },
914 { 0, BMP_CX, BMP_CX, 21, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 21" },
915 { 85, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 22" },
916 { 170, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 23" },
917 { 255, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 24" }
920 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 0");
922 #define add_bitmap(grey) \
923 sprintf(comment, "%d", n++); \
924 hbm = create_bitmap(BMP_CX, BMP_CX, RGB((grey),(grey),(grey)), comment); \
925 ImageList_Add(himl, hbm, NULL); \
928 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
930 add_bitmap(td[i].grey);
931 check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, td[i].grow,
932 td[i].width, td[i].height, td[i].bpp, td[i].comment);
937 static void test_imagelist_storage(void)
943 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
944 ok(himl != 0, "ImageList_Create failed\n");
946 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "empty");
948 image_list_init(himl);
949 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "orig");
951 ret = ImageList_Remove(himl, 4);
952 ok(ret, "ImageList_Remove failed\n");
953 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "1");
955 ret = ImageList_Remove(himl, 5);
956 ok(ret, "ImageList_Remove failed\n");
957 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "2");
959 ret = ImageList_Remove(himl, 6);
960 ok(ret, "ImageList_Remove failed\n");
961 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "3");
963 ret = ImageList_Remove(himl, 7);
964 ok(ret, "ImageList_Remove failed\n");
965 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "4");
967 ret = ImageList_Remove(himl, -2);
968 ok(!ret, "ImageList_Remove(-2) should fail\n");
969 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "5");
971 ret = ImageList_Remove(himl, 20);
972 ok(!ret, "ImageList_Remove(20) should fail\n");
973 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "6");
975 ret = ImageList_Remove(himl, -1);
976 ok(ret, "ImageList_Remove(-1) failed\n");
977 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, 4, BMP_CX * 4, BMP_CX * 1, 24, "7");
979 ret = ImageList_Destroy(himl);
980 ok(ret, "ImageList_Destroy failed\n");
982 iml_clear_stream_data();
984 /* test ImageList_Create storage allocation */
986 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 0, 32);
987 ok(himl != 0, "ImageList_Create failed\n");
988 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 32, BMP_CX * 4, BMP_CX * 1, 24, "init 0 grow 32");
989 hbm = create_bitmap(BMP_CX * 9, BMP_CX, 0, "9");
990 ret = ImageList_Add(himl, hbm, NULL);
991 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
992 check_iml_data(himl, BMP_CX, BMP_CX, 1, 34, 32, BMP_CX * 4, BMP_CX * 9, 24, "add 1 x 9");
994 ret = ImageList_Destroy(himl);
995 ok(ret, "ImageList_Destroy failed\n");
996 iml_clear_stream_data();
998 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 4);
999 ok(himl != 0, "ImageList_Create failed\n");
1000 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, 24, "init 4 grow 4");
1001 hbm = create_bitmap(BMP_CX, BMP_CX * 9, 0, "9");
1002 ret = ImageList_Add(himl, hbm, NULL);
1003 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1004 check_iml_data(himl, BMP_CX, BMP_CX, 9, 15, 4, BMP_CX * 4, BMP_CX * 4, 24, "add 9 x 1");
1005 ret = ImageList_Add(himl, hbm, NULL);
1006 ok(ret == 9, "ImageList_Add returned %d, expected 9\n", ret);
1007 check_iml_data(himl, BMP_CX, BMP_CX, 18, 25, 4, BMP_CX * 4, BMP_CX * 7, 24, "add 9 x 1");
1009 ret = ImageList_Destroy(himl);
1010 ok(ret, "ImageList_Destroy failed\n");
1011 iml_clear_stream_data();
1013 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 207, 209);
1014 ok(himl != 0, "ImageList_Create failed\n");
1015 check_iml_data(himl, BMP_CX, BMP_CX, 0, 208, 212, BMP_CX * 4, BMP_CX * 52, 24, "init 207 grow 209");
1016 ret = ImageList_Destroy(himl);
1017 ok(ret, "ImageList_Destroy failed\n");
1018 iml_clear_stream_data();
1020 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 209, 207);
1021 ok(himl != 0, "ImageList_Create failed\n");
1022 check_iml_data(himl, BMP_CX, BMP_CX, 0, 210, 208, BMP_CX * 4, BMP_CX * 53, 24, "init 209 grow 207");
1023 ret = ImageList_Destroy(himl);
1024 ok(ret, "ImageList_Destroy failed\n");
1025 iml_clear_stream_data();
1027 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 14, 4);
1028 ok(himl != 0, "ImageList_Create failed\n");
1029 check_iml_data(himl, BMP_CX, BMP_CX, 0, 15, 4, BMP_CX * 4, BMP_CX * 4, 24, "init 14 grow 4");
1030 ret = ImageList_Destroy(himl);
1031 ok(ret, "ImageList_Destroy failed\n");
1032 iml_clear_stream_data();
1034 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 5, 9);
1035 ok(himl != 0, "ImageList_Create failed\n");
1036 check_iml_data(himl, BMP_CX, BMP_CX, 0, 6, 12, BMP_CX * 4, BMP_CX * 2, 24, "init 5 grow 9");
1037 ret = ImageList_Destroy(himl);
1038 ok(ret, "ImageList_Destroy failed\n");
1039 iml_clear_stream_data();
1041 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 9, 5);
1042 ok(himl != 0, "ImageList_Create failed\n");
1043 check_iml_data(himl, BMP_CX, BMP_CX, 0, 10, 8, BMP_CX * 4, BMP_CX * 3, 24, "init 9 grow 5");
1044 ret = ImageList_Destroy(himl);
1045 ok(ret, "ImageList_Destroy failed\n");
1046 iml_clear_stream_data();
1048 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 2, 4);
1049 ok(himl != 0, "ImageList_Create failed\n");
1050 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX * 1, 24, "init 2 grow 4");
1051 ret = ImageList_Destroy(himl);
1052 ok(ret, "ImageList_Destroy failed\n");
1053 iml_clear_stream_data();
1055 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 2);
1056 ok(himl != 0, "ImageList_Create failed\n");
1057 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, 24, "init 4 grow 2");
1058 ret = ImageList_Destroy(himl);
1059 ok(ret, "ImageList_Destroy failed\n");
1060 iml_clear_stream_data();
1063 static void test_shell_imagelist(void)
1065 BOOL (WINAPI *pSHGetImageList)(INT, REFIID, void**);
1066 IImageList *iml = NULL;
1073 /* Try to load function from shell32 */
1074 hShell32 = LoadLibrary("shell32.dll");
1075 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1077 if (!pSHGetImageList)
1079 win_skip("SHGetImageList not available, skipping test\n");
1083 /* Get system image list */
1084 hr = (pSHGetImageList)(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1086 ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1091 IImageList_GetImageCount(iml, &out);
1092 ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1094 /* Fetch the small icon size */
1095 cx = GetSystemMetrics(SM_CXSMICON);
1096 cy = GetSystemMetrics(SM_CYSMICON);
1098 /* Check icon size matches */
1099 IImageList_GetImageRect(iml, 0, &rect);
1100 ok(((rect.right == cx) && (rect.bottom == cy)),
1101 "IImageList_GetImageRect returned r:%d,b:%d\n",
1102 rect.right, rect.bottom);
1104 IImageList_Release(iml);
1105 FreeLibrary(hShell32);
1108 static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
1111 UINT32 *buffer = NULL;
1112 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
1115 hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1116 ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1118 if(!hBitmap || !buffer)
1120 DeleteObject(hBitmap);
1130 static BOOL colour_match(UINT32 x, UINT32 y)
1132 const INT32 tolerance = 8;
1134 const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1135 const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1136 const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1138 return (dr <= tolerance && dg <= tolerance && db <= tolerance);
1141 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1142 UINT32 expected, int line)
1144 bits[0] = 0x00FFFFFF;
1145 pImageList_DrawIndirect(ildp);
1146 ok(colour_match(bits[0], expected),
1147 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1148 bits[0] & 0x00FFFFFF, expected, line);
1152 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1153 UINT fStyle, UINT32 expected, int line)
1155 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1156 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1157 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1160 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1161 DWORD dwRop, UINT32 expected, int line)
1163 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1164 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1165 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1168 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1169 UINT fState, DWORD Frame, UINT32 expected, int line)
1171 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1172 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1173 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1176 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1177 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1178 UINT32 broken_expected, int line)
1180 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1181 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1182 bits[0] = 0x00FFFFFF;
1183 pImageList_DrawIndirect(&ildp);
1184 ok(colour_match(bits[0], expected) ||
1185 broken(colour_match(bits[0], broken_expected)),
1186 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1187 bits[0] & 0x00FFFFFF, expected, line);
1190 static void test_ImageList_DrawIndirect(void)
1192 HIMAGELIST himl = NULL;
1195 HBITMAP hbmOld = NULL, hbmDst = NULL;
1196 HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1197 HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
1198 int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1200 UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1201 int bpp, broken_value;
1203 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1206 hdcDst = CreateCompatibleDC(0);
1207 ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1210 bpp = GetDeviceCaps(hdcDst, BITSPIXEL);
1212 hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1213 ok(hbmMask != 0, "CreateBitmap failed\n");
1214 if(!hbmMask) goto cleanup;
1216 hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1217 ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1218 if(!hbmInverseMask) goto cleanup;
1220 himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1221 ok(himl != 0, "ImageList_Create failed\n");
1222 if(!himl) goto cleanup;
1224 /* Add a no-alpha image */
1225 hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
1226 if(!hbmImage) goto cleanup;
1228 iImage = pImageList_Add(himl, hbmImage, hbmMask);
1229 ok(iImage != -1, "ImageList_Add failed\n");
1230 if(iImage == -1) goto cleanup;
1232 /* Add an alpha image */
1233 hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
1234 if(!hbmAlphaImage) goto cleanup;
1236 iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1237 ok(iAlphaImage != -1, "ImageList_Add failed\n");
1238 if(iAlphaImage == -1) goto cleanup;
1240 /* Add a transparent alpha image */
1241 hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
1242 if(!hbmTransparentImage) goto cleanup;
1244 iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1245 ok(iTransparentImage != -1, "ImageList_Add failed\n");
1246 if(iTransparentImage == -1) goto cleanup;
1249 bitmapInfo.bmiHeader.biBitCount = 32;
1250 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1251 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1252 if (!hbmDst || !bits)
1254 hbmOld = SelectObject(hdcDst, hbmDst);
1256 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1257 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1258 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
1259 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1260 else broken_value = 0x00B4BDC4;
1261 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1262 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1263 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1264 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1266 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
1267 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
1269 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1270 else broken_value = 0x009DA8B1;
1271 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1272 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1273 else broken_value = 0x008C99A3;
1274 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1275 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
1276 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
1277 todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
1279 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
1281 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1282 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
1284 /* ILD_ROP is ignored when the image has an alpha channel */
1285 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
1286 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
1288 todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
1289 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
1291 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
1292 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
1294 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
1295 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
1296 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
1301 SelectObject(hdcDst, hbmOld);
1303 DeleteObject(hbmDst);
1309 DeleteObject(hbmMask);
1311 DeleteObject(hbmInverseMask);
1314 DeleteObject(hbmImage);
1316 DeleteObject(hbmAlphaImage);
1317 if(hbmTransparentImage)
1318 DeleteObject(hbmTransparentImage);
1322 ret = ImageList_Destroy(himl);
1323 ok(ret, "ImageList_Destroy failed\n");
1327 static void test_iimagelist(void)
1329 IImageList *imgl, *imgl2;
1334 if (!pHIMAGELIST_QueryInterface)
1336 win_skip("XP imagelist functions not available\n");
1340 /* test reference counting on destruction */
1341 imgl = (IImageList*)createImageList(32, 32);
1342 ret = IUnknown_AddRef(imgl);
1343 ok(ret == 2, "Expected 2, got %d\n", ret);
1344 ret = ImageList_Destroy((HIMAGELIST)imgl);
1345 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1346 ret = ImageList_Destroy((HIMAGELIST)imgl);
1347 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1348 ret = ImageList_Destroy((HIMAGELIST)imgl);
1349 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
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 = IImageList_Release(imgl);
1357 ok(ret == 0, "Expected 0, got %d\n", ret);
1358 ret = ImageList_Destroy((HIMAGELIST)imgl);
1359 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1361 /* ref counting, HIMAGELIST_QueryInterface adds a reference */
1362 imgl = (IImageList*)createImageList(32, 32);
1363 hr = pHIMAGELIST_QueryInterface((HIMAGELIST)imgl, &IID_IImageList, (void**)&imgl2);
1364 ok(hr == S_OK, "got 0x%08x\n", hr);
1365 ok(imgl2 == imgl, "got different pointer\n");
1366 ret = IImageList_Release(imgl);
1367 ok(ret == 1, "got %u\n", ret);
1368 IImageList_Release(imgl);
1370 if (!pImageList_CoCreateInstance)
1372 win_skip("Vista imagelist functions not available\n");
1376 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1377 ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
1380 IImageList_Release(imgl);
1382 himl = createImageList(32, 32);
1387 hr = (pHIMAGELIST_QueryInterface)(himl, &IID_IImageList, (void **) &imgl);
1388 ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
1391 IImageList_Release(imgl);
1393 ImageList_Destroy(himl);
1396 static void test_hotspot_v6(void)
1407 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
1408 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
1415 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
1416 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
1417 IImageList *imgl1, *imgl2;
1420 /* cast to IImageList */
1421 imgl1 = (IImageList *) himl1;
1422 imgl2 = (IImageList *) himl2;
1424 for (i = 0; i < HOTSPOTS_MAX; i++) {
1425 for (j = 0; j < HOTSPOTS_MAX; j++) {
1426 int dx1 = hotspots[i].dx;
1427 int dy1 = hotspots[i].dy;
1428 int dx2 = hotspots[j].dx;
1429 int dy2 = hotspots[j].dy;
1430 int correctx, correcty, newx, newy;
1432 IImageList *imglNew;
1435 hr = IImageList_BeginDrag(imgl1, 0, dx1, dy1);
1436 ok(SUCCEEDED(hr), "BeginDrag failed for { %d, %d }\n", dx1, dy1);
1437 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
1439 /* check merging the dragged image with a second image */
1440 hr = IImageList_SetDragCursorImage(imgl2, (IUnknown *) imgl2, 0, dx2, dy2);
1441 ok(SUCCEEDED(hr), "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
1442 dx1, dy1, dx2, dy2);
1443 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
1445 /* check new hotspot, it should be the same like the old one */
1446 hr = IImageList_GetDragImage(imgl2, NULL, &ppt, &IID_IImageList, (PVOID *) &imglNew);
1447 ok(SUCCEEDED(hr), "GetDragImage failed\n");
1448 ok(ppt.x == dx1 && ppt.y == dy1,
1449 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
1450 dx1, dy1, ppt.x, ppt.y);
1451 /* check size of new dragged image */
1452 IImageList_GetIconSize(imglNew, &newx, &newy);
1453 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
1454 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
1455 ok(newx == correctx && newy == correcty,
1456 "Expected drag image size [%d,%d] got [%d,%d]\n",
1457 correctx, correcty, newx, newy);
1458 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
1459 IImageList_EndDrag(imgl2);
1467 IImageList_Release(imgl2);
1468 IImageList_Release(imgl1);
1471 static void test_IImageList_Add_Remove(void)
1483 /* create an imagelist to play with */
1484 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1485 ok(himl != 0,"failed to create imagelist\n");
1487 imgl = (IImageList *) himl;
1489 /* load the icons to add to the image list */
1490 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1491 ok(hicon1 != 0, "no hicon1\n");
1492 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1493 ok(hicon2 != 0, "no hicon2\n");
1494 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1495 ok(hicon3 != 0, "no hicon3\n");
1497 /* remove when nothing exists */
1498 hr = IImageList_Remove(imgl, 0);
1499 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1501 /* removing everything from an empty imagelist should succeed */
1502 hr = IImageList_Remove(imgl, -1);
1503 ok(hr == S_OK, "removed nonexistent icon\n");
1507 ok( IImageList_ReplaceIcon(imgl, -1, hicon1, &ret) == S_OK && (ret == 0),"failed to add icon1\n");
1509 ok( IImageList_ReplaceIcon(imgl, -1, hicon2, &ret) == S_OK && (ret == 1),"failed to add icon2\n");
1511 ok( IImageList_ReplaceIcon(imgl, -1, hicon3, &ret) == S_OK && (ret == 2),"failed to add icon3\n");
1513 /* remove an index out of range */
1514 ok( IImageList_Remove(imgl, 4711) == E_INVALIDARG, "got 0x%08x\n", hr);
1517 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1518 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1519 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1521 /* remove one extra */
1522 ok( IImageList_Remove(imgl, 0) == E_INVALIDARG, "got 0x%08x\n", hr);
1524 IImageList_Release(imgl);
1525 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1526 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1527 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1530 static void test_IImageList_Get_SetImageCount(void)
1537 /* create an imagelist to play with */
1538 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1539 ok(himl != 0,"failed to create imagelist\n");
1541 imgl = (IImageList *) himl;
1543 /* check SetImageCount/GetImageCount */
1544 hr = IImageList_SetImageCount(imgl, 3);
1545 ok(hr == S_OK, "got 0x%08x\n", hr);
1547 hr = IImageList_GetImageCount(imgl, &ret);
1548 ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
1549 hr = IImageList_SetImageCount(imgl, 1);
1550 ok(hr == S_OK, "got 0x%08x\n", hr);
1552 hr = IImageList_GetImageCount(imgl, &ret);
1553 ok(hr == S_OK && ret == 1, "invalid image count after decrease to 1\n");
1554 hr = IImageList_SetImageCount(imgl, 0);
1555 ok(hr == S_OK, "got 0x%08x\n", hr);
1557 hr = IImageList_GetImageCount(imgl, &ret);
1558 ok(hr == S_OK && ret == 0, "invalid image count after decrease to 0\n");
1560 IImageList_Release(imgl);
1563 static void test_IImageList_Draw(void)
1572 IMAGELISTDRAWPARAMS imldp;
1578 hwndfortest = create_a_window();
1579 hdc = GetDC(hwndfortest);
1580 ok(hdc!=NULL, "couldn't get DC\n");
1582 /* create an imagelist to play with */
1583 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1584 ok(himl!=0,"failed to create imagelist\n");
1586 imgl = (IImageList *) himl;
1588 /* load the icons to add to the image list */
1589 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1590 ok(hbm1 != 0, "no bitmap 1\n");
1591 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1592 ok(hbm2 != 0, "no bitmap 2\n");
1593 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1594 ok(hbm3 != 0, "no bitmap 3\n");
1598 ok( IImageList_Add(imgl, hbm1, 0, &ret) == S_OK && (ret == 0), "failed to add bitmap 1\n");
1600 ok( IImageList_Add(imgl, hbm2, 0, &ret) == S_OK && (ret == 1), "failed to add bitmap 2\n");
1602 ok( IImageList_SetImageCount(imgl, 3) == S_OK, "Setimage count failed\n");
1603 ok( IImageList_Replace(imgl, 2, hbm3, 0) == S_OK, "failed to replace bitmap 3\n");
1607 /* crashes on native */
1608 IImageList_Draw(imgl, NULL);
1611 memset(&imldp, 0, sizeof (imldp));
1612 hr = IImageList_Draw(imgl, &imldp);
1613 ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
1615 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
1619 REDRAW(hwndfortest);
1622 imldp.fStyle = SRCCOPY;
1623 imldp.rgbBk = CLR_DEFAULT;
1624 imldp.rgbFg = CLR_DEFAULT;
1627 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1629 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1631 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1633 ok( IImageList_Draw(imgl, &imldp) == E_INVALIDARG, "should fail\n");
1636 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 1st bitmap\n");
1637 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 2nd bitmap\n");
1638 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 3rd bitmap\n");
1641 IImageList_Release(imgl);
1643 /* bitmaps should not be deleted by the imagelist */
1644 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1645 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1646 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1648 ReleaseDC(hwndfortest, hdc);
1649 DestroyWindow(hwndfortest);
1652 static void test_IImageList_Merge(void)
1654 HIMAGELIST himl1, himl2;
1655 IImageList *imgl1, *imgl2, *merge;
1657 HWND hwnd = create_a_window();
1661 himl1 = ImageList_Create(32,32,0,0,3);
1662 ok(himl1 != NULL,"failed to create himl1\n");
1664 himl2 = ImageList_Create(32,32,0,0,3);
1665 ok(himl2 != NULL,"failed to create himl2\n");
1667 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1668 ok(hicon1 != NULL, "failed to create hicon1\n");
1670 if (!himl1 || !himl2 || !hicon1)
1673 /* cast to IImageList */
1674 imgl1 = (IImageList *) himl1;
1675 imgl2 = (IImageList *) himl2;
1678 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl2 failed\n");
1682 /* null cases that crash on native */
1683 IImageList_Merge(imgl1, -1, NULL, 0, 0, 0, &IID_IImageList, (void**)&merge);
1684 IImageList_Merge(imgl1, -1, (IUnknown*) imgl2, 0, 0, 0, &IID_IImageList, NULL);
1687 /* If himl1 has no images, merge still succeeds */
1688 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1689 ok(hr == S_OK, "merge himl1,-1 failed\n");
1690 if (hr == S_OK) IImageList_Release(merge);
1692 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1693 ok(hr == S_OK, "merge himl1,0 failed\n");
1694 if (hr == S_OK) IImageList_Release(merge);
1696 /* Same happens if himl2 is empty */
1697 IImageList_Release(imgl2);
1698 himl2 = ImageList_Create(32,32,0,0,3);
1699 ok(himl2 != NULL,"failed to recreate himl2\n");
1701 imgl2 = (IImageList *) himl2;
1703 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
1704 ok(hr == S_OK, "merge himl2,-1 failed\n");
1705 if (hr == S_OK) IImageList_Release(merge);
1707 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1708 ok(hr == S_OK, "merge himl2,0 failed\n");
1709 if (hr == S_OK) IImageList_Release(merge);
1711 /* Now try merging an image with itself */
1713 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"re-add icon1 to himl2 failed\n");
1715 hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1716 ok(hr == S_OK, "merge himl2 with itself failed\n");
1717 if (hr == S_OK) IImageList_Release(merge);
1719 /* Try merging 2 different image lists */
1721 ok( IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl1 failed\n");
1723 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1724 ok(hr == S_OK, "merge himl1 with himl2 failed\n");
1725 if (hr == S_OK) IImageList_Release(merge);
1727 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
1728 ok(hr == S_OK, "merge himl1 with himl2 8,16 failed\n");
1729 if (hr == S_OK) IImageList_Release(merge);
1731 IImageList_Release(imgl1);
1732 IImageList_Release(imgl2);
1734 DestroyIcon(hicon1);
1735 DestroyWindow(hwnd);
1738 static void test_iconsize(void)
1744 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1745 /* null pointers, not zero imagelist dimensions */
1746 ret = ImageList_GetIconSize(himl, NULL, NULL);
1747 ok(!ret, "got %d\n", ret);
1749 /* doesn't touch return pointers */
1751 ret = ImageList_GetIconSize(himl, &cx, NULL);
1752 ok(!ret, "got %d\n", ret);
1753 ok(cx == 0x1abe11ed, "got %d\n", cx);
1756 ret = ImageList_GetIconSize(himl, NULL, &cy);
1757 ok(!ret, "got %d\n", ret);
1758 ok(cy == 0x1abe11ed, "got %d\n", cy);
1760 ImageList_Destroy(himl);
1762 ret = ImageList_GetIconSize((HIMAGELIST)0xdeadbeef, &cx, &cy);
1763 ok(!ret, "got %d\n", ret);
1766 static void test_create_destroy(void)
1771 /* list with zero or negative image dimensions */
1772 himl = ImageList_Create(0, 0, ILC_COLOR16, 0, 3);
1773 ok(himl == NULL, "got %p\n", himl);
1775 himl = ImageList_Create(0, 16, ILC_COLOR16, 0, 3);
1776 ok(himl == NULL, "got %p\n", himl);
1778 himl = ImageList_Create(16, 0, ILC_COLOR16, 0, 3);
1779 ok(himl == NULL, "got %p\n", himl);
1781 himl = ImageList_Create(16, -1, ILC_COLOR16, 0, 3);
1782 ok(himl == NULL, "got %p\n", himl);
1784 himl = ImageList_Create(-1, 16, ILC_COLOR16, 0, 3);
1785 ok(himl == NULL, "got %p\n", himl);
1787 rc = ImageList_Destroy((HIMAGELIST)0xdeadbeef);
1788 ok(rc == FALSE, "ImageList_Destroy(0xdeadbeef) should fail and not crash\n");
1791 static void test_IImageList_Clone(void)
1793 IImageList *imgl, *imgl2;
1798 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1799 imgl = (IImageList*)himl;
1803 /* crashes on native */
1804 IImageList_Clone(imgl, &IID_IImageList, NULL);
1807 hr = IImageList_Clone(imgl, &IID_IImageList, (void**)&imgl2);
1808 ok(hr == S_OK, "got 0x%08x\n", hr);
1809 ref = IImageList_Release(imgl2);
1810 ok(ref == 0, "got %u\n", ref);
1812 IImageList_Release(imgl);
1815 static void test_IImageList_GetBkColor(void)
1822 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1823 imgl = (IImageList*)himl;
1827 /* crashes on native */
1828 IImageList_GetBkColor(imgl, NULL);
1831 hr = IImageList_GetBkColor(imgl, &color);
1832 ok(hr == S_OK, "got 0x%08x\n", hr);
1834 IImageList_Release(imgl);
1837 static void test_IImageList_SetBkColor(void)
1844 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1845 imgl = (IImageList*)himl;
1849 /* crashes on native */
1850 IImageList_SetBkColor(imgl, RGB(0, 0, 0), NULL);
1853 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1854 ok(hr == S_OK, "got 0x%08x\n", hr);
1856 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1857 ok(hr == S_OK, "got 0x%08x\n", hr);
1860 hr = IImageList_GetBkColor(imgl, &color);
1861 ok(hr == S_OK, "got 0x%08x\n", hr);
1862 ok(color == CLR_NONE, "got %x\n", color);
1864 IImageList_Release(imgl);
1867 static void test_IImageList_GetImageCount(void)
1874 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1875 imgl = (IImageList*)himl;
1879 /* crashes on native */
1880 IImageList_GetImageCount(imgl, NULL);
1884 hr = IImageList_GetImageCount(imgl, &count);
1885 ok(hr == S_OK, "got 0x%08x\n", hr);
1886 ok(count == 0, "got %d\n", count);
1888 IImageList_Release(imgl);
1891 static void test_IImageList_GetIconSize(void)
1898 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1899 imgl = (IImageList*)himl;
1901 hr = IImageList_GetIconSize(imgl, NULL, NULL);
1902 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1904 hr = IImageList_GetIconSize(imgl, &cx, NULL);
1905 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1907 hr = IImageList_GetIconSize(imgl, NULL, &cy);
1908 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1910 IImageList_Release(imgl);
1913 START_TEST(imagelist)
1915 ULONG_PTR ctx_cookie;
1918 HMODULE hComCtl32 = GetModuleHandle("comctl32.dll");
1919 pImageList_Create = NULL; /* These are not needed for non-v6.0 tests*/
1920 pImageList_Add = NULL;
1921 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1922 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1924 hinst = GetModuleHandleA(NULL);
1926 InitCommonControls();
1928 test_create_destroy();
1932 test_DrawIndirect();
1934 test_imagelist_storage();
1937 FreeLibrary(hComCtl32);
1939 /* Now perform v6 tests */
1941 if (!load_v6_module(&ctx_cookie, &hCtx))
1944 /* Reload comctl32 */
1945 hComCtl32 = LoadLibraryA("comctl32.dll");
1946 pImageList_Create = (void*)GetProcAddress(hComCtl32, "ImageList_Create");
1947 pImageList_Add = (void*)GetProcAddress(hComCtl32, "ImageList_Add");
1948 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1949 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1950 pImageList_CoCreateInstance = (void*)GetProcAddress(hComCtl32, "ImageList_CoCreateInstance");
1951 pHIMAGELIST_QueryInterface = (void*)GetProcAddress(hComCtl32, "HIMAGELIST_QueryInterface");
1953 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1956 test_ImageList_DrawIndirect();
1957 test_shell_imagelist();
1961 test_IImageList_Add_Remove();
1962 test_IImageList_Get_SetImageCount();
1963 test_IImageList_Draw();
1964 test_IImageList_Merge();
1965 test_IImageList_Clone();
1966 test_IImageList_GetBkColor();
1967 test_IImageList_SetBkColor();
1968 test_IImageList_GetImageCount();
1969 test_IImageList_GetIconSize();
1973 unload_v6_module(ctx_cookie, hCtx);