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 static 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 != NULL;
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 ULONG 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);
759 return hdr_size + image_size;
762 static void check_ilhead_data(const char *ilh_data, INT cx, INT cy, INT cur, INT max, INT grow, INT flags)
764 const ILHEAD *ilh = (const ILHEAD *)ilh_data;
766 ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
767 ok(ilh->usVersion == 0x101, "wrong usVersion %x (expected 0x101)\n", ilh->usVersion);
768 ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
769 ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
770 ok(ilh->cGrow == grow, "wrong cGrow %d (expected %d)\n", ilh->cGrow, grow);
771 ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
772 ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
773 ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
774 ok(ilh->flags == flags || broken(!(ilh->flags & 0xfe) && (flags & 0xfe) == ILC_COLOR4), /* <= w2k */
775 "wrong flags %04x\n", ilh->flags);
776 ok(ilh->ovls[0] == -1, "wrong ovls[0] %04x\n", ilh->ovls[0]);
777 ok(ilh->ovls[1] == -1, "wrong ovls[1] %04x\n", ilh->ovls[1]);
778 ok(ilh->ovls[2] == -1, "wrong ovls[2] %04x\n", ilh->ovls[2]);
779 ok(ilh->ovls[3] == -1, "wrong ovls[3] %04x\n", ilh->ovls[3]);
782 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
786 HBITMAP hbmp, hbmp_old;
788 RECT rc = { 0, 0, cx, cy };
790 hdc = CreateCompatibleDC(0);
792 memset(&bmi, 0, sizeof(bmi));
793 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
794 bmi.bmiHeader.biHeight = cx;
795 bmi.bmiHeader.biWidth = cy;
796 bmi.bmiHeader.biBitCount = 24;
797 bmi.bmiHeader.biPlanes = 1;
798 bmi.bmiHeader.biCompression = BI_RGB;
799 hbmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
801 hbmp_old = SelectObject(hdc, hbmp);
803 hbrush = CreateSolidBrush(color);
804 FillRect(hdc, &rc, hbrush);
805 DeleteObject(hbrush);
807 DrawText(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
809 SelectObject(hdc, hbmp_old);
815 #define iml_clear_stream_data() \
816 HeapFree(GetProcessHeap(), 0, Test_Stream.iml_data); \
817 Test_Stream.iml_data = NULL; \
818 Test_Stream.iml_data_size = 0;
820 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, INT grow,
821 INT width, INT height, INT flags, const char *comment)
823 INT ret, cxx, cyy, size;
825 trace("%s\n", comment);
827 ret = ImageList_GetImageCount(himl);
828 ok(ret == cur, "expected image count %d got %d\n", cur, ret);
830 ret = ImageList_GetIconSize(himl, &cxx, &cyy);
831 ok(ret, "ImageList_GetIconSize failed\n");
832 ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx);
833 ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy);
835 iml_clear_stream_data();
836 ret = ImageList_Write(himl, &Test_Stream.IStream_iface);
837 ok(ret, "ImageList_Write failed\n");
839 ok(Test_Stream.iml_data != 0, "ImageList_Write didn't write any data\n");
840 ok(Test_Stream.iml_data_size > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n");
842 check_ilhead_data(Test_Stream.iml_data, cx, cy, cur, max, grow, flags);
843 size = check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD),
844 Test_Stream.iml_data_size - sizeof(ILHEAD),
845 width, height, flags & 0xfe, comment);
846 if (size < Test_Stream.iml_data_size - sizeof(ILHEAD)) /* mask is present */
848 ok( flags & ILC_MASK, "extra data %u/%u but mask not expected\n",
849 Test_Stream.iml_data_size, size );
850 check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD) + size,
851 Test_Stream.iml_data_size - sizeof(ILHEAD) - size,
852 width, height, 1, comment);
856 static void image_list_init(HIMAGELIST himl)
862 static const struct test_data
865 INT cx, cy, cur, max, grow, width, height, bpp;
869 { 255, BMP_CX, BMP_CX, 1, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 1" },
870 { 170, BMP_CX, BMP_CX, 2, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 2" },
871 { 85, BMP_CX, BMP_CX, 3, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 3" },
872 { 0, BMP_CX, BMP_CX, 4, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 4" },
873 { 0, BMP_CX, BMP_CX, 5, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 5" },
874 { 85, BMP_CX, BMP_CX, 6, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 6" },
875 { 170, BMP_CX, BMP_CX, 7, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 7" },
876 { 255, BMP_CX, BMP_CX, 8, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 8" },
877 { 255, BMP_CX, BMP_CX, 9, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 9" },
878 { 170, BMP_CX, BMP_CX, 10, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 10" },
879 { 85, BMP_CX, BMP_CX, 11, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 11" },
880 { 0, BMP_CX, BMP_CX, 12, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 12" },
881 { 0, BMP_CX, BMP_CX, 13, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 13" },
882 { 85, BMP_CX, BMP_CX, 14, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 14" },
883 { 170, BMP_CX, BMP_CX, 15, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 15" },
884 { 255, BMP_CX, BMP_CX, 16, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 16" },
885 { 255, BMP_CX, BMP_CX, 17, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 17" },
886 { 170, BMP_CX, BMP_CX, 18, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 18" },
887 { 85, BMP_CX, BMP_CX, 19, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 19" },
888 { 0, BMP_CX, BMP_CX, 20, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 20" },
889 { 0, BMP_CX, BMP_CX, 21, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 21" },
890 { 85, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 22" },
891 { 170, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 23" },
892 { 255, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 24" }
895 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "total 0");
897 #define add_bitmap(grey) \
898 sprintf(comment, "%d", n++); \
899 hbm = create_bitmap(BMP_CX, BMP_CX, RGB((grey),(grey),(grey)), comment); \
900 ImageList_Add(himl, hbm, NULL); \
903 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
905 add_bitmap(td[i].grey);
906 check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, td[i].grow,
907 td[i].width, td[i].height, td[i].bpp, td[i].comment);
912 static void test_imagelist_storage(void)
919 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
920 ok(himl != 0, "ImageList_Create failed\n");
922 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "empty");
924 image_list_init(himl);
925 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "orig");
927 ret = ImageList_Remove(himl, 4);
928 ok(ret, "ImageList_Remove failed\n");
929 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "1");
931 ret = ImageList_Remove(himl, 5);
932 ok(ret, "ImageList_Remove failed\n");
933 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "2");
935 ret = ImageList_Remove(himl, 6);
936 ok(ret, "ImageList_Remove failed\n");
937 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "3");
939 ret = ImageList_Remove(himl, 7);
940 ok(ret, "ImageList_Remove failed\n");
941 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "4");
943 ret = ImageList_Remove(himl, -2);
944 ok(!ret, "ImageList_Remove(-2) should fail\n");
945 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "5");
947 ret = ImageList_Remove(himl, 20);
948 ok(!ret, "ImageList_Remove(20) should fail\n");
949 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "6");
951 ret = ImageList_Remove(himl, -1);
952 ok(ret, "ImageList_Remove(-1) failed\n");
953 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "7");
955 ret = ImageList_Destroy(himl);
956 ok(ret, "ImageList_Destroy failed\n");
958 iml_clear_stream_data();
960 /* test ImageList_Create storage allocation */
962 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 0, 32);
963 ok(himl != 0, "ImageList_Create failed\n");
964 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 32, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "init 0 grow 32");
965 hbm = create_bitmap(BMP_CX * 9, BMP_CX, 0, "9");
966 ret = ImageList_Add(himl, hbm, NULL);
967 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
968 check_iml_data(himl, BMP_CX, BMP_CX, 1, 34, 32, BMP_CX * 4, BMP_CX * 9, ILC_COLOR24, "add 1 x 9");
970 ret = ImageList_Destroy(himl);
971 ok(ret, "ImageList_Destroy failed\n");
972 iml_clear_stream_data();
974 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 4);
975 ok(himl != 0, "ImageList_Create failed\n");
976 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 4 grow 4");
977 hbm = create_bitmap(BMP_CX, BMP_CX * 9, 0, "9");
978 ret = ImageList_Add(himl, hbm, NULL);
979 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
980 check_iml_data(himl, BMP_CX, BMP_CX, 9, 15, 4, BMP_CX * 4, BMP_CX * 4, ILC_COLOR24, "add 9 x 1");
981 ret = ImageList_Add(himl, hbm, NULL);
982 ok(ret == 9, "ImageList_Add returned %d, expected 9\n", ret);
983 check_iml_data(himl, BMP_CX, BMP_CX, 18, 25, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "add 9 x 1");
985 ret = ImageList_Destroy(himl);
986 ok(ret, "ImageList_Destroy failed\n");
987 iml_clear_stream_data();
989 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 207, 209);
990 ok(himl != 0, "ImageList_Create failed\n");
991 check_iml_data(himl, BMP_CX, BMP_CX, 0, 208, 212, BMP_CX * 4, BMP_CX * 52, ILC_COLOR24, "init 207 grow 209");
992 ret = ImageList_Destroy(himl);
993 ok(ret, "ImageList_Destroy failed\n");
994 iml_clear_stream_data();
996 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 209, 207);
997 ok(himl != 0, "ImageList_Create failed\n");
998 check_iml_data(himl, BMP_CX, BMP_CX, 0, 210, 208, BMP_CX * 4, BMP_CX * 53, ILC_COLOR24, "init 209 grow 207");
999 ret = ImageList_Destroy(himl);
1000 ok(ret, "ImageList_Destroy failed\n");
1001 iml_clear_stream_data();
1003 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 14, 4);
1004 ok(himl != 0, "ImageList_Create failed\n");
1005 check_iml_data(himl, BMP_CX, BMP_CX, 0, 15, 4, BMP_CX * 4, BMP_CX * 4, ILC_COLOR24, "init 14 grow 4");
1006 ret = ImageList_Destroy(himl);
1007 ok(ret, "ImageList_Destroy failed\n");
1008 iml_clear_stream_data();
1010 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 5, 9);
1011 ok(himl != 0, "ImageList_Create failed\n");
1012 check_iml_data(himl, BMP_CX, BMP_CX, 0, 6, 12, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 5 grow 9");
1013 ret = ImageList_Destroy(himl);
1014 ok(ret, "ImageList_Destroy failed\n");
1015 iml_clear_stream_data();
1017 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 9, 5);
1018 ok(himl != 0, "ImageList_Create failed\n");
1019 check_iml_data(himl, BMP_CX, BMP_CX, 0, 10, 8, BMP_CX * 4, BMP_CX * 3, ILC_COLOR24, "init 9 grow 5");
1020 ret = ImageList_Destroy(himl);
1021 ok(ret, "ImageList_Destroy failed\n");
1022 iml_clear_stream_data();
1024 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 2, 4);
1025 ok(himl != 0, "ImageList_Create failed\n");
1026 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "init 2 grow 4");
1027 ret = ImageList_Destroy(himl);
1028 ok(ret, "ImageList_Destroy failed\n");
1029 iml_clear_stream_data();
1031 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 2);
1032 ok(himl != 0, "ImageList_Create failed\n");
1033 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 4 grow 2");
1034 ret = ImageList_Destroy(himl);
1035 ok(ret, "ImageList_Destroy failed\n");
1036 iml_clear_stream_data();
1038 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR8, 4, 2);
1039 ok(himl != 0, "ImageList_Create failed\n");
1040 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR8, "bpp 8");
1041 ret = ImageList_Destroy(himl);
1042 ok(ret, "ImageList_Destroy failed\n");
1043 iml_clear_stream_data();
1045 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4, 4, 2);
1046 ok(himl != 0, "ImageList_Create failed\n");
1047 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp 4");
1048 ret = ImageList_Destroy(himl);
1049 ok(ret, "ImageList_Destroy failed\n");
1050 iml_clear_stream_data();
1052 himl = ImageList_Create(BMP_CX, BMP_CX, 0, 4, 2);
1053 ok(himl != 0, "ImageList_Create failed\n");
1054 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp default");
1055 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1056 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1057 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1058 DestroyIcon( icon );
1059 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp default");
1060 ret = ImageList_Destroy(himl);
1061 ok(ret, "ImageList_Destroy failed\n");
1062 iml_clear_stream_data();
1064 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24|ILC_MASK, 4, 2);
1065 ok(himl != 0, "ImageList_Create failed\n");
1066 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24|ILC_MASK,
1068 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1069 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1070 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1071 DestroyIcon( icon );
1072 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24|ILC_MASK,
1074 ret = ImageList_Destroy(himl);
1075 ok(ret, "ImageList_Destroy failed\n");
1076 iml_clear_stream_data();
1078 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 4, 2);
1079 ok(himl != 0, "ImageList_Create failed\n");
1080 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4|ILC_MASK,
1082 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1083 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1084 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1085 DestroyIcon( icon );
1086 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4|ILC_MASK,
1088 ret = ImageList_Destroy(himl);
1089 ok(ret, "ImageList_Destroy failed\n");
1090 iml_clear_stream_data();
1092 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 99);
1093 ok(himl != 0, "ImageList_Create failed\n");
1094 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 100, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1096 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1097 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1098 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1099 check_iml_data(himl, BMP_CX, BMP_CX, 2, 3, 100, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1100 "init 2 grow 99 2 icons");
1101 ok( ImageList_AddIcon(himl, icon) == 2,"failed to add icon\n");
1102 DestroyIcon( icon );
1103 check_iml_data(himl, BMP_CX, BMP_CX, 3, 104, 100, BMP_CX * 4, BMP_CX * 104/4, ILC_COLOR4|ILC_MASK,
1104 "init 2 grow 99 3 icons");
1105 ok( ImageList_Remove(himl, -1) == TRUE,"failed to remove icon\n");
1106 check_iml_data(himl, BMP_CX, BMP_CX, 0, 100, 100, BMP_CX * 4, BMP_CX * 100/4, ILC_COLOR4|ILC_MASK,
1107 "init 2 grow 99 empty");
1108 ok( ImageList_SetImageCount(himl, 22) == TRUE,"failed to set image count\n");
1109 check_iml_data(himl, BMP_CX, BMP_CX, 22, 23, 100, BMP_CX * 4, BMP_CX * 24/4, ILC_COLOR4|ILC_MASK,
1110 "init 2 grow 99 set count 22");
1111 ok( ImageList_SetImageCount(himl, 0) == TRUE,"failed to set image count\n");
1112 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 100, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1113 "init 2 grow 99 set count 0");
1114 ok( ImageList_SetImageCount(himl, 42) == TRUE,"failed to set image count\n");
1115 check_iml_data(himl, BMP_CX, BMP_CX, 42, 43, 100, BMP_CX * 4, BMP_CX * 44/4, ILC_COLOR4|ILC_MASK,
1116 "init 2 grow 99 set count 42");
1117 ret = ImageList_Destroy(himl);
1118 ok(ret, "ImageList_Destroy failed\n");
1119 iml_clear_stream_data();
1121 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65536+12);
1122 ok(himl != 0, "ImageList_Create failed\n");
1123 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 12, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1124 "init 2 grow 65536+12");
1125 ret = ImageList_Destroy(himl);
1126 ok(ret, "ImageList_Destroy failed\n");
1127 iml_clear_stream_data();
1129 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65535);
1130 ok(himl != 0, "ImageList_Create failed\n");
1131 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 0, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1132 "init 2 grow 65535");
1133 ret = ImageList_Destroy(himl);
1134 ok(ret, "ImageList_Destroy failed\n");
1135 iml_clear_stream_data();
1137 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, -20);
1138 ok(himl != 0, "ImageList_Create failed\n");
1139 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1141 ret = ImageList_Destroy(himl);
1142 ok(ret, "ImageList_Destroy failed\n");
1143 iml_clear_stream_data();
1146 static void test_shell_imagelist(void)
1148 BOOL (WINAPI *pSHGetImageList)(INT, REFIID, void**);
1149 IImageList *iml = NULL;
1156 /* Try to load function from shell32 */
1157 hShell32 = LoadLibrary("shell32.dll");
1158 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1160 if (!pSHGetImageList)
1162 win_skip("SHGetImageList not available, skipping test\n");
1166 /* Get system image list */
1167 hr = (pSHGetImageList)(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1169 ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1174 IImageList_GetImageCount(iml, &out);
1175 ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1177 /* Fetch the small icon size */
1178 cx = GetSystemMetrics(SM_CXSMICON);
1179 cy = GetSystemMetrics(SM_CYSMICON);
1181 /* Check icon size matches */
1182 IImageList_GetImageRect(iml, 0, &rect);
1183 ok(((rect.right == cx) && (rect.bottom == cy)),
1184 "IImageList_GetImageRect returned r:%d,b:%d\n",
1185 rect.right, rect.bottom);
1187 IImageList_Release(iml);
1188 FreeLibrary(hShell32);
1191 static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
1194 UINT32 *buffer = NULL;
1195 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
1198 hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1199 ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1201 if(!hBitmap || !buffer)
1203 DeleteObject(hBitmap);
1213 static BOOL colour_match(UINT32 x, UINT32 y)
1215 const INT32 tolerance = 8;
1217 const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1218 const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1219 const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1221 return (dr <= tolerance && dg <= tolerance && db <= tolerance);
1224 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1225 UINT32 expected, int line)
1227 bits[0] = 0x00FFFFFF;
1228 pImageList_DrawIndirect(ildp);
1229 ok(colour_match(bits[0], expected),
1230 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1231 bits[0] & 0x00FFFFFF, expected, line);
1235 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1236 UINT fStyle, UINT32 expected, int line)
1238 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1239 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1240 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1243 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1244 DWORD dwRop, UINT32 expected, int line)
1246 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1247 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1248 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1251 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1252 UINT fState, DWORD Frame, UINT32 expected, int line)
1254 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1255 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1256 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1259 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1260 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1261 UINT32 broken_expected, int line)
1263 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1264 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1265 bits[0] = 0x00FFFFFF;
1266 pImageList_DrawIndirect(&ildp);
1267 ok(colour_match(bits[0], expected) ||
1268 broken(colour_match(bits[0], broken_expected)),
1269 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1270 bits[0] & 0x00FFFFFF, expected, line);
1273 static void test_ImageList_DrawIndirect(void)
1275 HIMAGELIST himl = NULL;
1278 HBITMAP hbmOld = NULL, hbmDst = NULL;
1279 HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1280 HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
1281 int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1283 UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1284 int bpp, broken_value;
1286 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1289 hdcDst = CreateCompatibleDC(0);
1290 ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1293 bpp = GetDeviceCaps(hdcDst, BITSPIXEL);
1295 hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1296 ok(hbmMask != 0, "CreateBitmap failed\n");
1297 if(!hbmMask) goto cleanup;
1299 hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1300 ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1301 if(!hbmInverseMask) goto cleanup;
1303 himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1304 ok(himl != 0, "ImageList_Create failed\n");
1305 if(!himl) goto cleanup;
1307 /* Add a no-alpha image */
1308 hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
1309 if(!hbmImage) goto cleanup;
1311 iImage = pImageList_Add(himl, hbmImage, hbmMask);
1312 ok(iImage != -1, "ImageList_Add failed\n");
1313 if(iImage == -1) goto cleanup;
1315 /* Add an alpha image */
1316 hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
1317 if(!hbmAlphaImage) goto cleanup;
1319 iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1320 ok(iAlphaImage != -1, "ImageList_Add failed\n");
1321 if(iAlphaImage == -1) goto cleanup;
1323 /* Add a transparent alpha image */
1324 hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
1325 if(!hbmTransparentImage) goto cleanup;
1327 iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1328 ok(iTransparentImage != -1, "ImageList_Add failed\n");
1329 if(iTransparentImage == -1) goto cleanup;
1332 bitmapInfo.bmiHeader.biBitCount = 32;
1333 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1334 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1335 if (!hbmDst || !bits)
1337 hbmOld = SelectObject(hdcDst, hbmDst);
1339 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1340 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1341 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
1342 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1343 else broken_value = 0x00B4BDC4;
1344 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1345 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1346 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1347 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1349 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
1350 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
1352 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1353 else broken_value = 0x009DA8B1;
1354 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1355 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1356 else broken_value = 0x008C99A3;
1357 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1358 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
1359 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
1360 todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
1362 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
1364 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1365 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
1367 /* ILD_ROP is ignored when the image has an alpha channel */
1368 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
1369 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
1371 todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
1372 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
1374 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
1375 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
1377 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
1378 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
1379 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
1384 SelectObject(hdcDst, hbmOld);
1386 DeleteObject(hbmDst);
1392 DeleteObject(hbmMask);
1394 DeleteObject(hbmInverseMask);
1397 DeleteObject(hbmImage);
1399 DeleteObject(hbmAlphaImage);
1400 if(hbmTransparentImage)
1401 DeleteObject(hbmTransparentImage);
1405 ret = ImageList_Destroy(himl);
1406 ok(ret, "ImageList_Destroy failed\n");
1410 static void test_iimagelist(void)
1412 IImageList *imgl, *imgl2;
1417 if (!pHIMAGELIST_QueryInterface)
1419 win_skip("XP imagelist functions not available\n");
1423 /* test reference counting on destruction */
1424 imgl = (IImageList*)createImageList(32, 32);
1425 ret = IImageList_AddRef(imgl);
1426 ok(ret == 2, "Expected 2, got %d\n", ret);
1427 ret = ImageList_Destroy((HIMAGELIST)imgl);
1428 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1429 ret = ImageList_Destroy((HIMAGELIST)imgl);
1430 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1431 ret = ImageList_Destroy((HIMAGELIST)imgl);
1432 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1434 imgl = (IImageList*)createImageList(32, 32);
1435 ret = IImageList_AddRef(imgl);
1436 ok(ret == 2, "Expected 2, got %d\n", ret);
1437 ret = ImageList_Destroy((HIMAGELIST)imgl);
1438 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1439 ret = IImageList_Release(imgl);
1440 ok(ret == 0, "Expected 0, got %d\n", ret);
1441 ret = ImageList_Destroy((HIMAGELIST)imgl);
1442 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1444 /* ref counting, HIMAGELIST_QueryInterface adds a reference */
1445 imgl = (IImageList*)createImageList(32, 32);
1446 hr = pHIMAGELIST_QueryInterface((HIMAGELIST)imgl, &IID_IImageList, (void**)&imgl2);
1447 ok(hr == S_OK, "got 0x%08x\n", hr);
1448 ok(imgl2 == imgl, "got different pointer\n");
1449 ret = IImageList_Release(imgl);
1450 ok(ret == 1, "got %u\n", ret);
1451 IImageList_Release(imgl);
1453 if (!pImageList_CoCreateInstance)
1455 win_skip("Vista imagelist functions not available\n");
1459 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1460 ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
1463 IImageList_Release(imgl);
1465 himl = createImageList(32, 32);
1470 hr = (pHIMAGELIST_QueryInterface)(himl, &IID_IImageList, (void **) &imgl);
1471 ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
1474 IImageList_Release(imgl);
1476 ImageList_Destroy(himl);
1479 static void test_hotspot_v6(void)
1490 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
1491 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
1498 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
1499 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
1500 IImageList *imgl1, *imgl2;
1503 /* cast to IImageList */
1504 imgl1 = (IImageList *) himl1;
1505 imgl2 = (IImageList *) himl2;
1507 for (i = 0; i < HOTSPOTS_MAX; i++) {
1508 for (j = 0; j < HOTSPOTS_MAX; j++) {
1509 int dx1 = hotspots[i].dx;
1510 int dy1 = hotspots[i].dy;
1511 int dx2 = hotspots[j].dx;
1512 int dy2 = hotspots[j].dy;
1513 int correctx, correcty, newx, newy;
1515 IImageList *imglNew;
1518 hr = IImageList_BeginDrag(imgl1, 0, dx1, dy1);
1519 ok(SUCCEEDED(hr), "BeginDrag failed for { %d, %d }\n", dx1, dy1);
1520 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
1522 /* check merging the dragged image with a second image */
1523 hr = IImageList_SetDragCursorImage(imgl2, (IUnknown *) imgl2, 0, dx2, dy2);
1524 ok(SUCCEEDED(hr), "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
1525 dx1, dy1, dx2, dy2);
1526 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
1528 /* check new hotspot, it should be the same like the old one */
1529 hr = IImageList_GetDragImage(imgl2, NULL, &ppt, &IID_IImageList, (PVOID *) &imglNew);
1530 ok(SUCCEEDED(hr), "GetDragImage failed\n");
1531 ok(ppt.x == dx1 && ppt.y == dy1,
1532 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
1533 dx1, dy1, ppt.x, ppt.y);
1534 /* check size of new dragged image */
1535 IImageList_GetIconSize(imglNew, &newx, &newy);
1536 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
1537 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
1538 ok(newx == correctx && newy == correcty,
1539 "Expected drag image size [%d,%d] got [%d,%d]\n",
1540 correctx, correcty, newx, newy);
1541 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
1542 IImageList_EndDrag(imgl2);
1550 IImageList_Release(imgl2);
1551 IImageList_Release(imgl1);
1554 static void test_IImageList_Add_Remove(void)
1566 /* create an imagelist to play with */
1567 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1568 ok(himl != 0,"failed to create imagelist\n");
1570 imgl = (IImageList *) himl;
1572 /* load the icons to add to the image list */
1573 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1574 ok(hicon1 != 0, "no hicon1\n");
1575 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1576 ok(hicon2 != 0, "no hicon2\n");
1577 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1578 ok(hicon3 != 0, "no hicon3\n");
1580 /* remove when nothing exists */
1581 hr = IImageList_Remove(imgl, 0);
1582 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1584 /* removing everything from an empty imagelist should succeed */
1585 hr = IImageList_Remove(imgl, -1);
1586 ok(hr == S_OK, "removed nonexistent icon\n");
1590 ok( IImageList_ReplaceIcon(imgl, -1, hicon1, &ret) == S_OK && (ret == 0),"failed to add icon1\n");
1592 ok( IImageList_ReplaceIcon(imgl, -1, hicon2, &ret) == S_OK && (ret == 1),"failed to add icon2\n");
1594 ok( IImageList_ReplaceIcon(imgl, -1, hicon3, &ret) == S_OK && (ret == 2),"failed to add icon3\n");
1596 /* remove an index out of range */
1597 ok( IImageList_Remove(imgl, 4711) == E_INVALIDARG, "got 0x%08x\n", hr);
1600 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1601 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1602 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1604 /* remove one extra */
1605 ok( IImageList_Remove(imgl, 0) == E_INVALIDARG, "got 0x%08x\n", hr);
1607 IImageList_Release(imgl);
1608 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1609 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1610 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1613 static void test_IImageList_Get_SetImageCount(void)
1620 /* create an imagelist to play with */
1621 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1622 ok(himl != 0,"failed to create imagelist\n");
1624 imgl = (IImageList *) himl;
1626 /* check SetImageCount/GetImageCount */
1627 hr = IImageList_SetImageCount(imgl, 3);
1628 ok(hr == S_OK, "got 0x%08x\n", hr);
1630 hr = IImageList_GetImageCount(imgl, &ret);
1631 ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
1632 hr = IImageList_SetImageCount(imgl, 1);
1633 ok(hr == S_OK, "got 0x%08x\n", hr);
1635 hr = IImageList_GetImageCount(imgl, &ret);
1636 ok(hr == S_OK && ret == 1, "invalid image count after decrease to 1\n");
1637 hr = IImageList_SetImageCount(imgl, 0);
1638 ok(hr == S_OK, "got 0x%08x\n", hr);
1640 hr = IImageList_GetImageCount(imgl, &ret);
1641 ok(hr == S_OK && ret == 0, "invalid image count after decrease to 0\n");
1643 IImageList_Release(imgl);
1646 static void test_IImageList_Draw(void)
1655 IMAGELISTDRAWPARAMS imldp;
1661 hwndfortest = create_a_window();
1662 hdc = GetDC(hwndfortest);
1663 ok(hdc!=NULL, "couldn't get DC\n");
1665 /* create an imagelist to play with */
1666 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1667 ok(himl!=0,"failed to create imagelist\n");
1669 imgl = (IImageList *) himl;
1671 /* load the icons to add to the image list */
1672 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1673 ok(hbm1 != 0, "no bitmap 1\n");
1674 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1675 ok(hbm2 != 0, "no bitmap 2\n");
1676 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1677 ok(hbm3 != 0, "no bitmap 3\n");
1681 ok( IImageList_Add(imgl, hbm1, 0, &ret) == S_OK && (ret == 0), "failed to add bitmap 1\n");
1683 ok( IImageList_Add(imgl, hbm2, 0, &ret) == S_OK && (ret == 1), "failed to add bitmap 2\n");
1685 ok( IImageList_SetImageCount(imgl, 3) == S_OK, "Setimage count failed\n");
1686 ok( IImageList_Replace(imgl, 2, hbm3, 0) == S_OK, "failed to replace bitmap 3\n");
1690 /* crashes on native */
1691 IImageList_Draw(imgl, NULL);
1694 memset(&imldp, 0, sizeof (imldp));
1695 hr = IImageList_Draw(imgl, &imldp);
1696 ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
1698 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
1702 REDRAW(hwndfortest);
1705 imldp.fStyle = SRCCOPY;
1706 imldp.rgbBk = CLR_DEFAULT;
1707 imldp.rgbFg = CLR_DEFAULT;
1710 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1712 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1714 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1716 ok( IImageList_Draw(imgl, &imldp) == E_INVALIDARG, "should fail\n");
1719 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 1st bitmap\n");
1720 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 2nd bitmap\n");
1721 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 3rd bitmap\n");
1724 IImageList_Release(imgl);
1726 /* bitmaps should not be deleted by the imagelist */
1727 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1728 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1729 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1731 ReleaseDC(hwndfortest, hdc);
1732 DestroyWindow(hwndfortest);
1735 static void test_IImageList_Merge(void)
1737 HIMAGELIST himl1, himl2;
1738 IImageList *imgl1, *imgl2, *merge;
1740 HWND hwnd = create_a_window();
1744 himl1 = ImageList_Create(32,32,0,0,3);
1745 ok(himl1 != NULL,"failed to create himl1\n");
1747 himl2 = ImageList_Create(32,32,0,0,3);
1748 ok(himl2 != NULL,"failed to create himl2\n");
1750 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1751 ok(hicon1 != NULL, "failed to create hicon1\n");
1753 if (!himl1 || !himl2 || !hicon1)
1756 /* cast to IImageList */
1757 imgl1 = (IImageList *) himl1;
1758 imgl2 = (IImageList *) himl2;
1761 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl2 failed\n");
1765 /* null cases that crash on native */
1766 IImageList_Merge(imgl1, -1, NULL, 0, 0, 0, &IID_IImageList, (void**)&merge);
1767 IImageList_Merge(imgl1, -1, (IUnknown*) imgl2, 0, 0, 0, &IID_IImageList, NULL);
1770 /* If himl1 has no images, merge still succeeds */
1771 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1772 ok(hr == S_OK, "merge himl1,-1 failed\n");
1773 if (hr == S_OK) IImageList_Release(merge);
1775 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1776 ok(hr == S_OK, "merge himl1,0 failed\n");
1777 if (hr == S_OK) IImageList_Release(merge);
1779 /* Same happens if himl2 is empty */
1780 IImageList_Release(imgl2);
1781 himl2 = ImageList_Create(32,32,0,0,3);
1782 ok(himl2 != NULL,"failed to recreate himl2\n");
1784 imgl2 = (IImageList *) himl2;
1786 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
1787 ok(hr == S_OK, "merge himl2,-1 failed\n");
1788 if (hr == S_OK) IImageList_Release(merge);
1790 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1791 ok(hr == S_OK, "merge himl2,0 failed\n");
1792 if (hr == S_OK) IImageList_Release(merge);
1794 /* Now try merging an image with itself */
1796 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"re-add icon1 to himl2 failed\n");
1798 hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1799 ok(hr == S_OK, "merge himl2 with itself failed\n");
1800 if (hr == S_OK) IImageList_Release(merge);
1802 /* Try merging 2 different image lists */
1804 ok( IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl1 failed\n");
1806 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1807 ok(hr == S_OK, "merge himl1 with himl2 failed\n");
1808 if (hr == S_OK) IImageList_Release(merge);
1810 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
1811 ok(hr == S_OK, "merge himl1 with himl2 8,16 failed\n");
1812 if (hr == S_OK) IImageList_Release(merge);
1814 IImageList_Release(imgl1);
1815 IImageList_Release(imgl2);
1817 DestroyIcon(hicon1);
1818 DestroyWindow(hwnd);
1821 static void test_iconsize(void)
1827 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1828 /* null pointers, not zero imagelist dimensions */
1829 ret = ImageList_GetIconSize(himl, NULL, NULL);
1830 ok(!ret, "got %d\n", ret);
1832 /* doesn't touch return pointers */
1834 ret = ImageList_GetIconSize(himl, &cx, NULL);
1835 ok(!ret, "got %d\n", ret);
1836 ok(cx == 0x1abe11ed, "got %d\n", cx);
1839 ret = ImageList_GetIconSize(himl, NULL, &cy);
1840 ok(!ret, "got %d\n", ret);
1841 ok(cy == 0x1abe11ed, "got %d\n", cy);
1843 ImageList_Destroy(himl);
1845 ret = ImageList_GetIconSize((HIMAGELIST)0xdeadbeef, &cx, &cy);
1846 ok(!ret, "got %d\n", ret);
1849 static void test_create_destroy(void)
1854 /* list with zero or negative image dimensions */
1855 himl = ImageList_Create(0, 0, ILC_COLOR16, 0, 3);
1856 ok(himl == NULL, "got %p\n", himl);
1858 himl = ImageList_Create(0, 16, ILC_COLOR16, 0, 3);
1859 ok(himl == NULL, "got %p\n", himl);
1861 himl = ImageList_Create(16, 0, ILC_COLOR16, 0, 3);
1862 ok(himl == NULL, "got %p\n", himl);
1864 himl = ImageList_Create(16, -1, ILC_COLOR16, 0, 3);
1865 ok(himl == NULL, "got %p\n", himl);
1867 himl = ImageList_Create(-1, 16, ILC_COLOR16, 0, 3);
1868 ok(himl == NULL, "got %p\n", himl);
1870 rc = ImageList_Destroy((HIMAGELIST)0xdeadbeef);
1871 ok(rc == FALSE, "ImageList_Destroy(0xdeadbeef) should fail and not crash\n");
1874 static void test_IImageList_Clone(void)
1876 IImageList *imgl, *imgl2;
1881 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1882 imgl = (IImageList*)himl;
1886 /* crashes on native */
1887 IImageList_Clone(imgl, &IID_IImageList, NULL);
1890 hr = IImageList_Clone(imgl, &IID_IImageList, (void**)&imgl2);
1891 ok(hr == S_OK, "got 0x%08x\n", hr);
1892 ref = IImageList_Release(imgl2);
1893 ok(ref == 0, "got %u\n", ref);
1895 IImageList_Release(imgl);
1898 static void test_IImageList_GetBkColor(void)
1905 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1906 imgl = (IImageList*)himl;
1910 /* crashes on native */
1911 IImageList_GetBkColor(imgl, NULL);
1914 hr = IImageList_GetBkColor(imgl, &color);
1915 ok(hr == S_OK, "got 0x%08x\n", hr);
1917 IImageList_Release(imgl);
1920 static void test_IImageList_SetBkColor(void)
1927 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1928 imgl = (IImageList*)himl;
1932 /* crashes on native */
1933 IImageList_SetBkColor(imgl, RGB(0, 0, 0), NULL);
1936 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1937 ok(hr == S_OK, "got 0x%08x\n", hr);
1939 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1940 ok(hr == S_OK, "got 0x%08x\n", hr);
1943 hr = IImageList_GetBkColor(imgl, &color);
1944 ok(hr == S_OK, "got 0x%08x\n", hr);
1945 ok(color == CLR_NONE, "got %x\n", color);
1947 IImageList_Release(imgl);
1950 static void test_IImageList_GetImageCount(void)
1957 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1958 imgl = (IImageList*)himl;
1962 /* crashes on native */
1963 IImageList_GetImageCount(imgl, NULL);
1967 hr = IImageList_GetImageCount(imgl, &count);
1968 ok(hr == S_OK, "got 0x%08x\n", hr);
1969 ok(count == 0, "got %d\n", count);
1971 IImageList_Release(imgl);
1974 static void test_IImageList_GetIconSize(void)
1981 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1982 imgl = (IImageList*)himl;
1984 hr = IImageList_GetIconSize(imgl, NULL, NULL);
1985 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1987 hr = IImageList_GetIconSize(imgl, &cx, NULL);
1988 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1990 hr = IImageList_GetIconSize(imgl, NULL, &cy);
1991 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1993 IImageList_Release(imgl);
1996 START_TEST(imagelist)
1998 ULONG_PTR ctx_cookie;
2001 HMODULE hComCtl32 = GetModuleHandle("comctl32.dll");
2002 pImageList_Create = NULL; /* These are not needed for non-v6.0 tests*/
2003 pImageList_Add = NULL;
2004 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
2005 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
2007 hinst = GetModuleHandleA(NULL);
2009 InitCommonControls();
2011 test_create_destroy();
2015 test_DrawIndirect();
2017 test_imagelist_storage();
2020 FreeLibrary(hComCtl32);
2022 /* Now perform v6 tests */
2024 if (!load_v6_module(&ctx_cookie, &hCtx))
2027 /* Reload comctl32 */
2028 hComCtl32 = LoadLibraryA("comctl32.dll");
2029 pImageList_Create = (void*)GetProcAddress(hComCtl32, "ImageList_Create");
2030 pImageList_Add = (void*)GetProcAddress(hComCtl32, "ImageList_Add");
2031 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
2032 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
2033 pImageList_CoCreateInstance = (void*)GetProcAddress(hComCtl32, "ImageList_CoCreateInstance");
2034 pHIMAGELIST_QueryInterface = (void*)GetProcAddress(hComCtl32, "HIMAGELIST_QueryInterface");
2036 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2039 test_ImageList_DrawIndirect();
2040 test_shell_imagelist();
2044 test_IImageList_Add_Remove();
2045 test_IImageList_Get_SetImageCount();
2046 test_IImageList_Draw();
2047 test_IImageList_Merge();
2048 test_IImageList_Clone();
2049 test_IImageList_GetBkColor();
2050 test_IImageList_SetBkColor();
2051 test_IImageList_GetImageCount();
2052 test_IImageList_GetIconSize();
2056 unload_v6_module(ctx_cookie, hCtx);