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 ***************************/
577 IStream IStream_iface;
578 char *iml_data; /* written imagelist data */
582 struct my_IStream *impl_from_IStream(IStream *iface)
584 return CONTAINING_RECORD(iface, struct my_IStream, IStream_iface);
587 static HRESULT STDMETHODCALLTYPE Test_Stream_QueryInterface(IStream *iface, REFIID riid,
594 static ULONG STDMETHODCALLTYPE Test_Stream_AddRef(IStream *iface)
600 static ULONG STDMETHODCALLTYPE Test_Stream_Release(IStream *iface)
606 static HRESULT STDMETHODCALLTYPE Test_Stream_Read(IStream *iface, void *pv, ULONG cb,
613 static BOOL allocate_storage(struct my_IStream *my_is, ULONG add)
615 my_is->iml_data_size += add;
617 if (!my_is->iml_data)
618 my_is->iml_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data_size);
620 my_is->iml_data = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data, my_is->iml_data_size);
622 return my_is->iml_data ? TRUE : FALSE;
625 static HRESULT STDMETHODCALLTYPE Test_Stream_Write(IStream *iface, const void *pv, ULONG cb,
628 struct my_IStream *my_is = impl_from_IStream(iface);
629 ULONG current_iml_data_size = my_is->iml_data_size;
631 if (!allocate_storage(my_is, cb)) return E_FAIL;
633 memcpy(my_is->iml_data + current_iml_data_size, pv, cb);
634 if (pcbWritten) *pcbWritten = cb;
639 static HRESULT STDMETHODCALLTYPE Test_Stream_Seek(IStream *iface, LARGE_INTEGER dlibMove,
640 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
646 static HRESULT STDMETHODCALLTYPE Test_Stream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
652 static HRESULT STDMETHODCALLTYPE Test_Stream_CopyTo(IStream *iface, IStream *pstm,
653 ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead,
654 ULARGE_INTEGER *pcbWritten)
660 static HRESULT STDMETHODCALLTYPE Test_Stream_Commit(IStream *iface, DWORD grfCommitFlags)
666 static HRESULT STDMETHODCALLTYPE Test_Stream_Revert(IStream *iface)
672 static HRESULT STDMETHODCALLTYPE Test_Stream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset,
673 ULARGE_INTEGER cb, DWORD dwLockType)
679 static HRESULT STDMETHODCALLTYPE Test_Stream_UnlockRegion(IStream *iface, ULARGE_INTEGER libOffset,
680 ULARGE_INTEGER cb, DWORD dwLockType)
686 static HRESULT STDMETHODCALLTYPE Test_Stream_Stat(IStream *iface, STATSTG *pstatstg,
693 static HRESULT STDMETHODCALLTYPE Test_Stream_Clone(IStream *iface, IStream **ppstm)
699 static const IStreamVtbl Test_Stream_Vtbl =
701 Test_Stream_QueryInterface,
711 Test_Stream_LockRegion,
712 Test_Stream_UnlockRegion,
717 static struct my_IStream Test_Stream = { { &Test_Stream_Vtbl }, 0, 0 };
719 static INT DIB_GetWidthBytes( int width, int bpp )
721 return ((width * bpp + 31) / 8) & ~3;
724 static void check_bitmap_data(const char *bm_data, ULONG bm_data_size,
725 INT width, INT height, INT bpp,
728 const BITMAPFILEHEADER *bmfh = (const BITMAPFILEHEADER *)bm_data;
729 const BITMAPINFOHEADER *bmih = (const BITMAPINFOHEADER *)(bm_data + sizeof(*bmfh));
730 ULONG hdr_size, image_size;
732 hdr_size = sizeof(*bmfh) + sizeof(*bmih);
733 if (bmih->biBitCount <= 8) hdr_size += (1 << bpp) * sizeof(RGBQUAD);
735 ok(bmfh->bfType == (('M' << 8) | 'B'), "wrong bfType 0x%02x\n", bmfh->bfType);
736 ok(bmfh->bfSize == hdr_size, "wrong bfSize 0x%02x\n", bmfh->bfSize);
737 ok(bmfh->bfReserved1 == 0, "wrong bfReserved1 0x%02x\n", bmfh->bfReserved1);
738 ok(bmfh->bfReserved2 == 0, "wrong bfReserved2 0x%02x\n", bmfh->bfReserved2);
739 ok(bmfh->bfOffBits == hdr_size, "wrong bfOffBits 0x%02x\n", bmfh->bfOffBits);
741 ok(bmih->biSize == sizeof(*bmih), "wrong biSize %d\n", bmih->biSize);
742 ok(bmih->biWidth == width, "wrong biWidth %d (expected %d)\n", bmih->biWidth, width);
743 ok(bmih->biHeight == height, "wrong biHeight %d (expected %d)\n", bmih->biHeight, height);
744 ok(bmih->biPlanes == 1, "wrong biPlanes %d\n", bmih->biPlanes);
745 ok(bmih->biBitCount == bpp, "wrong biBitCount %d\n", bmih->biBitCount);
747 image_size = DIB_GetWidthBytes(bmih->biWidth, bmih->biBitCount) * bmih->biHeight;
748 ok(bmih->biSizeImage == image_size, "wrong biSizeImage %u\n", bmih->biSizeImage);
753 sprintf(fname, "bmp_%s.bmp", comment);
754 f = fopen(fname, "wb");
755 fwrite(bm_data, 1, bm_data_size, f);
761 static void check_ilhead_data(const char *ilh_data, INT cx, INT cy, INT cur, INT max, INT grow)
763 const ILHEAD *ilh = (const ILHEAD *)ilh_data;
765 ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
766 ok(ilh->usVersion == 0x101, "wrong usVersion %x (expected 0x101)\n", ilh->usVersion);
767 ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
768 ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
769 ok(ilh->cGrow == grow, "wrong cGrow %d (expected %d)\n", ilh->cGrow, grow);
770 ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
771 ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
772 ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
773 ok(ilh->flags == ILC_COLOR24, "wrong flags %04x\n", ilh->flags);
774 ok(ilh->ovls[0] == -1, "wrong ovls[0] %04x\n", ilh->ovls[0]);
775 ok(ilh->ovls[1] == -1, "wrong ovls[1] %04x\n", ilh->ovls[1]);
776 ok(ilh->ovls[2] == -1, "wrong ovls[2] %04x\n", ilh->ovls[2]);
777 ok(ilh->ovls[3] == -1, "wrong ovls[3] %04x\n", ilh->ovls[3]);
780 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
783 char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
784 BITMAPINFO *bmi = (BITMAPINFO *)bmibuf;
785 HBITMAP hbmp, hbmp_old;
787 RECT rc = { 0, 0, cx, cy };
789 hdc = CreateCompatibleDC(0);
791 memset(bmi, 0, sizeof(*bmi));
792 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
793 bmi->bmiHeader.biHeight = cx;
794 bmi->bmiHeader.biWidth = cy;
795 bmi->bmiHeader.biBitCount = 24;
796 bmi->bmiHeader.biPlanes = 1;
797 bmi->bmiHeader.biCompression = BI_RGB;
798 hbmp = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
800 hbmp_old = SelectObject(hdc, hbmp);
802 hbrush = CreateSolidBrush(color);
803 FillRect(hdc, &rc, hbrush);
804 DeleteObject(hbrush);
806 DrawText(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
808 SelectObject(hdc, hbmp_old);
814 #define iml_clear_stream_data() \
815 HeapFree(GetProcessHeap(), 0, Test_Stream.iml_data); \
816 Test_Stream.iml_data = NULL; \
817 Test_Stream.iml_data_size = 0;
819 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, INT grow,
820 INT width, INT height, INT bpp, const char *comment)
824 trace("%s\n", comment);
826 ret = ImageList_GetImageCount(himl);
827 ok(ret == cur, "expected image count %d got %d\n", cur, ret);
829 ret = ImageList_GetIconSize(himl, &cxx, &cyy);
830 ok(ret, "ImageList_GetIconSize failed\n");
831 ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx);
832 ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy);
834 iml_clear_stream_data();
835 ret = ImageList_Write(himl, &Test_Stream.IStream_iface);
836 ok(ret, "ImageList_Write failed\n");
838 ok(Test_Stream.iml_data != 0, "ImageList_Write didn't write any data\n");
839 ok(Test_Stream.iml_data_size > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n");
841 check_ilhead_data(Test_Stream.iml_data, cx, cy, cur, max, grow);
842 check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD),
843 Test_Stream.iml_data_size - sizeof(ILHEAD),
844 width, height, bpp, comment);
847 static void image_list_init(HIMAGELIST himl)
853 static const struct test_data
856 INT cx, cy, cur, max, grow, width, height, bpp;
860 { 255, BMP_CX, BMP_CX, 1, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 1" },
861 { 170, BMP_CX, BMP_CX, 2, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 2" },
862 { 85, BMP_CX, BMP_CX, 3, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 3" },
863 { 0, BMP_CX, BMP_CX, 4, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 4" },
864 { 0, BMP_CX, BMP_CX, 5, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 5" },
865 { 85, BMP_CX, BMP_CX, 6, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 6" },
866 { 170, BMP_CX, BMP_CX, 7, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 7" },
867 { 255, BMP_CX, BMP_CX, 8, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 8" },
868 { 255, BMP_CX, BMP_CX, 9, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 9" },
869 { 170, BMP_CX, BMP_CX, 10, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 10" },
870 { 85, BMP_CX, BMP_CX, 11, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 11" },
871 { 0, BMP_CX, BMP_CX, 12, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 12" },
872 { 0, BMP_CX, BMP_CX, 13, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 13" },
873 { 85, BMP_CX, BMP_CX, 14, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 14" },
874 { 170, BMP_CX, BMP_CX, 15, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 15" },
875 { 255, BMP_CX, BMP_CX, 16, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 16" },
876 { 255, BMP_CX, BMP_CX, 17, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 17" },
877 { 170, BMP_CX, BMP_CX, 18, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 18" },
878 { 85, BMP_CX, BMP_CX, 19, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 19" },
879 { 0, BMP_CX, BMP_CX, 20, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 20" },
880 { 0, BMP_CX, BMP_CX, 21, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 21" },
881 { 85, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 22" },
882 { 170, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 23" },
883 { 255, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 24" }
886 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 0");
888 #define add_bitmap(grey) \
889 sprintf(comment, "%d", n++); \
890 hbm = create_bitmap(BMP_CX, BMP_CX, RGB((grey),(grey),(grey)), comment); \
891 ImageList_Add(himl, hbm, NULL); \
894 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
896 add_bitmap(td[i].grey);
897 check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, td[i].grow,
898 td[i].width, td[i].height, td[i].bpp, td[i].comment);
903 static void test_imagelist_storage(void)
909 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
910 ok(himl != 0, "ImageList_Create failed\n");
912 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "empty");
914 image_list_init(himl);
915 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "orig");
917 ret = ImageList_Remove(himl, 4);
918 ok(ret, "ImageList_Remove failed\n");
919 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "1");
921 ret = ImageList_Remove(himl, 5);
922 ok(ret, "ImageList_Remove failed\n");
923 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "2");
925 ret = ImageList_Remove(himl, 6);
926 ok(ret, "ImageList_Remove failed\n");
927 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "3");
929 ret = ImageList_Remove(himl, 7);
930 ok(ret, "ImageList_Remove failed\n");
931 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "4");
933 ret = ImageList_Remove(himl, -2);
934 ok(!ret, "ImageList_Remove(-2) should fail\n");
935 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "5");
937 ret = ImageList_Remove(himl, 20);
938 ok(!ret, "ImageList_Remove(20) should fail\n");
939 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "6");
941 ret = ImageList_Remove(himl, -1);
942 ok(ret, "ImageList_Remove(-1) failed\n");
943 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, 4, BMP_CX * 4, BMP_CX * 1, 24, "7");
945 ret = ImageList_Destroy(himl);
946 ok(ret, "ImageList_Destroy failed\n");
948 iml_clear_stream_data();
950 /* test ImageList_Create storage allocation */
952 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 0, 32);
953 ok(himl != 0, "ImageList_Create failed\n");
954 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 32, BMP_CX * 4, BMP_CX * 1, 24, "init 0 grow 32");
955 hbm = create_bitmap(BMP_CX * 9, BMP_CX, 0, "9");
956 ret = ImageList_Add(himl, hbm, NULL);
957 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
958 check_iml_data(himl, BMP_CX, BMP_CX, 1, 34, 32, BMP_CX * 4, BMP_CX * 9, 24, "add 1 x 9");
960 ret = ImageList_Destroy(himl);
961 ok(ret, "ImageList_Destroy failed\n");
962 iml_clear_stream_data();
964 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 4);
965 ok(himl != 0, "ImageList_Create failed\n");
966 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, 24, "init 4 grow 4");
967 hbm = create_bitmap(BMP_CX, BMP_CX * 9, 0, "9");
968 ret = ImageList_Add(himl, hbm, NULL);
969 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
970 check_iml_data(himl, BMP_CX, BMP_CX, 9, 15, 4, BMP_CX * 4, BMP_CX * 4, 24, "add 9 x 1");
971 ret = ImageList_Add(himl, hbm, NULL);
972 ok(ret == 9, "ImageList_Add returned %d, expected 9\n", ret);
973 check_iml_data(himl, BMP_CX, BMP_CX, 18, 25, 4, BMP_CX * 4, BMP_CX * 7, 24, "add 9 x 1");
975 ret = ImageList_Destroy(himl);
976 ok(ret, "ImageList_Destroy failed\n");
977 iml_clear_stream_data();
979 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 207, 209);
980 ok(himl != 0, "ImageList_Create failed\n");
981 check_iml_data(himl, BMP_CX, BMP_CX, 0, 208, 212, BMP_CX * 4, BMP_CX * 52, 24, "init 207 grow 209");
982 ret = ImageList_Destroy(himl);
983 ok(ret, "ImageList_Destroy failed\n");
984 iml_clear_stream_data();
986 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 209, 207);
987 ok(himl != 0, "ImageList_Create failed\n");
988 check_iml_data(himl, BMP_CX, BMP_CX, 0, 210, 208, BMP_CX * 4, BMP_CX * 53, 24, "init 209 grow 207");
989 ret = ImageList_Destroy(himl);
990 ok(ret, "ImageList_Destroy failed\n");
991 iml_clear_stream_data();
993 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 14, 4);
994 ok(himl != 0, "ImageList_Create failed\n");
995 check_iml_data(himl, BMP_CX, BMP_CX, 0, 15, 4, BMP_CX * 4, BMP_CX * 4, 24, "init 14 grow 4");
996 ret = ImageList_Destroy(himl);
997 ok(ret, "ImageList_Destroy failed\n");
998 iml_clear_stream_data();
1000 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 5, 9);
1001 ok(himl != 0, "ImageList_Create failed\n");
1002 check_iml_data(himl, BMP_CX, BMP_CX, 0, 6, 12, BMP_CX * 4, BMP_CX * 2, 24, "init 5 grow 9");
1003 ret = ImageList_Destroy(himl);
1004 ok(ret, "ImageList_Destroy failed\n");
1005 iml_clear_stream_data();
1007 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 9, 5);
1008 ok(himl != 0, "ImageList_Create failed\n");
1009 check_iml_data(himl, BMP_CX, BMP_CX, 0, 10, 8, BMP_CX * 4, BMP_CX * 3, 24, "init 9 grow 5");
1010 ret = ImageList_Destroy(himl);
1011 ok(ret, "ImageList_Destroy failed\n");
1012 iml_clear_stream_data();
1014 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 2, 4);
1015 ok(himl != 0, "ImageList_Create failed\n");
1016 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX * 1, 24, "init 2 grow 4");
1017 ret = ImageList_Destroy(himl);
1018 ok(ret, "ImageList_Destroy failed\n");
1019 iml_clear_stream_data();
1021 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 2);
1022 ok(himl != 0, "ImageList_Create failed\n");
1023 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, 24, "init 4 grow 2");
1024 ret = ImageList_Destroy(himl);
1025 ok(ret, "ImageList_Destroy failed\n");
1026 iml_clear_stream_data();
1029 static void test_shell_imagelist(void)
1031 BOOL (WINAPI *pSHGetImageList)(INT, REFIID, void**);
1032 IImageList *iml = NULL;
1039 /* Try to load function from shell32 */
1040 hShell32 = LoadLibrary("shell32.dll");
1041 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1043 if (!pSHGetImageList)
1045 win_skip("SHGetImageList not available, skipping test\n");
1049 /* Get system image list */
1050 hr = (pSHGetImageList)(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1052 ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1057 IImageList_GetImageCount(iml, &out);
1058 ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1060 /* Fetch the small icon size */
1061 cx = GetSystemMetrics(SM_CXSMICON);
1062 cy = GetSystemMetrics(SM_CYSMICON);
1064 /* Check icon size matches */
1065 IImageList_GetImageRect(iml, 0, &rect);
1066 ok(((rect.right == cx) && (rect.bottom == cy)),
1067 "IImageList_GetImageRect returned r:%d,b:%d\n",
1068 rect.right, rect.bottom);
1070 IImageList_Release(iml);
1071 FreeLibrary(hShell32);
1074 static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
1077 UINT32 *buffer = NULL;
1078 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
1081 hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1082 ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1084 if(!hBitmap || !buffer)
1086 DeleteObject(hBitmap);
1096 static BOOL colour_match(UINT32 x, UINT32 y)
1098 const INT32 tolerance = 8;
1100 const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1101 const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1102 const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1104 return (dr <= tolerance && dg <= tolerance && db <= tolerance);
1107 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1108 UINT32 expected, int line)
1110 bits[0] = 0x00FFFFFF;
1111 pImageList_DrawIndirect(ildp);
1112 ok(colour_match(bits[0], expected),
1113 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1114 bits[0] & 0x00FFFFFF, expected, line);
1118 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1119 UINT fStyle, UINT32 expected, int line)
1121 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1122 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1123 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1126 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1127 DWORD dwRop, UINT32 expected, int line)
1129 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1130 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1131 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1134 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1135 UINT fState, DWORD Frame, UINT32 expected, int line)
1137 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1138 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1139 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1142 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1143 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1144 UINT32 broken_expected, int line)
1146 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1147 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1148 bits[0] = 0x00FFFFFF;
1149 pImageList_DrawIndirect(&ildp);
1150 ok(colour_match(bits[0], expected) ||
1151 broken(colour_match(bits[0], broken_expected)),
1152 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1153 bits[0] & 0x00FFFFFF, expected, line);
1156 static void test_ImageList_DrawIndirect(void)
1158 HIMAGELIST himl = NULL;
1161 HBITMAP hbmOld = NULL, hbmDst = NULL;
1162 HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1163 HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
1164 int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1166 UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1167 int bpp, broken_value;
1169 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1172 hdcDst = CreateCompatibleDC(0);
1173 ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1176 bpp = GetDeviceCaps(hdcDst, BITSPIXEL);
1178 hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1179 ok(hbmMask != 0, "CreateBitmap failed\n");
1180 if(!hbmMask) goto cleanup;
1182 hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1183 ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1184 if(!hbmInverseMask) goto cleanup;
1186 himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1187 ok(himl != 0, "ImageList_Create failed\n");
1188 if(!himl) goto cleanup;
1190 /* Add a no-alpha image */
1191 hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
1192 if(!hbmImage) goto cleanup;
1194 iImage = pImageList_Add(himl, hbmImage, hbmMask);
1195 ok(iImage != -1, "ImageList_Add failed\n");
1196 if(iImage == -1) goto cleanup;
1198 /* Add an alpha image */
1199 hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
1200 if(!hbmAlphaImage) goto cleanup;
1202 iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1203 ok(iAlphaImage != -1, "ImageList_Add failed\n");
1204 if(iAlphaImage == -1) goto cleanup;
1206 /* Add a transparent alpha image */
1207 hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
1208 if(!hbmTransparentImage) goto cleanup;
1210 iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1211 ok(iTransparentImage != -1, "ImageList_Add failed\n");
1212 if(iTransparentImage == -1) goto cleanup;
1215 bitmapInfo.bmiHeader.biBitCount = 32;
1216 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1217 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1218 if (!hbmDst || !bits)
1220 hbmOld = SelectObject(hdcDst, hbmDst);
1222 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1223 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1224 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
1225 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1226 else broken_value = 0x00B4BDC4;
1227 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1228 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1229 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1230 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1232 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
1233 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
1235 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1236 else broken_value = 0x009DA8B1;
1237 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1238 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1239 else broken_value = 0x008C99A3;
1240 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1241 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
1242 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
1243 todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
1245 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
1247 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1248 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
1250 /* ILD_ROP is ignored when the image has an alpha channel */
1251 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
1252 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
1254 todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
1255 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
1257 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
1258 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
1260 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
1261 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
1262 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
1267 SelectObject(hdcDst, hbmOld);
1269 DeleteObject(hbmDst);
1275 DeleteObject(hbmMask);
1277 DeleteObject(hbmInverseMask);
1280 DeleteObject(hbmImage);
1282 DeleteObject(hbmAlphaImage);
1283 if(hbmTransparentImage)
1284 DeleteObject(hbmTransparentImage);
1288 ret = ImageList_Destroy(himl);
1289 ok(ret, "ImageList_Destroy failed\n");
1293 static void test_iimagelist(void)
1295 IImageList *imgl, *imgl2;
1300 if (!pHIMAGELIST_QueryInterface)
1302 win_skip("XP imagelist functions not available\n");
1306 /* test reference counting on destruction */
1307 imgl = (IImageList*)createImageList(32, 32);
1308 ret = IUnknown_AddRef(imgl);
1309 ok(ret == 2, "Expected 2, got %d\n", ret);
1310 ret = ImageList_Destroy((HIMAGELIST)imgl);
1311 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1312 ret = ImageList_Destroy((HIMAGELIST)imgl);
1313 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1314 ret = ImageList_Destroy((HIMAGELIST)imgl);
1315 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1317 imgl = (IImageList*)createImageList(32, 32);
1318 ret = IUnknown_AddRef(imgl);
1319 ok(ret == 2, "Expected 2, got %d\n", ret);
1320 ret = ImageList_Destroy((HIMAGELIST)imgl);
1321 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1322 ret = IImageList_Release(imgl);
1323 ok(ret == 0, "Expected 0, got %d\n", ret);
1324 ret = ImageList_Destroy((HIMAGELIST)imgl);
1325 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1327 /* ref counting, HIMAGELIST_QueryInterface adds a reference */
1328 imgl = (IImageList*)createImageList(32, 32);
1329 hr = pHIMAGELIST_QueryInterface((HIMAGELIST)imgl, &IID_IImageList, (void**)&imgl2);
1330 ok(hr == S_OK, "got 0x%08x\n", hr);
1331 ok(imgl2 == imgl, "got different pointer\n");
1332 ret = IImageList_Release(imgl);
1333 ok(ret == 1, "got %u\n", ret);
1334 IImageList_Release(imgl);
1336 if (!pImageList_CoCreateInstance)
1338 win_skip("Vista imagelist functions not available\n");
1342 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1343 ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
1346 IImageList_Release(imgl);
1348 himl = createImageList(32, 32);
1353 hr = (pHIMAGELIST_QueryInterface)(himl, &IID_IImageList, (void **) &imgl);
1354 ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
1357 IImageList_Release(imgl);
1359 ImageList_Destroy(himl);
1362 static void test_hotspot_v6(void)
1373 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
1374 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
1381 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
1382 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
1383 IImageList *imgl1, *imgl2;
1386 /* cast to IImageList */
1387 imgl1 = (IImageList *) himl1;
1388 imgl2 = (IImageList *) himl2;
1390 for (i = 0; i < HOTSPOTS_MAX; i++) {
1391 for (j = 0; j < HOTSPOTS_MAX; j++) {
1392 int dx1 = hotspots[i].dx;
1393 int dy1 = hotspots[i].dy;
1394 int dx2 = hotspots[j].dx;
1395 int dy2 = hotspots[j].dy;
1396 int correctx, correcty, newx, newy;
1398 IImageList *imglNew;
1401 hr = IImageList_BeginDrag(imgl1, 0, dx1, dy1);
1402 ok(SUCCEEDED(hr), "BeginDrag failed for { %d, %d }\n", dx1, dy1);
1403 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
1405 /* check merging the dragged image with a second image */
1406 hr = IImageList_SetDragCursorImage(imgl2, (IUnknown *) imgl2, 0, dx2, dy2);
1407 ok(SUCCEEDED(hr), "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
1408 dx1, dy1, dx2, dy2);
1409 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
1411 /* check new hotspot, it should be the same like the old one */
1412 hr = IImageList_GetDragImage(imgl2, NULL, &ppt, &IID_IImageList, (PVOID *) &imglNew);
1413 ok(SUCCEEDED(hr), "GetDragImage failed\n");
1414 ok(ppt.x == dx1 && ppt.y == dy1,
1415 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
1416 dx1, dy1, ppt.x, ppt.y);
1417 /* check size of new dragged image */
1418 IImageList_GetIconSize(imglNew, &newx, &newy);
1419 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
1420 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
1421 ok(newx == correctx && newy == correcty,
1422 "Expected drag image size [%d,%d] got [%d,%d]\n",
1423 correctx, correcty, newx, newy);
1424 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
1425 IImageList_EndDrag(imgl2);
1433 IImageList_Release(imgl2);
1434 IImageList_Release(imgl1);
1437 static void test_IImageList_Add_Remove(void)
1449 /* create an imagelist to play with */
1450 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1451 ok(himl != 0,"failed to create imagelist\n");
1453 imgl = (IImageList *) himl;
1455 /* load the icons to add to the image list */
1456 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1457 ok(hicon1 != 0, "no hicon1\n");
1458 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1459 ok(hicon2 != 0, "no hicon2\n");
1460 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1461 ok(hicon3 != 0, "no hicon3\n");
1463 /* remove when nothing exists */
1464 hr = IImageList_Remove(imgl, 0);
1465 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1467 /* removing everything from an empty imagelist should succeed */
1468 hr = IImageList_Remove(imgl, -1);
1469 ok(hr == S_OK, "removed nonexistent icon\n");
1473 ok( IImageList_ReplaceIcon(imgl, -1, hicon1, &ret) == S_OK && (ret == 0),"failed to add icon1\n");
1475 ok( IImageList_ReplaceIcon(imgl, -1, hicon2, &ret) == S_OK && (ret == 1),"failed to add icon2\n");
1477 ok( IImageList_ReplaceIcon(imgl, -1, hicon3, &ret) == S_OK && (ret == 2),"failed to add icon3\n");
1479 /* remove an index out of range */
1480 ok( IImageList_Remove(imgl, 4711) == E_INVALIDARG, "got 0x%08x\n", hr);
1483 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1484 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1485 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1487 /* remove one extra */
1488 ok( IImageList_Remove(imgl, 0) == E_INVALIDARG, "got 0x%08x\n", hr);
1490 IImageList_Release(imgl);
1491 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1492 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1493 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1496 static void test_IImageList_Get_SetImageCount(void)
1503 /* create an imagelist to play with */
1504 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1505 ok(himl != 0,"failed to create imagelist\n");
1507 imgl = (IImageList *) himl;
1509 /* check SetImageCount/GetImageCount */
1510 hr = IImageList_SetImageCount(imgl, 3);
1511 ok(hr == S_OK, "got 0x%08x\n", hr);
1513 hr = IImageList_GetImageCount(imgl, &ret);
1514 ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
1515 hr = IImageList_SetImageCount(imgl, 1);
1516 ok(hr == S_OK, "got 0x%08x\n", hr);
1518 hr = IImageList_GetImageCount(imgl, &ret);
1519 ok(hr == S_OK && ret == 1, "invalid image count after decrease to 1\n");
1520 hr = IImageList_SetImageCount(imgl, 0);
1521 ok(hr == S_OK, "got 0x%08x\n", hr);
1523 hr = IImageList_GetImageCount(imgl, &ret);
1524 ok(hr == S_OK && ret == 0, "invalid image count after decrease to 0\n");
1526 IImageList_Release(imgl);
1529 static void test_IImageList_Draw(void)
1538 IMAGELISTDRAWPARAMS imldp;
1544 hwndfortest = create_a_window();
1545 hdc = GetDC(hwndfortest);
1546 ok(hdc!=NULL, "couldn't get DC\n");
1548 /* create an imagelist to play with */
1549 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1550 ok(himl!=0,"failed to create imagelist\n");
1552 imgl = (IImageList *) himl;
1554 /* load the icons to add to the image list */
1555 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1556 ok(hbm1 != 0, "no bitmap 1\n");
1557 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1558 ok(hbm2 != 0, "no bitmap 2\n");
1559 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1560 ok(hbm3 != 0, "no bitmap 3\n");
1564 ok( IImageList_Add(imgl, hbm1, 0, &ret) == S_OK && (ret == 0), "failed to add bitmap 1\n");
1566 ok( IImageList_Add(imgl, hbm2, 0, &ret) == S_OK && (ret == 1), "failed to add bitmap 2\n");
1568 ok( IImageList_SetImageCount(imgl, 3) == S_OK, "Setimage count failed\n");
1569 ok( IImageList_Replace(imgl, 2, hbm3, 0) == S_OK, "failed to replace bitmap 3\n");
1573 /* crashes on native */
1574 IImageList_Draw(imgl, NULL);
1577 memset(&imldp, 0, sizeof (imldp));
1578 hr = IImageList_Draw(imgl, &imldp);
1579 ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
1581 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
1585 REDRAW(hwndfortest);
1588 imldp.fStyle = SRCCOPY;
1589 imldp.rgbBk = CLR_DEFAULT;
1590 imldp.rgbFg = CLR_DEFAULT;
1593 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1595 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1597 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1599 ok( IImageList_Draw(imgl, &imldp) == E_INVALIDARG, "should fail\n");
1602 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 1st bitmap\n");
1603 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 2nd bitmap\n");
1604 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 3rd bitmap\n");
1607 IImageList_Release(imgl);
1609 /* bitmaps should not be deleted by the imagelist */
1610 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1611 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1612 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1614 ReleaseDC(hwndfortest, hdc);
1615 DestroyWindow(hwndfortest);
1618 static void test_IImageList_Merge(void)
1620 HIMAGELIST himl1, himl2;
1621 IImageList *imgl1, *imgl2, *merge;
1623 HWND hwnd = create_a_window();
1627 himl1 = ImageList_Create(32,32,0,0,3);
1628 ok(himl1 != NULL,"failed to create himl1\n");
1630 himl2 = ImageList_Create(32,32,0,0,3);
1631 ok(himl2 != NULL,"failed to create himl2\n");
1633 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1634 ok(hicon1 != NULL, "failed to create hicon1\n");
1636 if (!himl1 || !himl2 || !hicon1)
1639 /* cast to IImageList */
1640 imgl1 = (IImageList *) himl1;
1641 imgl2 = (IImageList *) himl2;
1644 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl2 failed\n");
1648 /* null cases that crash on native */
1649 IImageList_Merge(imgl1, -1, NULL, 0, 0, 0, &IID_IImageList, (void**)&merge);
1650 IImageList_Merge(imgl1, -1, (IUnknown*) imgl2, 0, 0, 0, &IID_IImageList, NULL);
1653 /* If himl1 has no images, merge still succeeds */
1654 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1655 ok(hr == S_OK, "merge himl1,-1 failed\n");
1656 if (hr == S_OK) IImageList_Release(merge);
1658 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1659 ok(hr == S_OK, "merge himl1,0 failed\n");
1660 if (hr == S_OK) IImageList_Release(merge);
1662 /* Same happens if himl2 is empty */
1663 IImageList_Release(imgl2);
1664 himl2 = ImageList_Create(32,32,0,0,3);
1665 ok(himl2 != NULL,"failed to recreate himl2\n");
1667 imgl2 = (IImageList *) himl2;
1669 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
1670 ok(hr == S_OK, "merge himl2,-1 failed\n");
1671 if (hr == S_OK) IImageList_Release(merge);
1673 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1674 ok(hr == S_OK, "merge himl2,0 failed\n");
1675 if (hr == S_OK) IImageList_Release(merge);
1677 /* Now try merging an image with itself */
1679 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"re-add icon1 to himl2 failed\n");
1681 hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1682 ok(hr == S_OK, "merge himl2 with itself failed\n");
1683 if (hr == S_OK) IImageList_Release(merge);
1685 /* Try merging 2 different image lists */
1687 ok( IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl1 failed\n");
1689 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1690 ok(hr == S_OK, "merge himl1 with himl2 failed\n");
1691 if (hr == S_OK) IImageList_Release(merge);
1693 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
1694 ok(hr == S_OK, "merge himl1 with himl2 8,16 failed\n");
1695 if (hr == S_OK) IImageList_Release(merge);
1697 IImageList_Release(imgl1);
1698 IImageList_Release(imgl2);
1700 DestroyIcon(hicon1);
1701 DestroyWindow(hwnd);
1704 static void test_iconsize(void)
1710 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1711 /* null pointers, not zero imagelist dimensions */
1712 ret = ImageList_GetIconSize(himl, NULL, NULL);
1713 ok(!ret, "got %d\n", ret);
1715 /* doesn't touch return pointers */
1717 ret = ImageList_GetIconSize(himl, &cx, NULL);
1718 ok(!ret, "got %d\n", ret);
1719 ok(cx == 0x1abe11ed, "got %d\n", cx);
1722 ret = ImageList_GetIconSize(himl, NULL, &cy);
1723 ok(!ret, "got %d\n", ret);
1724 ok(cy == 0x1abe11ed, "got %d\n", cy);
1726 ImageList_Destroy(himl);
1728 ret = ImageList_GetIconSize((HIMAGELIST)0xdeadbeef, &cx, &cy);
1729 ok(!ret, "got %d\n", ret);
1732 static void test_create_destroy(void)
1737 /* list with zero or negative image dimensions */
1738 himl = ImageList_Create(0, 0, ILC_COLOR16, 0, 3);
1739 ok(himl == NULL, "got %p\n", himl);
1741 himl = ImageList_Create(0, 16, ILC_COLOR16, 0, 3);
1742 ok(himl == NULL, "got %p\n", himl);
1744 himl = ImageList_Create(16, 0, ILC_COLOR16, 0, 3);
1745 ok(himl == NULL, "got %p\n", himl);
1747 himl = ImageList_Create(16, -1, ILC_COLOR16, 0, 3);
1748 ok(himl == NULL, "got %p\n", himl);
1750 himl = ImageList_Create(-1, 16, ILC_COLOR16, 0, 3);
1751 ok(himl == NULL, "got %p\n", himl);
1753 rc = ImageList_Destroy((HIMAGELIST)0xdeadbeef);
1754 ok(rc == FALSE, "ImageList_Destroy(0xdeadbeef) should fail and not crash\n");
1757 static void test_IImageList_Clone(void)
1759 IImageList *imgl, *imgl2;
1764 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1765 imgl = (IImageList*)himl;
1769 /* crashes on native */
1770 IImageList_Clone(imgl, &IID_IImageList, NULL);
1773 hr = IImageList_Clone(imgl, &IID_IImageList, (void**)&imgl2);
1774 ok(hr == S_OK, "got 0x%08x\n", hr);
1775 ref = IImageList_Release(imgl2);
1776 ok(ref == 0, "got %u\n", ref);
1778 IImageList_Release(imgl);
1781 static void test_IImageList_GetBkColor(void)
1788 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1789 imgl = (IImageList*)himl;
1793 /* crashes on native */
1794 IImageList_GetBkColor(imgl, NULL);
1797 hr = IImageList_GetBkColor(imgl, &color);
1798 ok(hr == S_OK, "got 0x%08x\n", hr);
1800 IImageList_Release(imgl);
1803 static void test_IImageList_SetBkColor(void)
1810 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1811 imgl = (IImageList*)himl;
1815 /* crashes on native */
1816 IImageList_SetBkColor(imgl, RGB(0, 0, 0), NULL);
1819 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1820 ok(hr == S_OK, "got 0x%08x\n", hr);
1822 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1823 ok(hr == S_OK, "got 0x%08x\n", hr);
1826 hr = IImageList_GetBkColor(imgl, &color);
1827 ok(hr == S_OK, "got 0x%08x\n", hr);
1828 ok(color == CLR_NONE, "got %x\n", color);
1830 IImageList_Release(imgl);
1833 static void test_IImageList_GetImageCount(void)
1840 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1841 imgl = (IImageList*)himl;
1845 /* crashes on native */
1846 IImageList_GetImageCount(imgl, NULL);
1850 hr = IImageList_GetImageCount(imgl, &count);
1851 ok(hr == S_OK, "got 0x%08x\n", hr);
1852 ok(count == 0, "got %d\n", count);
1854 IImageList_Release(imgl);
1857 static void test_IImageList_GetIconSize(void)
1864 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1865 imgl = (IImageList*)himl;
1867 hr = IImageList_GetIconSize(imgl, NULL, NULL);
1868 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1870 hr = IImageList_GetIconSize(imgl, &cx, NULL);
1871 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1873 hr = IImageList_GetIconSize(imgl, NULL, &cy);
1874 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1876 IImageList_Release(imgl);
1879 START_TEST(imagelist)
1881 ULONG_PTR ctx_cookie;
1884 HMODULE hComCtl32 = GetModuleHandle("comctl32.dll");
1885 pImageList_Create = NULL; /* These are not needed for non-v6.0 tests*/
1886 pImageList_Add = NULL;
1887 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1888 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1890 hinst = GetModuleHandleA(NULL);
1892 InitCommonControls();
1894 test_create_destroy();
1898 test_DrawIndirect();
1900 test_imagelist_storage();
1903 FreeLibrary(hComCtl32);
1905 /* Now perform v6 tests */
1907 if (!load_v6_module(&ctx_cookie, &hCtx))
1910 /* Reload comctl32 */
1911 hComCtl32 = LoadLibraryA("comctl32.dll");
1912 pImageList_Create = (void*)GetProcAddress(hComCtl32, "ImageList_Create");
1913 pImageList_Add = (void*)GetProcAddress(hComCtl32, "ImageList_Add");
1914 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1915 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1916 pImageList_CoCreateInstance = (void*)GetProcAddress(hComCtl32, "ImageList_CoCreateInstance");
1917 pHIMAGELIST_QueryInterface = (void*)GetProcAddress(hComCtl32, "HIMAGELIST_QueryInterface");
1919 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1922 test_ImageList_DrawIndirect();
1923 test_shell_imagelist();
1927 test_IImageList_Add_Remove();
1928 test_IImageList_Get_SetImageCount();
1929 test_IImageList_Draw();
1930 test_IImageList_Merge();
1931 test_IImageList_Clone();
1932 test_IImageList_GetBkColor();
1933 test_IImageList_SetBkColor();
1934 test_IImageList_GetImageCount();
1935 test_IImageList_GetIconSize();
1939 unload_v6_module(ctx_cookie, hCtx);