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)
785 char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
786 BITMAPINFO *bmi = (BITMAPINFO *)bmibuf;
787 HBITMAP hbmp, hbmp_old;
789 RECT rc = { 0, 0, cx, cy };
791 hdc = CreateCompatibleDC(0);
793 memset(bmi, 0, sizeof(*bmi));
794 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
795 bmi->bmiHeader.biHeight = cx;
796 bmi->bmiHeader.biWidth = cy;
797 bmi->bmiHeader.biBitCount = 24;
798 bmi->bmiHeader.biPlanes = 1;
799 bmi->bmiHeader.biCompression = BI_RGB;
800 hbmp = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
802 hbmp_old = SelectObject(hdc, hbmp);
804 hbrush = CreateSolidBrush(color);
805 FillRect(hdc, &rc, hbrush);
806 DeleteObject(hbrush);
808 DrawText(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
810 SelectObject(hdc, hbmp_old);
816 #define iml_clear_stream_data() \
817 HeapFree(GetProcessHeap(), 0, Test_Stream.iml_data); \
818 Test_Stream.iml_data = NULL; \
819 Test_Stream.iml_data_size = 0;
821 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, INT grow,
822 INT width, INT height, INT flags, const char *comment)
824 INT ret, cxx, cyy, size;
826 trace("%s\n", comment);
828 ret = ImageList_GetImageCount(himl);
829 ok(ret == cur, "expected image count %d got %d\n", cur, ret);
831 ret = ImageList_GetIconSize(himl, &cxx, &cyy);
832 ok(ret, "ImageList_GetIconSize failed\n");
833 ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx);
834 ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy);
836 iml_clear_stream_data();
837 ret = ImageList_Write(himl, &Test_Stream.IStream_iface);
838 ok(ret, "ImageList_Write failed\n");
840 ok(Test_Stream.iml_data != 0, "ImageList_Write didn't write any data\n");
841 ok(Test_Stream.iml_data_size > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n");
843 check_ilhead_data(Test_Stream.iml_data, cx, cy, cur, max, grow, flags);
844 size = check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD),
845 Test_Stream.iml_data_size - sizeof(ILHEAD),
846 width, height, flags & 0xfe, comment);
847 if (size < Test_Stream.iml_data_size - sizeof(ILHEAD)) /* mask is present */
849 ok( flags & ILC_MASK, "extra data %u/%u but mask not expected\n",
850 Test_Stream.iml_data_size, size );
851 check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD) + size,
852 Test_Stream.iml_data_size - sizeof(ILHEAD) - size,
853 width, height, 1, comment);
857 static void image_list_init(HIMAGELIST himl)
863 static const struct test_data
866 INT cx, cy, cur, max, grow, width, height, bpp;
870 { 255, BMP_CX, BMP_CX, 1, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 1" },
871 { 170, BMP_CX, BMP_CX, 2, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 2" },
872 { 85, BMP_CX, BMP_CX, 3, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 3" },
873 { 0, BMP_CX, BMP_CX, 4, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 4" },
874 { 0, BMP_CX, BMP_CX, 5, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 5" },
875 { 85, BMP_CX, BMP_CX, 6, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 6" },
876 { 170, BMP_CX, BMP_CX, 7, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 7" },
877 { 255, BMP_CX, BMP_CX, 8, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 8" },
878 { 255, BMP_CX, BMP_CX, 9, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 9" },
879 { 170, BMP_CX, BMP_CX, 10, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 10" },
880 { 85, BMP_CX, BMP_CX, 11, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 11" },
881 { 0, BMP_CX, BMP_CX, 12, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 12" },
882 { 0, BMP_CX, BMP_CX, 13, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 13" },
883 { 85, BMP_CX, BMP_CX, 14, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 14" },
884 { 170, BMP_CX, BMP_CX, 15, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 15" },
885 { 255, BMP_CX, BMP_CX, 16, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 16" },
886 { 255, BMP_CX, BMP_CX, 17, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 17" },
887 { 170, BMP_CX, BMP_CX, 18, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 18" },
888 { 85, BMP_CX, BMP_CX, 19, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 19" },
889 { 0, BMP_CX, BMP_CX, 20, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 20" },
890 { 0, BMP_CX, BMP_CX, 21, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 21" },
891 { 85, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 22" },
892 { 170, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 23" },
893 { 255, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 24" }
896 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "total 0");
898 #define add_bitmap(grey) \
899 sprintf(comment, "%d", n++); \
900 hbm = create_bitmap(BMP_CX, BMP_CX, RGB((grey),(grey),(grey)), comment); \
901 ImageList_Add(himl, hbm, NULL); \
904 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
906 add_bitmap(td[i].grey);
907 check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, td[i].grow,
908 td[i].width, td[i].height, td[i].bpp, td[i].comment);
913 static void test_imagelist_storage(void)
920 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
921 ok(himl != 0, "ImageList_Create failed\n");
923 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "empty");
925 image_list_init(himl);
926 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "orig");
928 ret = ImageList_Remove(himl, 4);
929 ok(ret, "ImageList_Remove failed\n");
930 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "1");
932 ret = ImageList_Remove(himl, 5);
933 ok(ret, "ImageList_Remove failed\n");
934 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "2");
936 ret = ImageList_Remove(himl, 6);
937 ok(ret, "ImageList_Remove failed\n");
938 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "3");
940 ret = ImageList_Remove(himl, 7);
941 ok(ret, "ImageList_Remove failed\n");
942 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "4");
944 ret = ImageList_Remove(himl, -2);
945 ok(!ret, "ImageList_Remove(-2) should fail\n");
946 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "5");
948 ret = ImageList_Remove(himl, 20);
949 ok(!ret, "ImageList_Remove(20) should fail\n");
950 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "6");
952 ret = ImageList_Remove(himl, -1);
953 ok(ret, "ImageList_Remove(-1) failed\n");
954 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "7");
956 ret = ImageList_Destroy(himl);
957 ok(ret, "ImageList_Destroy failed\n");
959 iml_clear_stream_data();
961 /* test ImageList_Create storage allocation */
963 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 0, 32);
964 ok(himl != 0, "ImageList_Create failed\n");
965 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 32, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "init 0 grow 32");
966 hbm = create_bitmap(BMP_CX * 9, BMP_CX, 0, "9");
967 ret = ImageList_Add(himl, hbm, NULL);
968 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
969 check_iml_data(himl, BMP_CX, BMP_CX, 1, 34, 32, BMP_CX * 4, BMP_CX * 9, ILC_COLOR24, "add 1 x 9");
971 ret = ImageList_Destroy(himl);
972 ok(ret, "ImageList_Destroy failed\n");
973 iml_clear_stream_data();
975 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 4);
976 ok(himl != 0, "ImageList_Create failed\n");
977 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 4 grow 4");
978 hbm = create_bitmap(BMP_CX, BMP_CX * 9, 0, "9");
979 ret = ImageList_Add(himl, hbm, NULL);
980 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
981 check_iml_data(himl, BMP_CX, BMP_CX, 9, 15, 4, BMP_CX * 4, BMP_CX * 4, ILC_COLOR24, "add 9 x 1");
982 ret = ImageList_Add(himl, hbm, NULL);
983 ok(ret == 9, "ImageList_Add returned %d, expected 9\n", ret);
984 check_iml_data(himl, BMP_CX, BMP_CX, 18, 25, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "add 9 x 1");
986 ret = ImageList_Destroy(himl);
987 ok(ret, "ImageList_Destroy failed\n");
988 iml_clear_stream_data();
990 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 207, 209);
991 ok(himl != 0, "ImageList_Create failed\n");
992 check_iml_data(himl, BMP_CX, BMP_CX, 0, 208, 212, BMP_CX * 4, BMP_CX * 52, ILC_COLOR24, "init 207 grow 209");
993 ret = ImageList_Destroy(himl);
994 ok(ret, "ImageList_Destroy failed\n");
995 iml_clear_stream_data();
997 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 209, 207);
998 ok(himl != 0, "ImageList_Create failed\n");
999 check_iml_data(himl, BMP_CX, BMP_CX, 0, 210, 208, BMP_CX * 4, BMP_CX * 53, ILC_COLOR24, "init 209 grow 207");
1000 ret = ImageList_Destroy(himl);
1001 ok(ret, "ImageList_Destroy failed\n");
1002 iml_clear_stream_data();
1004 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 14, 4);
1005 ok(himl != 0, "ImageList_Create failed\n");
1006 check_iml_data(himl, BMP_CX, BMP_CX, 0, 15, 4, BMP_CX * 4, BMP_CX * 4, ILC_COLOR24, "init 14 grow 4");
1007 ret = ImageList_Destroy(himl);
1008 ok(ret, "ImageList_Destroy failed\n");
1009 iml_clear_stream_data();
1011 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 5, 9);
1012 ok(himl != 0, "ImageList_Create failed\n");
1013 check_iml_data(himl, BMP_CX, BMP_CX, 0, 6, 12, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 5 grow 9");
1014 ret = ImageList_Destroy(himl);
1015 ok(ret, "ImageList_Destroy failed\n");
1016 iml_clear_stream_data();
1018 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 9, 5);
1019 ok(himl != 0, "ImageList_Create failed\n");
1020 check_iml_data(himl, BMP_CX, BMP_CX, 0, 10, 8, BMP_CX * 4, BMP_CX * 3, ILC_COLOR24, "init 9 grow 5");
1021 ret = ImageList_Destroy(himl);
1022 ok(ret, "ImageList_Destroy failed\n");
1023 iml_clear_stream_data();
1025 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 2, 4);
1026 ok(himl != 0, "ImageList_Create failed\n");
1027 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "init 2 grow 4");
1028 ret = ImageList_Destroy(himl);
1029 ok(ret, "ImageList_Destroy failed\n");
1030 iml_clear_stream_data();
1032 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 2);
1033 ok(himl != 0, "ImageList_Create failed\n");
1034 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 4 grow 2");
1035 ret = ImageList_Destroy(himl);
1036 ok(ret, "ImageList_Destroy failed\n");
1037 iml_clear_stream_data();
1039 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR8, 4, 2);
1040 ok(himl != 0, "ImageList_Create failed\n");
1041 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR8, "bpp 8");
1042 ret = ImageList_Destroy(himl);
1043 ok(ret, "ImageList_Destroy failed\n");
1044 iml_clear_stream_data();
1046 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4, 4, 2);
1047 ok(himl != 0, "ImageList_Create failed\n");
1048 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp 4");
1049 ret = ImageList_Destroy(himl);
1050 ok(ret, "ImageList_Destroy failed\n");
1051 iml_clear_stream_data();
1053 himl = ImageList_Create(BMP_CX, BMP_CX, 0, 4, 2);
1054 ok(himl != 0, "ImageList_Create failed\n");
1055 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp default");
1056 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1057 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1058 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1059 DestroyIcon( icon );
1060 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp default");
1061 ret = ImageList_Destroy(himl);
1062 ok(ret, "ImageList_Destroy failed\n");
1063 iml_clear_stream_data();
1065 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24|ILC_MASK, 4, 2);
1066 ok(himl != 0, "ImageList_Create failed\n");
1067 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24|ILC_MASK,
1069 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1070 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1071 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1072 DestroyIcon( icon );
1073 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24|ILC_MASK,
1075 ret = ImageList_Destroy(himl);
1076 ok(ret, "ImageList_Destroy failed\n");
1077 iml_clear_stream_data();
1079 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 4, 2);
1080 ok(himl != 0, "ImageList_Create failed\n");
1081 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4|ILC_MASK,
1083 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1084 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1085 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1086 DestroyIcon( icon );
1087 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4|ILC_MASK,
1089 ret = ImageList_Destroy(himl);
1090 ok(ret, "ImageList_Destroy failed\n");
1091 iml_clear_stream_data();
1093 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 99);
1094 ok(himl != 0, "ImageList_Create failed\n");
1095 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 100, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1097 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1098 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1099 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1100 check_iml_data(himl, BMP_CX, BMP_CX, 2, 3, 100, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1101 "init 2 grow 99 2 icons");
1102 ok( ImageList_AddIcon(himl, icon) == 2,"failed to add icon\n");
1103 DestroyIcon( icon );
1104 check_iml_data(himl, BMP_CX, BMP_CX, 3, 104, 100, BMP_CX * 4, BMP_CX * 104/4, ILC_COLOR4|ILC_MASK,
1105 "init 2 grow 99 3 icons");
1106 ok( ImageList_Remove(himl, -1) == TRUE,"failed to remove icon\n");
1107 check_iml_data(himl, BMP_CX, BMP_CX, 0, 100, 100, BMP_CX * 4, BMP_CX * 100/4, ILC_COLOR4|ILC_MASK,
1108 "init 2 grow 99 empty");
1109 ok( ImageList_SetImageCount(himl, 22) == TRUE,"failed to set image count\n");
1110 check_iml_data(himl, BMP_CX, BMP_CX, 22, 23, 100, BMP_CX * 4, BMP_CX * 24/4, ILC_COLOR4|ILC_MASK,
1111 "init 2 grow 99 set count 22");
1112 ok( ImageList_SetImageCount(himl, 0) == TRUE,"failed to set image count\n");
1113 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 100, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1114 "init 2 grow 99 set count 0");
1115 ok( ImageList_SetImageCount(himl, 42) == TRUE,"failed to set image count\n");
1116 check_iml_data(himl, BMP_CX, BMP_CX, 42, 43, 100, BMP_CX * 4, BMP_CX * 44/4, ILC_COLOR4|ILC_MASK,
1117 "init 2 grow 99 set count 42");
1118 ret = ImageList_Destroy(himl);
1119 ok(ret, "ImageList_Destroy failed\n");
1120 iml_clear_stream_data();
1122 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65536+12);
1123 ok(himl != 0, "ImageList_Create failed\n");
1124 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 12, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1125 "init 2 grow 65536+12");
1126 ret = ImageList_Destroy(himl);
1127 ok(ret, "ImageList_Destroy failed\n");
1128 iml_clear_stream_data();
1130 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65535);
1131 ok(himl != 0, "ImageList_Create failed\n");
1132 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 0, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1133 "init 2 grow 65535");
1134 ret = ImageList_Destroy(himl);
1135 ok(ret, "ImageList_Destroy failed\n");
1136 iml_clear_stream_data();
1138 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, -20);
1139 ok(himl != 0, "ImageList_Create failed\n");
1140 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1142 ret = ImageList_Destroy(himl);
1143 ok(ret, "ImageList_Destroy failed\n");
1144 iml_clear_stream_data();
1147 static void test_shell_imagelist(void)
1149 BOOL (WINAPI *pSHGetImageList)(INT, REFIID, void**);
1150 IImageList *iml = NULL;
1157 /* Try to load function from shell32 */
1158 hShell32 = LoadLibrary("shell32.dll");
1159 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1161 if (!pSHGetImageList)
1163 win_skip("SHGetImageList not available, skipping test\n");
1167 /* Get system image list */
1168 hr = (pSHGetImageList)(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1170 ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1175 IImageList_GetImageCount(iml, &out);
1176 ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1178 /* Fetch the small icon size */
1179 cx = GetSystemMetrics(SM_CXSMICON);
1180 cy = GetSystemMetrics(SM_CYSMICON);
1182 /* Check icon size matches */
1183 IImageList_GetImageRect(iml, 0, &rect);
1184 ok(((rect.right == cx) && (rect.bottom == cy)),
1185 "IImageList_GetImageRect returned r:%d,b:%d\n",
1186 rect.right, rect.bottom);
1188 IImageList_Release(iml);
1189 FreeLibrary(hShell32);
1192 static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
1195 UINT32 *buffer = NULL;
1196 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
1199 hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1200 ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1202 if(!hBitmap || !buffer)
1204 DeleteObject(hBitmap);
1214 static BOOL colour_match(UINT32 x, UINT32 y)
1216 const INT32 tolerance = 8;
1218 const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1219 const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1220 const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1222 return (dr <= tolerance && dg <= tolerance && db <= tolerance);
1225 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1226 UINT32 expected, int line)
1228 bits[0] = 0x00FFFFFF;
1229 pImageList_DrawIndirect(ildp);
1230 ok(colour_match(bits[0], expected),
1231 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1232 bits[0] & 0x00FFFFFF, expected, line);
1236 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1237 UINT fStyle, UINT32 expected, int line)
1239 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1240 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1241 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1244 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1245 DWORD dwRop, UINT32 expected, int line)
1247 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1248 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1249 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1252 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1253 UINT fState, DWORD Frame, UINT32 expected, int line)
1255 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1256 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1257 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1260 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1261 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1262 UINT32 broken_expected, int line)
1264 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1265 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1266 bits[0] = 0x00FFFFFF;
1267 pImageList_DrawIndirect(&ildp);
1268 ok(colour_match(bits[0], expected) ||
1269 broken(colour_match(bits[0], broken_expected)),
1270 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1271 bits[0] & 0x00FFFFFF, expected, line);
1274 static void test_ImageList_DrawIndirect(void)
1276 HIMAGELIST himl = NULL;
1279 HBITMAP hbmOld = NULL, hbmDst = NULL;
1280 HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1281 HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
1282 int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1284 UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1285 int bpp, broken_value;
1287 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1290 hdcDst = CreateCompatibleDC(0);
1291 ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1294 bpp = GetDeviceCaps(hdcDst, BITSPIXEL);
1296 hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1297 ok(hbmMask != 0, "CreateBitmap failed\n");
1298 if(!hbmMask) goto cleanup;
1300 hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1301 ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1302 if(!hbmInverseMask) goto cleanup;
1304 himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1305 ok(himl != 0, "ImageList_Create failed\n");
1306 if(!himl) goto cleanup;
1308 /* Add a no-alpha image */
1309 hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
1310 if(!hbmImage) goto cleanup;
1312 iImage = pImageList_Add(himl, hbmImage, hbmMask);
1313 ok(iImage != -1, "ImageList_Add failed\n");
1314 if(iImage == -1) goto cleanup;
1316 /* Add an alpha image */
1317 hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
1318 if(!hbmAlphaImage) goto cleanup;
1320 iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1321 ok(iAlphaImage != -1, "ImageList_Add failed\n");
1322 if(iAlphaImage == -1) goto cleanup;
1324 /* Add a transparent alpha image */
1325 hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
1326 if(!hbmTransparentImage) goto cleanup;
1328 iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1329 ok(iTransparentImage != -1, "ImageList_Add failed\n");
1330 if(iTransparentImage == -1) goto cleanup;
1333 bitmapInfo.bmiHeader.biBitCount = 32;
1334 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1335 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1336 if (!hbmDst || !bits)
1338 hbmOld = SelectObject(hdcDst, hbmDst);
1340 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1341 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1342 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
1343 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1344 else broken_value = 0x00B4BDC4;
1345 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1346 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1347 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1348 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1350 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
1351 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
1353 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1354 else broken_value = 0x009DA8B1;
1355 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1356 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1357 else broken_value = 0x008C99A3;
1358 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1359 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
1360 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
1361 todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
1363 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
1365 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1366 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
1368 /* ILD_ROP is ignored when the image has an alpha channel */
1369 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
1370 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
1372 todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
1373 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
1375 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
1376 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
1378 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
1379 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
1380 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
1385 SelectObject(hdcDst, hbmOld);
1387 DeleteObject(hbmDst);
1393 DeleteObject(hbmMask);
1395 DeleteObject(hbmInverseMask);
1398 DeleteObject(hbmImage);
1400 DeleteObject(hbmAlphaImage);
1401 if(hbmTransparentImage)
1402 DeleteObject(hbmTransparentImage);
1406 ret = ImageList_Destroy(himl);
1407 ok(ret, "ImageList_Destroy failed\n");
1411 static void test_iimagelist(void)
1413 IImageList *imgl, *imgl2;
1418 if (!pHIMAGELIST_QueryInterface)
1420 win_skip("XP imagelist functions not available\n");
1424 /* test reference counting on destruction */
1425 imgl = (IImageList*)createImageList(32, 32);
1426 ret = IImageList_AddRef(imgl);
1427 ok(ret == 2, "Expected 2, got %d\n", ret);
1428 ret = ImageList_Destroy((HIMAGELIST)imgl);
1429 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1430 ret = ImageList_Destroy((HIMAGELIST)imgl);
1431 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1432 ret = ImageList_Destroy((HIMAGELIST)imgl);
1433 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1435 imgl = (IImageList*)createImageList(32, 32);
1436 ret = IImageList_AddRef(imgl);
1437 ok(ret == 2, "Expected 2, got %d\n", ret);
1438 ret = ImageList_Destroy((HIMAGELIST)imgl);
1439 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1440 ret = IImageList_Release(imgl);
1441 ok(ret == 0, "Expected 0, got %d\n", ret);
1442 ret = ImageList_Destroy((HIMAGELIST)imgl);
1443 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1445 /* ref counting, HIMAGELIST_QueryInterface adds a reference */
1446 imgl = (IImageList*)createImageList(32, 32);
1447 hr = pHIMAGELIST_QueryInterface((HIMAGELIST)imgl, &IID_IImageList, (void**)&imgl2);
1448 ok(hr == S_OK, "got 0x%08x\n", hr);
1449 ok(imgl2 == imgl, "got different pointer\n");
1450 ret = IImageList_Release(imgl);
1451 ok(ret == 1, "got %u\n", ret);
1452 IImageList_Release(imgl);
1454 if (!pImageList_CoCreateInstance)
1456 win_skip("Vista imagelist functions not available\n");
1460 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1461 ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
1464 IImageList_Release(imgl);
1466 himl = createImageList(32, 32);
1471 hr = (pHIMAGELIST_QueryInterface)(himl, &IID_IImageList, (void **) &imgl);
1472 ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
1475 IImageList_Release(imgl);
1477 ImageList_Destroy(himl);
1480 static void test_hotspot_v6(void)
1491 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
1492 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
1499 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
1500 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
1501 IImageList *imgl1, *imgl2;
1504 /* cast to IImageList */
1505 imgl1 = (IImageList *) himl1;
1506 imgl2 = (IImageList *) himl2;
1508 for (i = 0; i < HOTSPOTS_MAX; i++) {
1509 for (j = 0; j < HOTSPOTS_MAX; j++) {
1510 int dx1 = hotspots[i].dx;
1511 int dy1 = hotspots[i].dy;
1512 int dx2 = hotspots[j].dx;
1513 int dy2 = hotspots[j].dy;
1514 int correctx, correcty, newx, newy;
1516 IImageList *imglNew;
1519 hr = IImageList_BeginDrag(imgl1, 0, dx1, dy1);
1520 ok(SUCCEEDED(hr), "BeginDrag failed for { %d, %d }\n", dx1, dy1);
1521 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
1523 /* check merging the dragged image with a second image */
1524 hr = IImageList_SetDragCursorImage(imgl2, (IUnknown *) imgl2, 0, dx2, dy2);
1525 ok(SUCCEEDED(hr), "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
1526 dx1, dy1, dx2, dy2);
1527 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
1529 /* check new hotspot, it should be the same like the old one */
1530 hr = IImageList_GetDragImage(imgl2, NULL, &ppt, &IID_IImageList, (PVOID *) &imglNew);
1531 ok(SUCCEEDED(hr), "GetDragImage failed\n");
1532 ok(ppt.x == dx1 && ppt.y == dy1,
1533 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
1534 dx1, dy1, ppt.x, ppt.y);
1535 /* check size of new dragged image */
1536 IImageList_GetIconSize(imglNew, &newx, &newy);
1537 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
1538 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
1539 ok(newx == correctx && newy == correcty,
1540 "Expected drag image size [%d,%d] got [%d,%d]\n",
1541 correctx, correcty, newx, newy);
1542 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
1543 IImageList_EndDrag(imgl2);
1551 IImageList_Release(imgl2);
1552 IImageList_Release(imgl1);
1555 static void test_IImageList_Add_Remove(void)
1567 /* create an imagelist to play with */
1568 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1569 ok(himl != 0,"failed to create imagelist\n");
1571 imgl = (IImageList *) himl;
1573 /* load the icons to add to the image list */
1574 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1575 ok(hicon1 != 0, "no hicon1\n");
1576 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1577 ok(hicon2 != 0, "no hicon2\n");
1578 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1579 ok(hicon3 != 0, "no hicon3\n");
1581 /* remove when nothing exists */
1582 hr = IImageList_Remove(imgl, 0);
1583 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1585 /* removing everything from an empty imagelist should succeed */
1586 hr = IImageList_Remove(imgl, -1);
1587 ok(hr == S_OK, "removed nonexistent icon\n");
1591 ok( IImageList_ReplaceIcon(imgl, -1, hicon1, &ret) == S_OK && (ret == 0),"failed to add icon1\n");
1593 ok( IImageList_ReplaceIcon(imgl, -1, hicon2, &ret) == S_OK && (ret == 1),"failed to add icon2\n");
1595 ok( IImageList_ReplaceIcon(imgl, -1, hicon3, &ret) == S_OK && (ret == 2),"failed to add icon3\n");
1597 /* remove an index out of range */
1598 ok( IImageList_Remove(imgl, 4711) == E_INVALIDARG, "got 0x%08x\n", hr);
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");
1603 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1605 /* remove one extra */
1606 ok( IImageList_Remove(imgl, 0) == E_INVALIDARG, "got 0x%08x\n", hr);
1608 IImageList_Release(imgl);
1609 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1610 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1611 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1614 static void test_IImageList_Get_SetImageCount(void)
1621 /* create an imagelist to play with */
1622 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1623 ok(himl != 0,"failed to create imagelist\n");
1625 imgl = (IImageList *) himl;
1627 /* check SetImageCount/GetImageCount */
1628 hr = IImageList_SetImageCount(imgl, 3);
1629 ok(hr == S_OK, "got 0x%08x\n", hr);
1631 hr = IImageList_GetImageCount(imgl, &ret);
1632 ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
1633 hr = IImageList_SetImageCount(imgl, 1);
1634 ok(hr == S_OK, "got 0x%08x\n", hr);
1636 hr = IImageList_GetImageCount(imgl, &ret);
1637 ok(hr == S_OK && ret == 1, "invalid image count after decrease to 1\n");
1638 hr = IImageList_SetImageCount(imgl, 0);
1639 ok(hr == S_OK, "got 0x%08x\n", hr);
1641 hr = IImageList_GetImageCount(imgl, &ret);
1642 ok(hr == S_OK && ret == 0, "invalid image count after decrease to 0\n");
1644 IImageList_Release(imgl);
1647 static void test_IImageList_Draw(void)
1656 IMAGELISTDRAWPARAMS imldp;
1662 hwndfortest = create_a_window();
1663 hdc = GetDC(hwndfortest);
1664 ok(hdc!=NULL, "couldn't get DC\n");
1666 /* create an imagelist to play with */
1667 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1668 ok(himl!=0,"failed to create imagelist\n");
1670 imgl = (IImageList *) himl;
1672 /* load the icons to add to the image list */
1673 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1674 ok(hbm1 != 0, "no bitmap 1\n");
1675 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1676 ok(hbm2 != 0, "no bitmap 2\n");
1677 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1678 ok(hbm3 != 0, "no bitmap 3\n");
1682 ok( IImageList_Add(imgl, hbm1, 0, &ret) == S_OK && (ret == 0), "failed to add bitmap 1\n");
1684 ok( IImageList_Add(imgl, hbm2, 0, &ret) == S_OK && (ret == 1), "failed to add bitmap 2\n");
1686 ok( IImageList_SetImageCount(imgl, 3) == S_OK, "Setimage count failed\n");
1687 ok( IImageList_Replace(imgl, 2, hbm3, 0) == S_OK, "failed to replace bitmap 3\n");
1691 /* crashes on native */
1692 IImageList_Draw(imgl, NULL);
1695 memset(&imldp, 0, sizeof (imldp));
1696 hr = IImageList_Draw(imgl, &imldp);
1697 ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
1699 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
1703 REDRAW(hwndfortest);
1706 imldp.fStyle = SRCCOPY;
1707 imldp.rgbBk = CLR_DEFAULT;
1708 imldp.rgbFg = CLR_DEFAULT;
1711 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1713 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1715 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1717 ok( IImageList_Draw(imgl, &imldp) == E_INVALIDARG, "should fail\n");
1720 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 1st bitmap\n");
1721 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 2nd bitmap\n");
1722 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 3rd bitmap\n");
1725 IImageList_Release(imgl);
1727 /* bitmaps should not be deleted by the imagelist */
1728 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1729 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1730 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1732 ReleaseDC(hwndfortest, hdc);
1733 DestroyWindow(hwndfortest);
1736 static void test_IImageList_Merge(void)
1738 HIMAGELIST himl1, himl2;
1739 IImageList *imgl1, *imgl2, *merge;
1741 HWND hwnd = create_a_window();
1745 himl1 = ImageList_Create(32,32,0,0,3);
1746 ok(himl1 != NULL,"failed to create himl1\n");
1748 himl2 = ImageList_Create(32,32,0,0,3);
1749 ok(himl2 != NULL,"failed to create himl2\n");
1751 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1752 ok(hicon1 != NULL, "failed to create hicon1\n");
1754 if (!himl1 || !himl2 || !hicon1)
1757 /* cast to IImageList */
1758 imgl1 = (IImageList *) himl1;
1759 imgl2 = (IImageList *) himl2;
1762 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl2 failed\n");
1766 /* null cases that crash on native */
1767 IImageList_Merge(imgl1, -1, NULL, 0, 0, 0, &IID_IImageList, (void**)&merge);
1768 IImageList_Merge(imgl1, -1, (IUnknown*) imgl2, 0, 0, 0, &IID_IImageList, NULL);
1771 /* If himl1 has no images, merge still succeeds */
1772 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1773 ok(hr == S_OK, "merge himl1,-1 failed\n");
1774 if (hr == S_OK) IImageList_Release(merge);
1776 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1777 ok(hr == S_OK, "merge himl1,0 failed\n");
1778 if (hr == S_OK) IImageList_Release(merge);
1780 /* Same happens if himl2 is empty */
1781 IImageList_Release(imgl2);
1782 himl2 = ImageList_Create(32,32,0,0,3);
1783 ok(himl2 != NULL,"failed to recreate himl2\n");
1785 imgl2 = (IImageList *) himl2;
1787 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
1788 ok(hr == S_OK, "merge himl2,-1 failed\n");
1789 if (hr == S_OK) IImageList_Release(merge);
1791 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1792 ok(hr == S_OK, "merge himl2,0 failed\n");
1793 if (hr == S_OK) IImageList_Release(merge);
1795 /* Now try merging an image with itself */
1797 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"re-add icon1 to himl2 failed\n");
1799 hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1800 ok(hr == S_OK, "merge himl2 with itself failed\n");
1801 if (hr == S_OK) IImageList_Release(merge);
1803 /* Try merging 2 different image lists */
1805 ok( IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl1 failed\n");
1807 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1808 ok(hr == S_OK, "merge himl1 with himl2 failed\n");
1809 if (hr == S_OK) IImageList_Release(merge);
1811 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
1812 ok(hr == S_OK, "merge himl1 with himl2 8,16 failed\n");
1813 if (hr == S_OK) IImageList_Release(merge);
1815 IImageList_Release(imgl1);
1816 IImageList_Release(imgl2);
1818 DestroyIcon(hicon1);
1819 DestroyWindow(hwnd);
1822 static void test_iconsize(void)
1828 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1829 /* null pointers, not zero imagelist dimensions */
1830 ret = ImageList_GetIconSize(himl, NULL, NULL);
1831 ok(!ret, "got %d\n", ret);
1833 /* doesn't touch return pointers */
1835 ret = ImageList_GetIconSize(himl, &cx, NULL);
1836 ok(!ret, "got %d\n", ret);
1837 ok(cx == 0x1abe11ed, "got %d\n", cx);
1840 ret = ImageList_GetIconSize(himl, NULL, &cy);
1841 ok(!ret, "got %d\n", ret);
1842 ok(cy == 0x1abe11ed, "got %d\n", cy);
1844 ImageList_Destroy(himl);
1846 ret = ImageList_GetIconSize((HIMAGELIST)0xdeadbeef, &cx, &cy);
1847 ok(!ret, "got %d\n", ret);
1850 static void test_create_destroy(void)
1855 /* list with zero or negative image dimensions */
1856 himl = ImageList_Create(0, 0, ILC_COLOR16, 0, 3);
1857 ok(himl == NULL, "got %p\n", himl);
1859 himl = ImageList_Create(0, 16, ILC_COLOR16, 0, 3);
1860 ok(himl == NULL, "got %p\n", himl);
1862 himl = ImageList_Create(16, 0, ILC_COLOR16, 0, 3);
1863 ok(himl == NULL, "got %p\n", himl);
1865 himl = ImageList_Create(16, -1, ILC_COLOR16, 0, 3);
1866 ok(himl == NULL, "got %p\n", himl);
1868 himl = ImageList_Create(-1, 16, ILC_COLOR16, 0, 3);
1869 ok(himl == NULL, "got %p\n", himl);
1871 rc = ImageList_Destroy((HIMAGELIST)0xdeadbeef);
1872 ok(rc == FALSE, "ImageList_Destroy(0xdeadbeef) should fail and not crash\n");
1875 static void test_IImageList_Clone(void)
1877 IImageList *imgl, *imgl2;
1882 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1883 imgl = (IImageList*)himl;
1887 /* crashes on native */
1888 IImageList_Clone(imgl, &IID_IImageList, NULL);
1891 hr = IImageList_Clone(imgl, &IID_IImageList, (void**)&imgl2);
1892 ok(hr == S_OK, "got 0x%08x\n", hr);
1893 ref = IImageList_Release(imgl2);
1894 ok(ref == 0, "got %u\n", ref);
1896 IImageList_Release(imgl);
1899 static void test_IImageList_GetBkColor(void)
1906 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1907 imgl = (IImageList*)himl;
1911 /* crashes on native */
1912 IImageList_GetBkColor(imgl, NULL);
1915 hr = IImageList_GetBkColor(imgl, &color);
1916 ok(hr == S_OK, "got 0x%08x\n", hr);
1918 IImageList_Release(imgl);
1921 static void test_IImageList_SetBkColor(void)
1928 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1929 imgl = (IImageList*)himl;
1933 /* crashes on native */
1934 IImageList_SetBkColor(imgl, RGB(0, 0, 0), NULL);
1937 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1938 ok(hr == S_OK, "got 0x%08x\n", hr);
1940 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1941 ok(hr == S_OK, "got 0x%08x\n", hr);
1944 hr = IImageList_GetBkColor(imgl, &color);
1945 ok(hr == S_OK, "got 0x%08x\n", hr);
1946 ok(color == CLR_NONE, "got %x\n", color);
1948 IImageList_Release(imgl);
1951 static void test_IImageList_GetImageCount(void)
1958 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1959 imgl = (IImageList*)himl;
1963 /* crashes on native */
1964 IImageList_GetImageCount(imgl, NULL);
1968 hr = IImageList_GetImageCount(imgl, &count);
1969 ok(hr == S_OK, "got 0x%08x\n", hr);
1970 ok(count == 0, "got %d\n", count);
1972 IImageList_Release(imgl);
1975 static void test_IImageList_GetIconSize(void)
1982 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1983 imgl = (IImageList*)himl;
1985 hr = IImageList_GetIconSize(imgl, NULL, NULL);
1986 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1988 hr = IImageList_GetIconSize(imgl, &cx, NULL);
1989 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1991 hr = IImageList_GetIconSize(imgl, NULL, &cy);
1992 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1994 IImageList_Release(imgl);
1997 START_TEST(imagelist)
1999 ULONG_PTR ctx_cookie;
2002 HMODULE hComCtl32 = GetModuleHandle("comctl32.dll");
2003 pImageList_Create = NULL; /* These are not needed for non-v6.0 tests*/
2004 pImageList_Add = NULL;
2005 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
2006 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
2008 hinst = GetModuleHandleA(NULL);
2010 InitCommonControls();
2012 test_create_destroy();
2016 test_DrawIndirect();
2018 test_imagelist_storage();
2021 FreeLibrary(hComCtl32);
2023 /* Now perform v6 tests */
2025 if (!load_v6_module(&ctx_cookie, &hCtx))
2028 /* Reload comctl32 */
2029 hComCtl32 = LoadLibraryA("comctl32.dll");
2030 pImageList_Create = (void*)GetProcAddress(hComCtl32, "ImageList_Create");
2031 pImageList_Add = (void*)GetProcAddress(hComCtl32, "ImageList_Add");
2032 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
2033 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
2034 pImageList_CoCreateInstance = (void*)GetProcAddress(hComCtl32, "ImageList_CoCreateInstance");
2035 pHIMAGELIST_QueryInterface = (void*)GetProcAddress(hComCtl32, "HIMAGELIST_QueryInterface");
2037 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2040 test_ImageList_DrawIndirect();
2041 test_shell_imagelist();
2045 test_IImageList_Add_Remove();
2046 test_IImageList_Get_SetImageCount();
2047 test_IImageList_Draw();
2048 test_IImageList_Merge();
2049 test_IImageList_Clone();
2050 test_IImageList_GetBkColor();
2051 test_IImageList_SetBkColor();
2052 test_IImageList_GetImageCount();
2053 test_IImageList_GetIconSize();
2057 unload_v6_module(ctx_cookie, hCtx);