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);
132 static HWND create_a_window(void)
134 char className[] = "bmwnd";
135 char winName[] = "Test Bitmap";
137 static int registered = 0;
143 cls.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
144 cls.lpfnWndProc = DefWindowProcA;
148 cls.hIcon = LoadIconA (0, IDI_APPLICATION);
149 cls.hCursor = LoadCursorA (0, IDC_ARROW);
150 cls.hbrBackground = GetStockObject (WHITE_BRUSH);
151 cls.lpszMenuName = 0;
152 cls.lpszClassName = className;
154 RegisterClassA (&cls);
159 hWnd = CreateWindowA (className, winName,
160 WS_OVERLAPPEDWINDOW ,
161 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
165 ShowWindow (hWnd, SW_SHOW);
173 static HDC show_image(HWND hwnd, HIMAGELIST himl, int idx, int size,
174 LPCSTR loc, BOOL clear)
178 if (!himl) return NULL;
180 SetWindowText(hwnd, loc);
182 ImageList_Draw(himl, idx, hdc, 0, 0, ILD_TRANSPARENT);
189 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
190 ReleaseDC(hwnd, hdc);
197 /* Useful for checking differences */
199 static void dump_bits(const BYTE *p, const BYTE *q, int size)
205 for (i = 0; i < size * 2; i++)
208 for (j = 0; j < size; j++)
209 printf("%c%c", p[j] & 0xf0 ? 'X' : ' ', p[j] & 0xf ? 'X' : ' ');
211 for (j = 0; j < size; j++)
212 printf("%c%c", q[j] & 0xf0 ? 'X' : ' ', q[j] & 0xf ? 'X' : ' ');
221 static void check_bits(HWND hwnd, HIMAGELIST himl, int idx, int size,
222 const BYTE *checkbits, LPCSTR loc)
225 BYTE bits[100*100/8];
232 memset(bits, 0, sizeof(bits));
233 hdc = show_image(hwnd, himl, idx, size, loc, FALSE);
235 c = GetPixel(hdc, 0, 0);
237 for (y = 0; y < size; y ++)
239 for (x = 0; x < size; x++)
242 if (GetPixel(hdc, x, y) != c) bits[i] |= (0x80 >> (x & 0x7));
246 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
247 ReleaseDC(hwnd, hdc);
249 ok (memcmp(bits, checkbits, (size * size)/8) == 0,
250 "%s: bits different\n", loc);
251 if (memcmp(bits, checkbits, (size * size)/8))
252 dump_bits(bits, checkbits, size);
256 static void testHotspot (void)
267 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
268 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
275 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
276 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
277 HWND hwnd = create_a_window();
280 for (i = 0; i < HOTSPOTS_MAX; i++) {
281 for (j = 0; j < HOTSPOTS_MAX; j++) {
282 int dx1 = hotspots[i].dx;
283 int dy1 = hotspots[i].dy;
284 int dx2 = hotspots[j].dx;
285 int dy2 = hotspots[j].dy;
286 int correctx, correcty, newx, newy;
291 ret = ImageList_BeginDrag(himl1, 0, dx1, dy1);
292 ok(ret != 0, "BeginDrag failed for { %d, %d }\n", dx1, dy1);
293 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
294 show_image(hwnd, himl1, 0, max(SIZEX1, SIZEY1), loc, TRUE);
296 /* check merging the dragged image with a second image */
297 ret = ImageList_SetDragCursorImage(himl2, 0, dx2, dy2);
298 ok(ret != 0, "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
300 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
301 show_image(hwnd, himl2, 0, max(SIZEX2, SIZEY2), loc, TRUE);
303 /* check new hotspot, it should be the same like the old one */
304 himlNew = ImageList_GetDragImage(NULL, &ppt);
305 ok(ppt.x == dx1 && ppt.y == dy1,
306 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
307 dx1, dy1, ppt.x, ppt.y);
308 /* check size of new dragged image */
309 ImageList_GetIconSize(himlNew, &newx, &newy);
310 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
311 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
312 ok(newx == correctx && newy == correcty,
313 "Expected drag image size [%d,%d] got [%d,%d]\n",
314 correctx, correcty, newx, newy);
315 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
316 show_image(hwnd, himlNew, 0, max(correctx, correcty), loc, TRUE);
325 ImageList_Destroy(himl2);
326 ImageList_Destroy(himl1);
330 static BOOL DoTest1(void)
338 /* create an imagelist to play with */
339 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
340 ok(himl!=0,"failed to create imagelist\n");
342 /* load the icons to add to the image list */
343 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
344 ok(hicon1 != 0, "no hicon1\n");
345 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
346 ok(hicon2 != 0, "no hicon2\n");
347 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
348 ok(hicon3 != 0, "no hicon3\n");
350 /* remove when nothing exists */
351 ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
352 /* removing everything from an empty imagelist should succeed */
353 ok(ImageList_RemoveAll(himl),"removed nonexistent icon\n");
356 ok(0==ImageList_AddIcon(himl, hicon1),"failed to add icon1\n");
357 ok(1==ImageList_AddIcon(himl, hicon2),"failed to add icon2\n");
358 ok(2==ImageList_AddIcon(himl, hicon3),"failed to add icon3\n");
360 /* remove an index out of range */
361 ok(!ImageList_Remove(himl,4711),"removed nonexistent icon\n");
364 ok(ImageList_Remove(himl,0),"can't remove 0\n");
365 ok(ImageList_Remove(himl,0),"can't remove 0\n");
366 ok(ImageList_Remove(himl,0),"can't remove 0\n");
368 /* remove one extra */
369 ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
371 /* check SetImageCount/GetImageCount */
372 if (pImageList_SetImageCount)
374 ok(pImageList_SetImageCount(himl, 3), "couldn't increase image count\n");
375 ok(ImageList_GetImageCount(himl) == 3, "invalid image count after increase\n");
376 ok(pImageList_SetImageCount(himl, 1), "couldn't decrease image count\n");
377 ok(ImageList_GetImageCount(himl) == 1, "invalid image count after decrease to 1\n");
378 ok(pImageList_SetImageCount(himl, 0), "couldn't decrease image count\n");
379 ok(ImageList_GetImageCount(himl) == 0, "invalid image count after decrease to 0\n");
383 skip("skipped ImageList_SetImageCount tests\n");
387 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
389 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
390 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
391 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
396 static BOOL DoTest2(void)
404 /* create an imagelist to play with */
405 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
406 ok(himl!=0,"failed to create imagelist\n");
408 /* load the icons to add to the image list */
409 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
410 ok(hicon1 != 0, "no hicon1\n");
411 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
412 ok(hicon2 != 0, "no hicon2\n");
413 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
414 ok(hicon3 != 0, "no hicon3\n");
417 ok(0==ImageList_AddIcon(himl, hicon1),"failed to add icon1\n");
418 ok(1==ImageList_AddIcon(himl, hicon2),"failed to add icon2\n");
419 ok(2==ImageList_AddIcon(himl, hicon3),"failed to add icon3\n");
422 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
424 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
425 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
426 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
431 static BOOL DoTest3(void)
439 IMAGELISTDRAWPARAMS imldp;
443 if (!pImageList_DrawIndirect)
445 win_skip("ImageList_DrawIndirect not available, skipping test\n");
449 hwndfortest = create_a_window();
450 hdc = GetDC(hwndfortest);
451 ok(hdc!=NULL, "couldn't get DC\n");
453 /* create an imagelist to play with */
454 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
455 ok(himl!=0,"failed to create imagelist\n");
457 /* load the icons to add to the image list */
458 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
459 ok(hbm1 != 0, "no bitmap 1\n");
460 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
461 ok(hbm2 != 0, "no bitmap 2\n");
462 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
463 ok(hbm3 != 0, "no bitmap 3\n");
466 ok(0==ImageList_Add(himl, hbm1, 0),"failed to add bitmap 1\n");
467 ok(1==ImageList_Add(himl, hbm2, 0),"failed to add bitmap 2\n");
469 if (pImageList_SetImageCount)
471 ok(pImageList_SetImageCount(himl,3),"Setimage count failed\n");
472 /*ok(2==ImageList_Add(himl, hbm3, NULL),"failed to add bitmap 3\n"); */
473 ok(ImageList_Replace(himl, 2, hbm3, 0),"failed to replace bitmap 3\n");
476 memset(&imldp, 0, sizeof (imldp));
477 ok(!pImageList_DrawIndirect(&imldp), "zero data succeeded!\n");
478 imldp.cbSize = sizeof (imldp);
479 ok(!pImageList_DrawIndirect(&imldp), "zero hdc succeeded!\n");
481 ok(!pImageList_DrawIndirect(&imldp),"zero himl succeeded!\n");
483 if (!pImageList_DrawIndirect(&imldp))
485 /* Earlier versions of native comctl32 use a smaller structure */
486 imldp.cbSize -= 3 * sizeof(DWORD);
487 ok(pImageList_DrawIndirect(&imldp),"DrawIndirect should succeed\n");
492 imldp.fStyle = SRCCOPY;
493 imldp.rgbBk = CLR_DEFAULT;
494 imldp.rgbFg = CLR_DEFAULT;
497 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
499 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
501 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
503 ok(!pImageList_DrawIndirect(&imldp),"should fail\n");
506 ok(ImageList_Remove(himl, 0), "removing 1st bitmap\n");
507 ok(ImageList_Remove(himl, 0), "removing 2nd bitmap\n");
508 ok(ImageList_Remove(himl, 0), "removing 3rd bitmap\n");
511 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
513 /* bitmaps should not be deleted by the imagelist */
514 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
515 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
516 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
518 ReleaseDC(hwndfortest, hdc);
519 DestroyWindow(hwndfortest);
524 static void testMerge(void)
526 HIMAGELIST himl1, himl2, hmerge;
528 HWND hwnd = create_a_window();
530 himl1 = ImageList_Create(32,32,0,0,3);
531 ok(himl1 != NULL,"failed to create himl1\n");
533 himl2 = ImageList_Create(32,32,0,0,3);
534 ok(himl2 != NULL,"failed to create himl2\n");
536 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
537 ok(hicon1 != NULL, "failed to create hicon1\n");
539 if (!himl1 || !himl2 || !hicon1)
542 ok(0==ImageList_AddIcon(himl2, hicon1),"add icon1 to himl2 failed\n");
543 check_bits(hwnd, himl2, 0, 32, icon_bits, "add icon1 to himl2");
545 /* If himl1 has no images, merge still succeeds */
546 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
547 ok(hmerge != NULL, "merge himl1,-1 failed\n");
548 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,-1");
549 if (hmerge) ImageList_Destroy(hmerge);
551 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
552 ok(hmerge != NULL,"merge himl1,0 failed\n");
553 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,0");
554 if (hmerge) ImageList_Destroy(hmerge);
556 /* Same happens if himl2 is empty */
557 ImageList_Destroy(himl2);
558 himl2 = ImageList_Create(32,32,0,0,3);
559 ok(himl2 != NULL,"failed to recreate himl2\n");
563 hmerge = ImageList_Merge(himl1, -1, himl2, -1, 0, 0);
564 ok(hmerge != NULL, "merge himl2,-1 failed\n");
565 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,-1");
566 if (hmerge) ImageList_Destroy(hmerge);
568 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
569 ok(hmerge != NULL, "merge himl2,0 failed\n");
570 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,0");
571 if (hmerge) ImageList_Destroy(hmerge);
573 /* Now try merging an image with itself */
574 ok(0==ImageList_AddIcon(himl2, hicon1),"re-add icon1 to himl2 failed\n");
576 hmerge = ImageList_Merge(himl2, 0, himl2, 0, 0, 0);
577 ok(hmerge != NULL, "merge himl2 with itself failed\n");
578 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2 with itself");
579 if (hmerge) ImageList_Destroy(hmerge);
581 /* Try merging 2 different image lists */
582 ok(0==ImageList_AddIcon(himl1, hicon1),"add icon1 to himl1 failed\n");
584 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
585 ok(hmerge != NULL, "merge himl1 with himl2 failed\n");
586 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2");
587 if (hmerge) ImageList_Destroy(hmerge);
589 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 8, 16);
590 ok(hmerge != NULL, "merge himl1 with himl2 8,16 failed\n");
591 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2, 8,16");
592 if (hmerge) ImageList_Destroy(hmerge);
594 ImageList_Destroy(himl1);
595 ImageList_Destroy(himl2);
600 /*********************** imagelist storage test ***************************/
607 char *iml_data; /* written imagelist data */
611 static HRESULT STDMETHODCALLTYPE Test_Stream_QueryInterface(
620 static ULONG STDMETHODCALLTYPE Test_Stream_AddRef(
627 static ULONG STDMETHODCALLTYPE Test_Stream_Release(
634 static HRESULT STDMETHODCALLTYPE Test_Stream_Read(
644 static BOOL allocate_storage(struct my_IStream *my_is, ULONG add)
646 my_is->iml_data_size += add;
648 if (!my_is->iml_data)
649 my_is->iml_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data_size);
651 my_is->iml_data = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data, my_is->iml_data_size);
653 return my_is->iml_data ? TRUE : FALSE;
656 static HRESULT STDMETHODCALLTYPE Test_Stream_Write(
662 struct my_IStream *my_is = (struct my_IStream *)This;
663 ULONG current_iml_data_size = my_is->iml_data_size;
665 if (!allocate_storage(my_is, cb)) return E_FAIL;
667 memcpy(my_is->iml_data + current_iml_data_size, pv, cb);
668 if (pcbWritten) *pcbWritten = cb;
673 static HRESULT STDMETHODCALLTYPE Test_Stream_Seek(
675 LARGE_INTEGER dlibMove,
677 ULARGE_INTEGER* plibNewPosition)
683 static HRESULT STDMETHODCALLTYPE Test_Stream_SetSize(
685 ULARGE_INTEGER libNewSize)
691 static HRESULT STDMETHODCALLTYPE Test_Stream_CopyTo(
695 ULARGE_INTEGER* pcbRead,
696 ULARGE_INTEGER* pcbWritten)
702 static HRESULT STDMETHODCALLTYPE Test_Stream_Commit(
704 DWORD grfCommitFlags)
710 static HRESULT STDMETHODCALLTYPE Test_Stream_Revert(
717 static HRESULT STDMETHODCALLTYPE Test_Stream_LockRegion(
719 ULARGE_INTEGER libOffset,
727 static HRESULT STDMETHODCALLTYPE Test_Stream_UnlockRegion(
729 ULARGE_INTEGER libOffset,
737 static HRESULT STDMETHODCALLTYPE Test_Stream_Stat(
746 static HRESULT STDMETHODCALLTYPE Test_Stream_Clone(
754 static const IStreamVtbl Test_Stream_Vtbl =
756 Test_Stream_QueryInterface,
766 Test_Stream_LockRegion,
767 Test_Stream_UnlockRegion,
772 static struct my_IStream Test_Stream = { { &Test_Stream_Vtbl }, 0, 0 };
774 static INT DIB_GetWidthBytes( int width, int bpp )
780 case 1: words = (width + 31) / 32; break;
781 case 4: words = (width + 7) / 8; break;
782 case 8: words = (width + 3) / 4; break;
784 case 16: words = (width + 1) / 2; break;
785 case 24: words = (width * 3 + 3)/4; break;
786 case 32: words = width; break;
790 trace("Unknown depth %d, please report.\n", bpp );
797 static void check_bitmap_data(const char *bm_data, ULONG bm_data_size,
798 INT width, INT height, INT bpp,
801 const BITMAPFILEHEADER *bmfh = (const BITMAPFILEHEADER *)bm_data;
802 const BITMAPINFOHEADER *bmih = (const BITMAPINFOHEADER *)(bm_data + sizeof(*bmfh));
803 ULONG hdr_size, image_size;
805 hdr_size = sizeof(*bmfh) + sizeof(*bmih);
806 if (bmih->biBitCount <= 8) hdr_size += (1 << bpp) * sizeof(RGBQUAD);
808 ok(bmfh->bfType == (('M' << 8) | 'B'), "wrong bfType 0x%02x\n", bmfh->bfType);
809 ok(bmfh->bfSize == hdr_size, "wrong bfSize 0x%02x\n", bmfh->bfSize);
810 ok(bmfh->bfReserved1 == 0, "wrong bfReserved1 0x%02x\n", bmfh->bfReserved1);
811 ok(bmfh->bfReserved2 == 0, "wrong bfReserved2 0x%02x\n", bmfh->bfReserved2);
812 ok(bmfh->bfOffBits == hdr_size, "wrong bfOffBits 0x%02x\n", bmfh->bfOffBits);
814 ok(bmih->biSize == sizeof(*bmih), "wrong biSize %d\n", bmih->biSize);
815 ok(bmih->biWidth == width, "wrong biWidth %d (expected %d)\n", bmih->biWidth, width);
816 ok(bmih->biHeight == height, "wrong biHeight %d (expected %d)\n", bmih->biHeight, height);
817 ok(bmih->biPlanes == 1, "wrong biPlanes %d\n", bmih->biPlanes);
818 ok(bmih->biBitCount == bpp, "wrong biBitCount %d\n", bmih->biBitCount);
820 image_size = DIB_GetWidthBytes(bmih->biWidth, bmih->biBitCount) * bmih->biHeight;
821 ok(bmih->biSizeImage == image_size, "wrong biSizeImage %u\n", bmih->biSizeImage);
826 sprintf(fname, "bmp_%s.bmp", comment);
827 f = fopen(fname, "wb");
828 fwrite(bm_data, 1, bm_data_size, f);
834 static void check_ilhead_data(const char *ilh_data, INT cx, INT cy, INT cur, INT max)
836 ILHEAD *ilh = (ILHEAD *)ilh_data;
838 ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
839 ok(ilh->usVersion == 0x101, "wrong usVersion %x (expected 0x101)\n", ilh->usVersion);
840 ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
841 ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
842 ok(ilh->cGrow == 4, "wrong cGrow %d (expected 4)\n", ilh->cGrow);
843 ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
844 ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
845 ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
846 ok(ilh->flags == ILC_COLOR24, "wrong flags %04x\n", ilh->flags);
847 ok(ilh->ovls[0] == -1 ||
848 ilh->ovls[0] == 0, /* win95 */
849 "wrong ovls[0] %04x\n", ilh->ovls[0]);
850 ok(ilh->ovls[1] == -1 ||
851 ilh->ovls[1] == 0, /* win95 */
852 "wrong ovls[1] %04x\n", ilh->ovls[1]);
853 ok(ilh->ovls[2] == -1 ||
854 ilh->ovls[2] == 0, /* win95 */
855 "wrong ovls[2] %04x\n", ilh->ovls[2]);
856 ok(ilh->ovls[3] == -1 ||
857 ilh->ovls[3] == 0, /* win95 */
858 "wrong ovls[3] %04x\n", ilh->ovls[3]);
861 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
864 char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
865 BITMAPINFO *bmi = (BITMAPINFO *)bmibuf;
866 HBITMAP hbmp, hbmp_old;
868 RECT rc = { 0, 0, cx, cy };
870 hdc = CreateCompatibleDC(0);
872 memset(bmi, 0, sizeof(*bmi));
873 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
874 bmi->bmiHeader.biHeight = cx;
875 bmi->bmiHeader.biWidth = cy;
876 bmi->bmiHeader.biBitCount = 24;
877 bmi->bmiHeader.biPlanes = 1;
878 bmi->bmiHeader.biCompression = BI_RGB;
879 hbmp = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
881 hbmp_old = SelectObject(hdc, hbmp);
883 hbrush = CreateSolidBrush(color);
884 FillRect(hdc, &rc, hbrush);
885 DeleteObject(hbrush);
887 DrawText(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
889 SelectObject(hdc, hbmp_old);
895 static void image_list_init(HIMAGELIST himl)
901 #define add_bitmap(grey) \
902 sprintf(comment, "%d", n++); \
903 hbm = create_bitmap(BMP_CX, BMP_CX, RGB((grey),(grey),(grey)), comment); \
904 ImageList_Add(himl, hbm, NULL);
906 add_bitmap(255); add_bitmap(170); add_bitmap(85); add_bitmap(0);
907 add_bitmap(0); add_bitmap(85); add_bitmap(170); add_bitmap(255);
908 add_bitmap(255); add_bitmap(170); add_bitmap(85); add_bitmap(0);
909 add_bitmap(0); add_bitmap(85); add_bitmap(170); add_bitmap(255);
910 add_bitmap(255); add_bitmap(170); add_bitmap(85); add_bitmap(0);
911 add_bitmap(0); add_bitmap(85); add_bitmap(170); add_bitmap(255);
915 #define iml_clear_stream_data() \
916 HeapFree(GetProcessHeap(), 0, Test_Stream.iml_data); \
917 Test_Stream.iml_data = NULL; \
918 Test_Stream.iml_data_size = 0;
920 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max,
921 INT width, INT height, INT bpp, const char *comment)
925 ret = ImageList_GetImageCount(himl);
926 ok(ret == cur, "expected cur %d got %d\n", cur, ret);
928 ret = ImageList_GetIconSize(himl, &cxx, &cyy);
929 ok(ret, "ImageList_GetIconSize failed\n");
930 ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx);
931 ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy);
933 iml_clear_stream_data();
934 ret = ImageList_Write(himl, &Test_Stream.is);
935 ok(ret, "ImageList_Write failed\n");
937 ok(Test_Stream.iml_data != 0, "ImageList_Write didn't write any data\n");
938 ok(Test_Stream.iml_data_size > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n");
940 check_ilhead_data(Test_Stream.iml_data, cx, cy, cur, max);
941 check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD),
942 Test_Stream.iml_data_size - sizeof(ILHEAD),
943 width, height, bpp, comment);
946 static void test_imagelist_storage(void)
951 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
952 ok(himl != 0, "ImageList_Create failed\n");
954 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, BMP_CX * 4, BMP_CX * 1, 24, "empty");
956 image_list_init(himl);
957 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, BMP_CX * 4, BMP_CX * 7, 24, "orig");
959 ret = ImageList_Remove(himl, 4);
960 ok(ret, "ImageList_Remove failed\n");
961 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, BMP_CX * 4, BMP_CX * 7, 24, "1");
963 ret = ImageList_Remove(himl, 5);
964 ok(ret, "ImageList_Remove failed\n");
965 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, BMP_CX * 4, BMP_CX * 7, 24, "2");
967 ret = ImageList_Remove(himl, 6);
968 ok(ret, "ImageList_Remove failed\n");
969 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, BMP_CX * 4, BMP_CX * 7, 24, "3");
971 ret = ImageList_Remove(himl, 7);
972 ok(ret, "ImageList_Remove failed\n");
973 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, BMP_CX * 4, BMP_CX * 7, 24, "4");
975 ret = ImageList_Remove(himl, -2);
976 ok(!ret, "ImageList_Remove(-2) should fail\n");
977 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, BMP_CX * 4, BMP_CX * 7, 24, "5");
979 ret = ImageList_Remove(himl, 20);
980 ok(!ret, "ImageList_Remove(20) should fail\n");
981 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, BMP_CX * 4, BMP_CX * 7, 24, "6");
983 ret = ImageList_Remove(himl, -1);
984 ok(ret, "ImageList_Remove(-1) failed\n");
985 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, BMP_CX * 4, BMP_CX * 1, 24, "7");
987 ret = ImageList_Destroy(himl);
988 ok(ret, "ImageList_Destroy failed\n");
990 iml_clear_stream_data();
993 static void test_shell_imagelist(void)
995 BOOL (WINAPI *pSHGetImageList)(INT, REFIID, void**);
996 IImageList *iml = NULL;
1003 /* Try to load function from shell32 */
1004 hShell32 = LoadLibrary("shell32.dll");
1005 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1007 if (!pSHGetImageList)
1009 win_skip("SHGetImageList not available, skipping test\n");
1013 /* Get system image list */
1014 hr = (pSHGetImageList)(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1016 ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1021 IImageList_GetImageCount(iml, &out);
1022 ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1024 /* Fetch the small icon size */
1025 cx = GetSystemMetrics(SM_CXSMICON);
1026 cy = GetSystemMetrics(SM_CYSMICON);
1028 /* Check icon size matches */
1029 IImageList_GetImageRect(iml, 0, &rect);
1030 ok(((rect.right == cx) && (rect.bottom == cy)),
1031 "IImageList_GetImageRect returned r:%d,b:%d\n",
1032 rect.right, rect.bottom);
1034 IImageList_Release(iml);
1035 FreeLibrary(hShell32);
1038 static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
1041 UINT32 *buffer = NULL;
1042 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
1045 hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1046 ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1048 if(!hBitmap || !buffer)
1050 DeleteObject(hBitmap);
1060 static BOOL colour_match(UINT32 x, UINT32 y)
1062 const INT32 tolerance = 8;
1064 const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1065 const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1066 const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1068 return (dr <= tolerance && dg <= tolerance && db <= tolerance);
1071 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1072 UINT32 expected, int line)
1074 bits[0] = 0x00FFFFFF;
1075 pImageList_DrawIndirect(ildp);
1076 ok(colour_match(bits[0], expected),
1077 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1078 bits[0] & 0x00FFFFFF, expected, line);
1082 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1083 UINT fStyle, UINT32 expected, int line)
1085 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1086 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1087 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1090 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1091 DWORD dwRop, UINT32 expected, int line)
1093 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1094 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1095 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1098 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1099 UINT fState, DWORD Frame, UINT32 expected, int line)
1101 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1102 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1103 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1106 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1107 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1108 UINT32 broken_expected, int line)
1110 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1111 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1112 bits[0] = 0x00FFFFFF;
1113 pImageList_DrawIndirect(&ildp);
1114 ok(colour_match(bits[0], expected) ||
1115 broken(colour_match(bits[0], broken_expected)),
1116 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1117 bits[0] & 0x00FFFFFF, expected, line);
1120 static void test_ImageList_DrawIndirect(void)
1122 HIMAGELIST himl = NULL;
1125 HBITMAP hbmOld = NULL, hbmDst = NULL;
1126 HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1127 HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
1128 int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1130 UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1132 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1135 hdcDst = CreateCompatibleDC(0);
1136 ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1140 hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1141 ok(hbmMask != 0, "CreateBitmap failed\n");
1142 if(!hbmMask) goto cleanup;
1144 hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1145 ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1146 if(!hbmInverseMask) goto cleanup;
1148 himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1149 ok(himl != 0, "ImageList_Create failed\n");
1150 if(!himl) goto cleanup;
1152 /* Add a no-alpha image */
1153 hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
1154 if(!hbmImage) goto cleanup;
1156 iImage = pImageList_Add(himl, hbmImage, hbmMask);
1157 ok(iImage != -1, "ImageList_Add failed\n");
1158 if(iImage == -1) goto cleanup;
1160 /* Add an alpha image */
1161 hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
1162 if(!hbmAlphaImage) goto cleanup;
1164 iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1165 ok(iAlphaImage != -1, "ImageList_Add failed\n");
1166 if(iAlphaImage == -1) goto cleanup;
1168 /* Add a transparent alpha image */
1169 hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
1170 if(!hbmTransparentImage) goto cleanup;
1172 iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1173 ok(iTransparentImage != -1, "ImageList_Add failed\n");
1174 if(iTransparentImage == -1) goto cleanup;
1177 bitmapInfo.bmiHeader.biBitCount = 32;
1178 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1179 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1180 if (!hbmDst || !bits)
1182 hbmOld = SelectObject(hdcDst, hbmDst);
1184 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1185 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1186 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
1187 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, 0x00B4BDC4, __LINE__);
1188 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1189 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1190 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1194 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
1195 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
1196 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x009DA8B1, __LINE__);
1197 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, 0x008C99A3, __LINE__);
1199 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
1200 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
1201 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
1204 todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
1206 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1207 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
1209 /* ILD_ROP is ignored when the image has an alpha channel */
1210 todo_wine check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
1211 todo_wine check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
1213 todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
1214 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
1216 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
1217 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
1219 todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
1220 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
1221 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
1226 SelectObject(hdcDst, hbmOld);
1228 DeleteObject(hbmDst);
1234 DeleteObject(hbmMask);
1236 DeleteObject(hbmInverseMask);
1239 DeleteObject(hbmImage);
1241 DeleteObject(hbmAlphaImage);
1242 if(hbmTransparentImage)
1243 DeleteObject(hbmTransparentImage);
1247 ret = ImageList_Destroy(himl);
1248 ok(ret, "ImageList_Destroy failed\n");
1252 static void test_iimagelist(void)
1259 if (!pHIMAGELIST_QueryInterface)
1261 win_skip("XP imagelist functions not available\n");
1265 /* test reference counting on destruction */
1266 imgl = (IImageList*)createImageList(32, 32);
1267 ret = IUnknown_AddRef(imgl);
1268 ok(ret == 2, "Expected 2, got %d\n", ret);
1269 ret = ImageList_Destroy((HIMAGELIST)imgl);
1270 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1271 ret = ImageList_Destroy((HIMAGELIST)imgl);
1272 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1273 ret = ImageList_Destroy((HIMAGELIST)imgl);
1274 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1276 imgl = (IImageList*)createImageList(32, 32);
1277 ret = IUnknown_AddRef(imgl);
1278 ok(ret == 2, "Expected 2, got %d\n", ret);
1279 ret = ImageList_Destroy((HIMAGELIST)imgl);
1280 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1281 ret = IImageList_Release(imgl);
1282 ok(ret == 0, "Expected 0, got %d\n", ret);
1283 ret = ImageList_Destroy((HIMAGELIST)imgl);
1284 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1286 if (!pImageList_CoCreateInstance)
1288 win_skip("Vista imagelist functions not available\n");
1292 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1293 ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
1296 IImageList_Release(imgl);
1298 himl = createImageList(32, 32);
1303 hr = (pHIMAGELIST_QueryInterface)(himl, &IID_IImageList, (void **) &imgl);
1304 ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
1307 IImageList_Release(imgl);
1309 ImageList_Destroy(himl);
1312 static void testHotspot_v6(void)
1323 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
1324 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
1331 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
1332 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
1333 IImageList *imgl1, *imgl2;
1336 /* cast to IImageList */
1337 imgl1 = (IImageList *) himl1;
1338 imgl2 = (IImageList *) himl2;
1340 for (i = 0; i < HOTSPOTS_MAX; i++) {
1341 for (j = 0; j < HOTSPOTS_MAX; j++) {
1342 int dx1 = hotspots[i].dx;
1343 int dy1 = hotspots[i].dy;
1344 int dx2 = hotspots[j].dx;
1345 int dy2 = hotspots[j].dy;
1346 int correctx, correcty, newx, newy;
1348 IImageList *imglNew;
1351 hr = IImageList_BeginDrag(imgl1, 0, dx1, dy1);
1352 ok(SUCCEEDED(hr), "BeginDrag failed for { %d, %d }\n", dx1, dy1);
1353 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
1355 /* check merging the dragged image with a second image */
1356 hr = IImageList_SetDragCursorImage(imgl2, (IUnknown *) imgl2, 0, dx2, dy2);
1357 ok(SUCCEEDED(hr), "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
1358 dx1, dy1, dx2, dy2);
1359 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
1361 /* check new hotspot, it should be the same like the old one */
1362 hr = IImageList_GetDragImage(imgl2, NULL, &ppt, &IID_IImageList, (PVOID *) &imglNew);
1363 ok(SUCCEEDED(hr), "GetDragImage failed\n");
1364 ok(ppt.x == dx1 && ppt.y == dy1,
1365 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
1366 dx1, dy1, ppt.x, ppt.y);
1367 /* check size of new dragged image */
1368 IImageList_GetIconSize(imglNew, &newx, &newy);
1369 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
1370 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
1371 ok(newx == correctx && newy == correcty,
1372 "Expected drag image size [%d,%d] got [%d,%d]\n",
1373 correctx, correcty, newx, newy);
1374 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
1375 IImageList_EndDrag(imgl2);
1383 IImageList_Release(imgl2);
1384 IImageList_Release(imgl1);
1387 static void DoTest1_v6(void)
1399 /* create an imagelist to play with */
1400 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1401 ok(himl != 0,"failed to create imagelist\n");
1403 imgl = (IImageList *) himl;
1405 /* load the icons to add to the image list */
1406 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1407 ok(hicon1 != 0, "no hicon1\n");
1408 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1409 ok(hicon2 != 0, "no hicon2\n");
1410 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1411 ok(hicon3 != 0, "no hicon3\n");
1413 /* remove when nothing exists */
1414 hr = IImageList_Remove(imgl, 0);
1415 ok(!(SUCCEEDED(hr)), "removed nonexistent icon\n");
1417 /* removing everything from an empty imagelist should succeed */
1418 hr = IImageList_Remove(imgl, -1);
1419 ok(SUCCEEDED(hr), "removed nonexistent icon\n");
1422 ok(SUCCEEDED(IImageList_ReplaceIcon(imgl, -1, hicon1, &ret)) && (ret == 0),"failed to add icon1\n");
1423 ok(SUCCEEDED(IImageList_ReplaceIcon(imgl, -1, hicon2, &ret)) && (ret == 1),"failed to add icon2\n");
1424 ok(SUCCEEDED(IImageList_ReplaceIcon(imgl, -1, hicon3, &ret)) && (ret == 2),"failed to add icon3\n");
1426 /* remove an index out of range */
1427 ok(FAILED(IImageList_Remove(imgl, 4711)),"removed nonexistent icon\n");
1430 ok(SUCCEEDED(IImageList_Remove(imgl,0)),"can't remove 0\n");
1431 ok(SUCCEEDED(IImageList_Remove(imgl,0)),"can't remove 0\n");
1432 ok(SUCCEEDED(IImageList_Remove(imgl,0)),"can't remove 0\n");
1434 /* remove one extra */
1435 ok(FAILED(IImageList_Remove(imgl, 0)),"removed nonexistent icon\n");
1437 /* check SetImageCount/GetImageCount */
1438 ok(SUCCEEDED(IImageList_SetImageCount(imgl, 3)), "couldn't increase image count\n");
1439 ok(SUCCEEDED(IImageList_GetImageCount(imgl, &ret)) && (ret == 3), "invalid image count after increase\n");
1440 ok(SUCCEEDED(IImageList_SetImageCount(imgl, 1)), "couldn't decrease image count\n");
1441 ok(SUCCEEDED(IImageList_GetImageCount(imgl, &ret)) && (ret == 1), "invalid image count after decrease to 1\n");
1442 ok(SUCCEEDED(IImageList_SetImageCount(imgl, 0)), "couldn't decrease image count\n");
1443 ok(SUCCEEDED(IImageList_GetImageCount(imgl, &ret)) && (ret == 0), "invalid image count after decrease to 0\n");
1446 ok(SUCCEEDED(IImageList_Release(imgl)),"release imagelist failed\n");
1448 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1449 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1450 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1453 static void DoTest3_v6(void)
1462 IMAGELISTDRAWPARAMS imldp;
1467 hwndfortest = create_a_window();
1468 hdc = GetDC(hwndfortest);
1469 ok(hdc!=NULL, "couldn't get DC\n");
1471 /* create an imagelist to play with */
1472 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1473 ok(himl!=0,"failed to create imagelist\n");
1475 imgl = (IImageList *) himl;
1477 /* load the icons to add to the image list */
1478 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1479 ok(hbm1 != 0, "no bitmap 1\n");
1480 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1481 ok(hbm2 != 0, "no bitmap 2\n");
1482 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1483 ok(hbm3 != 0, "no bitmap 3\n");
1486 ok(SUCCEEDED(IImageList_Add(imgl, hbm1, 0, &ret)) && (ret == 0), "failed to add bitmap 1\n");
1487 ok(SUCCEEDED(IImageList_Add(imgl, hbm2, 0, &ret)) && (ret == 1), "failed to add bitmap 2\n");
1489 ok(SUCCEEDED(IImageList_SetImageCount(imgl, 3)), "Setimage count failed\n");
1490 ok(SUCCEEDED(IImageList_Replace(imgl, 2, hbm3, 0)), "failed to replace bitmap 3\n");
1492 memset(&imldp, 0, sizeof (imldp));
1493 ok(FAILED(IImageList_Draw(imgl, &imldp)), "zero data succeeded!\n");
1495 imldp.cbSize = sizeof (imldp);
1499 if (FAILED(IImageList_Draw(imgl, &imldp)))
1501 /* Earlier versions of native comctl32 use a smaller structure */
1502 imldp.cbSize -= 3 * sizeof(DWORD);
1503 ok(SUCCEEDED(IImageList_Draw(imgl, &imldp)), "should succeed\n");
1506 REDRAW(hwndfortest);
1509 imldp.fStyle = SRCCOPY;
1510 imldp.rgbBk = CLR_DEFAULT;
1511 imldp.rgbFg = CLR_DEFAULT;
1514 ok(SUCCEEDED(IImageList_Draw(imgl, &imldp)), "should succeed\n");
1516 ok(SUCCEEDED(IImageList_Draw(imgl, &imldp)), "should succeed\n");
1518 ok(SUCCEEDED(IImageList_Draw(imgl, &imldp)), "should succeed\n");
1520 ok(FAILED(IImageList_Draw(imgl, &imldp)), "should fail\n");
1523 ok(SUCCEEDED(IImageList_Remove(imgl, 0)), "removing 1st bitmap\n");
1524 ok(SUCCEEDED(IImageList_Remove(imgl, 0)), "removing 2nd bitmap\n");
1525 ok(SUCCEEDED(IImageList_Remove(imgl, 0)), "removing 3rd bitmap\n");
1528 ok(SUCCEEDED(IImageList_Release(imgl)), "release imagelist failed\n");
1530 /* bitmaps should not be deleted by the imagelist */
1531 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1532 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1533 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1535 ReleaseDC(hwndfortest, hdc);
1536 DestroyWindow(hwndfortest);
1539 static void testMerge_v6(void)
1541 HIMAGELIST himl1, himl2;
1542 IImageList *imgl1, *imgl2, *merge;
1544 HWND hwnd = create_a_window();
1548 himl1 = ImageList_Create(32,32,0,0,3);
1549 ok(himl1 != NULL,"failed to create himl1\n");
1551 himl2 = ImageList_Create(32,32,0,0,3);
1552 ok(himl2 != NULL,"failed to create himl2\n");
1554 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1555 ok(hicon1 != NULL, "failed to create hicon1\n");
1557 if (!himl1 || !himl2 || !hicon1)
1560 /* cast to IImageList */
1561 imgl1 = (IImageList *) himl1;
1562 imgl2 = (IImageList *) himl2;
1564 ok(SUCCEEDED(IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret)) && (ret == 0),"add icon1 to himl2 failed\n");
1566 /* If himl1 has no images, merge still succeeds */
1567 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1568 ok(SUCCEEDED(hr), "merge himl1,-1 failed\n");
1569 if (SUCCEEDED(hr)) IImageList_Release(merge);
1571 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1572 ok(SUCCEEDED(hr), "merge himl1,0 failed\n");
1573 if (SUCCEEDED(hr)) IImageList_Release(merge);
1575 /* Same happens if himl2 is empty */
1576 IImageList_Release(imgl2);
1577 himl2 = ImageList_Create(32,32,0,0,3);
1578 ok(himl2 != NULL,"failed to recreate himl2\n");
1580 imgl2 = (IImageList *) himl2;
1582 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
1583 ok(SUCCEEDED(hr), "merge himl2,-1 failed\n");
1584 if (SUCCEEDED(hr)) IImageList_Release(merge);
1586 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1587 ok(SUCCEEDED(hr), "merge himl2,0 failed\n");
1588 if (SUCCEEDED(hr)) IImageList_Release(merge);
1590 /* Now try merging an image with itself */
1591 ok(SUCCEEDED(IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret)) && (ret == 0),"re-add icon1 to himl2 failed\n");
1593 hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1594 ok(SUCCEEDED(hr), "merge himl2 with itself failed\n");
1595 if (SUCCEEDED(hr)) IImageList_Release(merge);
1597 /* Try merging 2 different image lists */
1598 ok(SUCCEEDED(IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret)) && (ret == 0),"add icon1 to himl1 failed\n");
1600 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1601 ok(SUCCEEDED(hr), "merge himl1 with himl2 failed\n");
1602 if (SUCCEEDED(hr)) IImageList_Release(merge);
1604 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
1605 ok(SUCCEEDED(hr), "merge himl1 with himl2 8,16 failed\n");
1606 if (SUCCEEDED(hr)) IImageList_Release(merge);
1608 IImageList_Release(imgl1);
1609 IImageList_Release(imgl2);
1611 DestroyIcon(hicon1);
1612 DestroyWindow(hwnd);
1615 START_TEST(imagelist)
1617 ULONG_PTR ctx_cookie;
1620 HMODULE hComCtl32 = GetModuleHandle("comctl32.dll");
1621 pImageList_Create = NULL; /* These are not needed for non-v6.0 tests*/
1622 pImageList_Add = NULL;
1623 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1624 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1626 hinst = GetModuleHandleA(NULL);
1628 InitCommonControls();
1635 test_imagelist_storage();
1637 FreeLibrary(hComCtl32);
1639 /* Now perform v6 tests */
1641 if (!load_v6_module(&ctx_cookie, &hCtx))
1644 /* Reload comctl32 */
1645 hComCtl32 = LoadLibraryA("comctl32.dll");
1646 pImageList_Create = (void*)GetProcAddress(hComCtl32, "ImageList_Create");
1647 pImageList_Add = (void*)GetProcAddress(hComCtl32, "ImageList_Add");
1648 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1649 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1650 pImageList_CoCreateInstance = (void*)GetProcAddress(hComCtl32, "ImageList_CoCreateInstance");
1651 pHIMAGELIST_QueryInterface = (void*)GetProcAddress(hComCtl32, "HIMAGELIST_QueryInterface");
1653 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1656 test_ImageList_DrawIndirect();
1657 test_shell_imagelist();
1667 unload_v6_module(ctx_cookie, hCtx);