TESTING -- override pthreads to fix gstreamer v5
[wine/multimedia.git] / dlls / comctl32 / tests / imagelist.c
blob7e029e09010de12c6fd33c8872e0be87960541b9
1 /*
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
24 #define COBJMACROS
25 #define CONST_VTABLE
27 #include <stdarg.h>
28 #include <stdio.h>
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wingdi.h"
33 #include "winuser.h"
34 #include "objbase.h"
35 #include "commctrl.h" /* must be included after objbase.h to get ImageList_Write */
36 #include "initguid.h"
37 #include "commoncontrols.h"
38 #include "shellapi.h"
40 #include "wine/test.h"
41 #include "v6util.h"
43 #define IMAGELIST_MAGIC (('L' << 8) | 'I')
45 #include "pshpack2.h"
46 /* Header used by ImageList_Read() and ImageList_Write() */
47 typedef struct _ILHEAD
49 USHORT usMagic;
50 USHORT usVersion;
51 WORD cCurImage;
52 WORD cMaxImage;
53 WORD cGrow;
54 WORD cx;
55 WORD cy;
56 COLORREF bkcolor;
57 WORD flags;
58 SHORT ovls[4];
59 } ILHEAD;
60 #include "poppack.h"
62 static HIMAGELIST (WINAPI *pImageList_Create)(int, int, UINT, int, int);
63 static int (WINAPI *pImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP);
64 static BOOL (WINAPI *pImageList_DrawIndirect)(IMAGELISTDRAWPARAMS*);
65 static BOOL (WINAPI *pImageList_SetImageCount)(HIMAGELIST,UINT);
66 static HRESULT (WINAPI *pImageList_CoCreateInstance)(REFCLSID,const IUnknown *,
67 REFIID,void **);
68 static HRESULT (WINAPI *pHIMAGELIST_QueryInterface)(HIMAGELIST,REFIID,void **);
70 static HINSTANCE hinst;
72 /* only used in interactive mode */
73 static void force_redraw(HWND hwnd)
75 if (!winetest_interactive)
76 return;
78 RedrawWindow(hwnd, NULL, 0, RDW_UPDATENOW);
79 Sleep(1000);
82 /* These macros build cursor/bitmap data in 4x4 pixel blocks */
83 #define B(x,y) ((x?0xf0:0)|(y?0xf:0))
84 #define ROW1(a,b,c,d,e,f,g,h) B(a,b),B(c,d),B(e,f),B(g,h)
85 #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), \
86 ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h)
87 #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)
88 #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), \
89 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), \
90 ROW2(a,b,c,d,e,f,g,h,i,j,k,l)
92 static const BYTE empty_bits[48*48/8];
94 static const BYTE icon_bits[32*32/8] =
96 ROW32(0,0,0,0,0,0,0,0),
97 ROW32(0,0,1,1,1,1,0,0),
98 ROW32(0,1,1,1,1,1,1,0),
99 ROW32(0,1,1,0,0,1,1,0),
100 ROW32(0,1,1,0,0,1,1,0),
101 ROW32(0,1,1,1,1,1,1,0),
102 ROW32(0,0,1,1,1,1,0,0),
103 ROW32(0,0,0,0,0,0,0,0)
106 static const BYTE bitmap_bits[48*48/8] =
108 ROW48(0,0,0,0,0,0,0,0,0,0,0,0),
109 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
110 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
111 ROW48(0,1,0,0,0,0,0,0,1,0,1,0),
112 ROW48(0,1,0,0,0,0,0,1,0,0,1,0),
113 ROW48(0,1,0,0,0,0,1,0,0,0,1,0),
114 ROW48(0,1,0,0,0,1,0,0,0,0,1,0),
115 ROW48(0,1,0,0,1,0,0,0,0,0,1,0),
116 ROW48(0,1,0,1,0,0,0,0,0,0,1,0),
117 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
118 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
119 ROW48(0,0,0,0,0,0,0,0,0,0,0,0)
122 static HIMAGELIST createImageList(int cx, int cy)
124 /* Create an ImageList and put an image into it */
125 HIMAGELIST himl = ImageList_Create(cx, cy, ILC_COLOR, 1, 1);
126 HBITMAP hbm = CreateBitmap(48, 48, 1, 1, bitmap_bits);
127 ImageList_Add(himl, hbm, NULL);
128 DeleteObject(hbm);
129 return himl;
132 static HWND create_a_window(void)
134 char className[] = "bmwnd";
135 char winName[] = "Test Bitmap";
136 HWND hWnd;
137 static BOOL registered = FALSE;
139 if (!registered)
141 WNDCLASSA cls;
143 cls.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
144 cls.lpfnWndProc = DefWindowProcA;
145 cls.cbClsExtra = 0;
146 cls.cbWndExtra = 0;
147 cls.hInstance = 0;
148 cls.hIcon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
149 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
150 cls.hbrBackground = GetStockObject (WHITE_BRUSH);
151 cls.lpszMenuName = 0;
152 cls.lpszClassName = className;
154 RegisterClassA (&cls);
155 registered = TRUE;
158 /* Setup window */
159 hWnd = CreateWindowA (className, winName,
160 WS_OVERLAPPEDWINDOW ,
161 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
162 0, hinst, 0);
164 if (winetest_interactive)
166 ShowWindow (hWnd, SW_SHOW);
167 force_redraw (hWnd);
170 return hWnd;
173 static HDC show_image(HWND hwnd, HIMAGELIST himl, int idx, int size,
174 LPCSTR loc, BOOL clear)
176 HDC hdc;
178 if (!winetest_interactive || !himl) return NULL;
180 SetWindowTextA(hwnd, loc);
181 hdc = GetDC(hwnd);
182 ImageList_Draw(himl, idx, hdc, 0, 0, ILD_TRANSPARENT);
184 force_redraw(hwnd);
186 if (clear)
188 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
189 ReleaseDC(hwnd, hdc);
190 hdc = NULL;
193 return hdc;
196 /* Useful for checking differences */
197 static void dump_bits(const BYTE *p, const BYTE *q, int size)
199 int i, j;
201 size /= 8;
203 for (i = 0; i < size * 2; i++)
205 printf("|");
206 for (j = 0; j < size; j++)
207 printf("%c%c", p[j] & 0xf0 ? 'X' : ' ', p[j] & 0xf ? 'X' : ' ');
208 printf(" -- ");
209 for (j = 0; j < size; j++)
210 printf("%c%c", q[j] & 0xf0 ? 'X' : ' ', q[j] & 0xf ? 'X' : ' ');
211 printf("|\n");
212 p += size * 4;
213 q += size * 4;
215 printf("\n");
218 static void check_bits(HWND hwnd, HIMAGELIST himl, int idx, int size,
219 const BYTE *checkbits, LPCSTR loc)
221 BYTE bits[100*100/8];
222 COLORREF c;
223 HDC hdc;
224 int x, y, i = -1;
226 if (!winetest_interactive || !himl) return;
228 memset(bits, 0, sizeof(bits));
229 hdc = show_image(hwnd, himl, idx, size, loc, FALSE);
231 c = GetPixel(hdc, 0, 0);
233 for (y = 0; y < size; y ++)
235 for (x = 0; x < size; x++)
237 if (!(x & 0x7)) i++;
238 if (GetPixel(hdc, x, y) != c) bits[i] |= (0x80 >> (x & 0x7));
242 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
243 ReleaseDC(hwnd, hdc);
245 ok (memcmp(bits, checkbits, (size * size)/8) == 0,
246 "%s: bits different\n", loc);
247 if (memcmp(bits, checkbits, (size * size)/8))
248 dump_bits(bits, checkbits, size);
251 static void test_begindrag(void)
253 HIMAGELIST himl = createImageList(7,13);
254 HIMAGELIST drag;
255 BOOL ret;
256 int count;
257 POINT hotspot;
259 count = ImageList_GetImageCount(himl);
260 ok(count > 2, "Tests need an ImageList with more than 2 images\n");
262 /* Two BeginDrag() without EndDrag() in between */
263 ret = ImageList_BeginDrag(himl, 1, 0, 0);
264 drag = ImageList_GetDragImage(NULL, NULL);
265 ok(ret && drag, "ImageList_BeginDrag() failed\n");
266 ret = ImageList_BeginDrag(himl, 0, 3, 5);
267 ok(!ret, "ImageList_BeginDrag() returned TRUE\n");
268 drag = ImageList_GetDragImage(NULL, &hotspot);
269 ok(!!drag, "No active ImageList drag left\n");
270 ok(hotspot.x == 0 && hotspot.y == 0, "New ImageList drag was created\n");
271 ImageList_EndDrag();
272 drag = ImageList_GetDragImage(NULL, NULL);
273 ok(!drag, "ImageList drag was not destroyed\n");
275 /* Invalid image index */
276 ImageList_BeginDrag(himl, 0, 0, 0);
277 ret = ImageList_BeginDrag(himl, count, 3, 5);
278 ok(!ret, "ImageList_BeginDrag() returned TRUE\n");
279 drag = ImageList_GetDragImage(NULL, &hotspot);
280 ok(drag && hotspot.x == 0 && hotspot.y == 0, "Active drag should not have been canceled\n");
281 ImageList_EndDrag();
282 drag = ImageList_GetDragImage(NULL, NULL);
283 ok(!drag, "ImageList drag was not destroyed\n");
284 /* Invalid negative image indexes succeed */
285 ret = ImageList_BeginDrag(himl, -17, 0, 0);
286 drag = ImageList_GetDragImage(NULL, NULL);
287 ok(ret && drag, "ImageList drag was created\n");
288 ImageList_EndDrag();
289 ret = ImageList_BeginDrag(himl, -1, 0, 0);
290 drag = ImageList_GetDragImage(NULL, NULL);
291 ok(ret && drag, "ImageList drag was created\n");
292 ImageList_EndDrag();
293 ImageList_Destroy(himl);
296 static void test_hotspot(void)
298 struct hotspot {
299 int dx;
300 int dy;
303 #define SIZEX1 47
304 #define SIZEY1 31
305 #define SIZEX2 11
306 #define SIZEY2 17
307 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
308 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
309 { 10, 7 },
310 { SIZEX1, SIZEY1 },
311 { -9, -8 },
312 { -7, 35 }
314 int i, j, ret;
315 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
316 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
317 HWND hwnd = create_a_window();
320 for (i = 0; i < HOTSPOTS_MAX; i++) {
321 for (j = 0; j < HOTSPOTS_MAX; j++) {
322 int dx1 = hotspots[i].dx;
323 int dy1 = hotspots[i].dy;
324 int dx2 = hotspots[j].dx;
325 int dy2 = hotspots[j].dy;
326 int correctx, correcty, newx, newy;
327 char loc[256];
328 HIMAGELIST himlNew;
329 POINT ppt;
331 ret = ImageList_BeginDrag(himl1, 0, dx1, dy1);
332 ok(ret != 0, "BeginDrag failed for { %d, %d }\n", dx1, dy1);
333 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
334 show_image(hwnd, himl1, 0, max(SIZEX1, SIZEY1), loc, TRUE);
336 /* check merging the dragged image with a second image */
337 ret = ImageList_SetDragCursorImage(himl2, 0, dx2, dy2);
338 ok(ret != 0, "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
339 dx1, dy1, dx2, dy2);
340 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
341 show_image(hwnd, himl2, 0, max(SIZEX2, SIZEY2), loc, TRUE);
343 /* check new hotspot, it should be the same like the old one */
344 himlNew = ImageList_GetDragImage(NULL, &ppt);
345 ok(ppt.x == dx1 && ppt.y == dy1,
346 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
347 dx1, dy1, ppt.x, ppt.y);
348 /* check size of new dragged image */
349 ImageList_GetIconSize(himlNew, &newx, &newy);
350 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
351 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
352 ok(newx == correctx && newy == correcty,
353 "Expected drag image size [%d,%d] got [%d,%d]\n",
354 correctx, correcty, newx, newy);
355 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
356 show_image(hwnd, himlNew, 0, max(correctx, correcty), loc, TRUE);
357 ImageList_EndDrag();
360 #undef SIZEX1
361 #undef SIZEY1
362 #undef SIZEX2
363 #undef SIZEY2
364 #undef HOTSPOTS_MAX
365 ImageList_Destroy(himl2);
366 ImageList_Destroy(himl1);
367 DestroyWindow(hwnd);
370 static void test_add_remove(void)
372 HIMAGELIST himl ;
374 HICON hicon1 ;
375 HICON hicon2 ;
376 HICON hicon3 ;
378 /* create an imagelist to play with */
379 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
380 ok(himl!=0,"failed to create imagelist\n");
382 /* load the icons to add to the image list */
383 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
384 ok(hicon1 != 0, "no hicon1\n");
385 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
386 ok(hicon2 != 0, "no hicon2\n");
387 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
388 ok(hicon3 != 0, "no hicon3\n");
390 /* remove when nothing exists */
391 ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
392 /* removing everything from an empty imagelist should succeed */
393 ok(ImageList_RemoveAll(himl),"removed nonexistent icon\n");
395 /* add three */
396 ok(0==ImageList_AddIcon(himl, hicon1),"failed to add icon1\n");
397 ok(1==ImageList_AddIcon(himl, hicon2),"failed to add icon2\n");
398 ok(2==ImageList_AddIcon(himl, hicon3),"failed to add icon3\n");
400 /* remove an index out of range */
401 ok(!ImageList_Remove(himl,4711),"removed nonexistent icon\n");
403 /* remove three */
404 ok(ImageList_Remove(himl,0),"can't remove 0\n");
405 ok(ImageList_Remove(himl,0),"can't remove 0\n");
406 ok(ImageList_Remove(himl,0),"can't remove 0\n");
408 /* remove one extra */
409 ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
411 /* destroy it */
412 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
414 ok(-1==ImageList_AddIcon((HIMAGELIST)0xdeadbeef, hicon1),"don't crash on bad handle\n");
416 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
417 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
418 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
421 static void test_imagecount(void)
423 HIMAGELIST himl;
425 ok(0==ImageList_GetImageCount((HIMAGELIST)0xdeadbeef),"don't crash on bad handle\n");
427 if (!pImageList_SetImageCount)
429 win_skip("ImageList_SetImageCount not available\n");
430 return;
433 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
434 ok(himl!=0,"failed to create imagelist\n");
436 ok(pImageList_SetImageCount(himl, 3), "couldn't increase image count\n");
437 ok(ImageList_GetImageCount(himl) == 3, "invalid image count after increase\n");
438 ok(pImageList_SetImageCount(himl, 1), "couldn't decrease image count\n");
439 ok(ImageList_GetImageCount(himl) == 1, "invalid image count after decrease to 1\n");
440 ok(pImageList_SetImageCount(himl, 0), "couldn't decrease image count\n");
441 ok(ImageList_GetImageCount(himl) == 0, "invalid image count after decrease to 0\n");
443 ok(ImageList_Destroy(himl), "destroy imagelist failed\n");
446 static void test_DrawIndirect(void)
448 HIMAGELIST himl;
450 HBITMAP hbm1;
451 HBITMAP hbm2;
452 HBITMAP hbm3;
454 IMAGELISTDRAWPARAMS imldp;
455 HDC hdc;
456 HWND hwndfortest;
458 if (!pImageList_DrawIndirect)
460 win_skip("ImageList_DrawIndirect not available, skipping test\n");
461 return;
464 hwndfortest = create_a_window();
465 hdc = GetDC(hwndfortest);
466 ok(hdc!=NULL, "couldn't get DC\n");
468 /* create an imagelist to play with */
469 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
470 ok(himl!=0,"failed to create imagelist\n");
472 /* load the icons to add to the image list */
473 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
474 ok(hbm1 != 0, "no bitmap 1\n");
475 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
476 ok(hbm2 != 0, "no bitmap 2\n");
477 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
478 ok(hbm3 != 0, "no bitmap 3\n");
480 /* add three */
481 ok(0==ImageList_Add(himl, hbm1, 0),"failed to add bitmap 1\n");
482 ok(1==ImageList_Add(himl, hbm2, 0),"failed to add bitmap 2\n");
484 if (pImageList_SetImageCount)
486 ok(pImageList_SetImageCount(himl,3),"Setimage count failed\n");
487 /*ok(2==ImageList_Add(himl, hbm3, NULL),"failed to add bitmap 3\n"); */
488 ok(ImageList_Replace(himl, 2, hbm3, 0),"failed to replace bitmap 3\n");
491 memset(&imldp, 0, sizeof (imldp));
492 ok(!pImageList_DrawIndirect(&imldp), "zero data succeeded!\n");
493 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
494 ok(!pImageList_DrawIndirect(&imldp), "zero hdc succeeded!\n");
495 imldp.hdcDst = hdc;
496 ok(!pImageList_DrawIndirect(&imldp),"zero himl succeeded!\n");
497 imldp.himl = (HIMAGELIST)0xdeadbeef;
498 ok(!pImageList_DrawIndirect(&imldp),"bad himl succeeded!\n");
499 imldp.himl = himl;
501 force_redraw(hwndfortest);
503 imldp.fStyle = SRCCOPY;
504 imldp.rgbBk = CLR_DEFAULT;
505 imldp.rgbFg = CLR_DEFAULT;
506 imldp.y = 100;
507 imldp.x = 100;
508 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
509 imldp.i ++;
510 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
511 imldp.i ++;
512 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
513 imldp.i ++;
514 ok(!pImageList_DrawIndirect(&imldp),"should fail\n");
516 /* remove three */
517 ok(ImageList_Remove(himl, 0), "removing 1st bitmap\n");
518 ok(ImageList_Remove(himl, 0), "removing 2nd bitmap\n");
519 ok(ImageList_Remove(himl, 0), "removing 3rd bitmap\n");
521 /* destroy it */
522 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
524 /* bitmaps should not be deleted by the imagelist */
525 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
526 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
527 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
529 ReleaseDC(hwndfortest, hdc);
530 DestroyWindow(hwndfortest);
533 static int get_color_format(HBITMAP bmp)
535 BITMAPINFO bmi;
536 HDC hdc = CreateCompatibleDC(0);
537 HBITMAP hOldBmp = SelectObject(hdc, bmp);
538 int ret;
540 memset(&bmi, 0, sizeof(bmi));
541 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
542 ret = GetDIBits(hdc, bmp, 0, 0, 0, &bmi, DIB_RGB_COLORS);
543 ok(ret, "GetDIBits failed\n");
545 SelectObject(hdc, hOldBmp);
546 DeleteDC(hdc);
547 return bmi.bmiHeader.biBitCount;
550 static void test_merge_colors(void)
552 HIMAGELIST himl[8], hmerge;
553 int sizes[] = { ILC_COLOR, ILC_COLOR | ILC_MASK, ILC_COLOR4, ILC_COLOR8, ILC_COLOR16, ILC_COLOR24, ILC_COLOR32, ILC_COLORDDB };
554 HICON hicon1;
555 IMAGEINFO info;
556 int bpp, i, j;
558 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
559 ok(hicon1 != NULL, "failed to create hicon1\n");
561 for (i = 0; i < 8; i++)
563 himl[i] = ImageList_Create(32, 32, sizes[i], 0, 3);
564 ok(himl[i] != NULL, "failed to create himl[%d]\n", i);
565 ok(0 == ImageList_AddIcon(himl[i], hicon1), "add icon1 to himl[%d] failed\n", i);
566 if (i == 0 || i == 1 || i == 7)
568 ImageList_GetImageInfo(himl[i], 0, &info);
569 sizes[i] = get_color_format(info.hbmImage);
572 DestroyIcon(hicon1);
573 for (i = 0; i < 8; i++)
574 for (j = 0; j < 8; j++)
576 hmerge = ImageList_Merge(himl[i], 0, himl[j], 0, 0, 0);
577 ok(hmerge != NULL, "merge himl[%d], himl[%d] failed\n", i, j);
579 ImageList_GetImageInfo(hmerge, 0, &info);
580 bpp = get_color_format(info.hbmImage);
581 /* ILC_COLOR[X] is defined as [X] */
582 if (i == 4 && j == 7)
583 ok(bpp == 16, /* merging ILC_COLOR16 with ILC_COLORDDB seems to be a special case */
584 "wrong biBitCount %d when merging lists %d (%d) and %d (%d)\n", bpp, i, sizes[i], j, sizes[j]);
585 else
586 ok(bpp == (i > j ? sizes[i] : sizes[j]),
587 "wrong biBitCount %d when merging lists %d (%d) and %d (%d)\n", bpp, i, sizes[i], j, sizes[j]);
588 ok(info.hbmMask != 0, "Imagelist merged from %d and %d had no mask\n", i, j);
590 if (hmerge) ImageList_Destroy(hmerge);
593 for (i = 0; i < 8; i++)
594 ImageList_Destroy(himl[i]);
597 static void test_merge(void)
599 HIMAGELIST himl1, himl2, hmerge;
600 HICON hicon1;
601 HWND hwnd = create_a_window();
603 himl1 = ImageList_Create(32,32,0,0,3);
604 ok(himl1 != NULL,"failed to create himl1\n");
606 himl2 = ImageList_Create(32,32,0,0,3);
607 ok(himl2 != NULL,"failed to create himl2\n");
609 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
610 ok(hicon1 != NULL, "failed to create hicon1\n");
612 if (!himl1 || !himl2 || !hicon1)
613 return;
615 ok(0==ImageList_AddIcon(himl2, hicon1),"add icon1 to himl2 failed\n");
616 check_bits(hwnd, himl2, 0, 32, icon_bits, "add icon1 to himl2");
618 /* If himl1 has no images, merge still succeeds */
619 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
620 ok(hmerge != NULL, "merge himl1,-1 failed\n");
621 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,-1");
622 if (hmerge) ImageList_Destroy(hmerge);
624 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
625 ok(hmerge != NULL,"merge himl1,0 failed\n");
626 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,0");
627 if (hmerge) ImageList_Destroy(hmerge);
629 /* Same happens if himl2 is empty */
630 ImageList_Destroy(himl2);
631 himl2 = ImageList_Create(32,32,0,0,3);
632 ok(himl2 != NULL,"failed to recreate himl2\n");
633 if (!himl2)
634 return;
636 hmerge = ImageList_Merge(himl1, -1, himl2, -1, 0, 0);
637 ok(hmerge != NULL, "merge himl2,-1 failed\n");
638 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,-1");
639 if (hmerge) ImageList_Destroy(hmerge);
641 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
642 ok(hmerge != NULL, "merge himl2,0 failed\n");
643 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,0");
644 if (hmerge) ImageList_Destroy(hmerge);
646 /* Now try merging an image with itself */
647 ok(0==ImageList_AddIcon(himl2, hicon1),"re-add icon1 to himl2 failed\n");
649 hmerge = ImageList_Merge(himl2, 0, himl2, 0, 0, 0);
650 ok(hmerge != NULL, "merge himl2 with itself failed\n");
651 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2 with itself");
652 if (hmerge) ImageList_Destroy(hmerge);
654 /* Try merging 2 different image lists */
655 ok(0==ImageList_AddIcon(himl1, hicon1),"add icon1 to himl1 failed\n");
657 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
658 ok(hmerge != NULL, "merge himl1 with himl2 failed\n");
659 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2");
660 if (hmerge) ImageList_Destroy(hmerge);
662 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 8, 16);
663 ok(hmerge != NULL, "merge himl1 with himl2 8,16 failed\n");
664 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2, 8,16");
665 if (hmerge) ImageList_Destroy(hmerge);
667 ImageList_Destroy(himl1);
668 ImageList_Destroy(himl2);
669 DestroyIcon(hicon1);
670 DestroyWindow(hwnd);
673 /*********************** imagelist storage test ***************************/
675 #define BMP_CX 48
677 struct my_IStream
679 IStream IStream_iface;
680 char *iml_data; /* written imagelist data */
681 ULONG iml_data_size;
684 static struct my_IStream *impl_from_IStream(IStream *iface)
686 return CONTAINING_RECORD(iface, struct my_IStream, IStream_iface);
689 static HRESULT STDMETHODCALLTYPE Test_Stream_QueryInterface(IStream *iface, REFIID riid,
690 void **ppvObject)
692 ok(0, "unexpected call\n");
693 return E_NOTIMPL;
696 static ULONG STDMETHODCALLTYPE Test_Stream_AddRef(IStream *iface)
698 ok(0, "unexpected call\n");
699 return 2;
702 static ULONG STDMETHODCALLTYPE Test_Stream_Release(IStream *iface)
704 ok(0, "unexpected call\n");
705 return 1;
708 static HRESULT STDMETHODCALLTYPE Test_Stream_Read(IStream *iface, void *pv, ULONG cb,
709 ULONG *pcbRead)
711 ok(0, "unexpected call\n");
712 return E_NOTIMPL;
715 static BOOL allocate_storage(struct my_IStream *my_is, ULONG add)
717 my_is->iml_data_size += add;
719 if (!my_is->iml_data)
720 my_is->iml_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data_size);
721 else
722 my_is->iml_data = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data, my_is->iml_data_size);
724 return my_is->iml_data != NULL;
727 static HRESULT STDMETHODCALLTYPE Test_Stream_Write(IStream *iface, const void *pv, ULONG cb,
728 ULONG *pcbWritten)
730 struct my_IStream *my_is = impl_from_IStream(iface);
731 ULONG current_iml_data_size = my_is->iml_data_size;
733 if (!allocate_storage(my_is, cb)) return E_FAIL;
735 memcpy(my_is->iml_data + current_iml_data_size, pv, cb);
736 if (pcbWritten) *pcbWritten = cb;
738 return S_OK;
741 static HRESULT STDMETHODCALLTYPE Test_Stream_Seek(IStream *iface, LARGE_INTEGER dlibMove,
742 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
744 ok(0, "unexpected call\n");
745 return E_NOTIMPL;
748 static HRESULT STDMETHODCALLTYPE Test_Stream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
750 ok(0, "unexpected call\n");
751 return E_NOTIMPL;
754 static HRESULT STDMETHODCALLTYPE Test_Stream_CopyTo(IStream *iface, IStream *pstm,
755 ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead,
756 ULARGE_INTEGER *pcbWritten)
758 ok(0, "unexpected call\n");
759 return E_NOTIMPL;
762 static HRESULT STDMETHODCALLTYPE Test_Stream_Commit(IStream *iface, DWORD grfCommitFlags)
764 ok(0, "unexpected call\n");
765 return E_NOTIMPL;
768 static HRESULT STDMETHODCALLTYPE Test_Stream_Revert(IStream *iface)
770 ok(0, "unexpected call\n");
771 return E_NOTIMPL;
774 static HRESULT STDMETHODCALLTYPE Test_Stream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset,
775 ULARGE_INTEGER cb, DWORD dwLockType)
777 ok(0, "unexpected call\n");
778 return E_NOTIMPL;
781 static HRESULT STDMETHODCALLTYPE Test_Stream_UnlockRegion(IStream *iface, ULARGE_INTEGER libOffset,
782 ULARGE_INTEGER cb, DWORD dwLockType)
784 ok(0, "unexpected call\n");
785 return E_NOTIMPL;
788 static HRESULT STDMETHODCALLTYPE Test_Stream_Stat(IStream *iface, STATSTG *pstatstg,
789 DWORD grfStatFlag)
791 ok(0, "unexpected call\n");
792 return E_NOTIMPL;
795 static HRESULT STDMETHODCALLTYPE Test_Stream_Clone(IStream *iface, IStream **ppstm)
797 ok(0, "unexpected call\n");
798 return E_NOTIMPL;
801 static const IStreamVtbl Test_Stream_Vtbl =
803 Test_Stream_QueryInterface,
804 Test_Stream_AddRef,
805 Test_Stream_Release,
806 Test_Stream_Read,
807 Test_Stream_Write,
808 Test_Stream_Seek,
809 Test_Stream_SetSize,
810 Test_Stream_CopyTo,
811 Test_Stream_Commit,
812 Test_Stream_Revert,
813 Test_Stream_LockRegion,
814 Test_Stream_UnlockRegion,
815 Test_Stream_Stat,
816 Test_Stream_Clone
819 static struct my_IStream Test_Stream = { { &Test_Stream_Vtbl }, 0, 0 };
821 static INT DIB_GetWidthBytes( int width, int bpp )
823 return ((width * bpp + 31) / 8) & ~3;
826 static ULONG check_bitmap_data(const char *bm_data, ULONG bm_data_size,
827 INT width, INT height, INT bpp,
828 const char *comment)
830 const BITMAPFILEHEADER *bmfh = (const BITMAPFILEHEADER *)bm_data;
831 const BITMAPINFOHEADER *bmih = (const BITMAPINFOHEADER *)(bm_data + sizeof(*bmfh));
832 ULONG hdr_size, image_size;
834 hdr_size = sizeof(*bmfh) + sizeof(*bmih);
835 if (bmih->biBitCount <= 8) hdr_size += (1 << bpp) * sizeof(RGBQUAD);
837 ok(bmfh->bfType == (('M' << 8) | 'B'), "wrong bfType 0x%02x\n", bmfh->bfType);
838 ok(bmfh->bfSize == hdr_size, "wrong bfSize 0x%02x\n", bmfh->bfSize);
839 ok(bmfh->bfReserved1 == 0, "wrong bfReserved1 0x%02x\n", bmfh->bfReserved1);
840 ok(bmfh->bfReserved2 == 0, "wrong bfReserved2 0x%02x\n", bmfh->bfReserved2);
841 ok(bmfh->bfOffBits == hdr_size, "wrong bfOffBits 0x%02x\n", bmfh->bfOffBits);
843 ok(bmih->biSize == sizeof(*bmih), "wrong biSize %d\n", bmih->biSize);
844 ok(bmih->biWidth == width, "wrong biWidth %d (expected %d)\n", bmih->biWidth, width);
845 ok(bmih->biHeight == height, "wrong biHeight %d (expected %d)\n", bmih->biHeight, height);
846 ok(bmih->biPlanes == 1, "wrong biPlanes %d\n", bmih->biPlanes);
847 ok(bmih->biBitCount == bpp, "wrong biBitCount %d\n", bmih->biBitCount);
849 image_size = DIB_GetWidthBytes(bmih->biWidth, bmih->biBitCount) * bmih->biHeight;
850 ok(bmih->biSizeImage == image_size, "wrong biSizeImage %u\n", bmih->biSizeImage);
852 if (0)
854 char fname[256];
855 FILE *f;
856 sprintf(fname, "bmp_%s.bmp", comment);
857 f = fopen(fname, "wb");
858 fwrite(bm_data, 1, bm_data_size, f);
859 fclose(f);
862 return hdr_size + image_size;
865 static void check_ilhead_data(const char *ilh_data, INT cx, INT cy, INT cur, INT max, INT grow, INT flags)
867 const ILHEAD *ilh = (const ILHEAD *)ilh_data;
869 ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
870 ok(ilh->usVersion == 0x101, "wrong usVersion %x (expected 0x101)\n", ilh->usVersion);
871 ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
872 ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
873 ok(ilh->cGrow == grow, "wrong cGrow %d (expected %d)\n", ilh->cGrow, grow);
874 ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
875 ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
876 ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
877 ok(ilh->flags == flags || broken(!(ilh->flags & 0xfe) && (flags & 0xfe) == ILC_COLOR4), /* <= w2k */
878 "wrong flags %04x\n", ilh->flags);
879 ok(ilh->ovls[0] == -1, "wrong ovls[0] %04x\n", ilh->ovls[0]);
880 ok(ilh->ovls[1] == -1, "wrong ovls[1] %04x\n", ilh->ovls[1]);
881 ok(ilh->ovls[2] == -1, "wrong ovls[2] %04x\n", ilh->ovls[2]);
882 ok(ilh->ovls[3] == -1, "wrong ovls[3] %04x\n", ilh->ovls[3]);
885 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
887 HDC hdc;
888 BITMAPINFO bmi;
889 HBITMAP hbmp, hbmp_old;
890 HBRUSH hbrush;
891 RECT rc = { 0, 0, cx, cy };
893 hdc = CreateCompatibleDC(0);
895 memset(&bmi, 0, sizeof(bmi));
896 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
897 bmi.bmiHeader.biHeight = cx;
898 bmi.bmiHeader.biWidth = cy;
899 bmi.bmiHeader.biBitCount = 24;
900 bmi.bmiHeader.biPlanes = 1;
901 bmi.bmiHeader.biCompression = BI_RGB;
902 hbmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
904 hbmp_old = SelectObject(hdc, hbmp);
906 hbrush = CreateSolidBrush(color);
907 FillRect(hdc, &rc, hbrush);
908 DeleteObject(hbrush);
910 DrawTextA(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
912 SelectObject(hdc, hbmp_old);
913 DeleteDC(hdc);
915 return hbmp;
918 #define iml_clear_stream_data() \
919 HeapFree(GetProcessHeap(), 0, Test_Stream.iml_data); \
920 Test_Stream.iml_data = NULL; \
921 Test_Stream.iml_data_size = 0;
923 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, INT grow,
924 INT width, INT height, INT flags, const char *comment)
926 INT ret, cxx, cyy, size;
928 trace("%s\n", comment);
930 ret = ImageList_GetImageCount(himl);
931 ok(ret == cur, "expected image count %d got %d\n", cur, ret);
933 ret = ImageList_GetIconSize(himl, &cxx, &cyy);
934 ok(ret, "ImageList_GetIconSize failed\n");
935 ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx);
936 ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy);
938 iml_clear_stream_data();
939 ret = ImageList_Write(himl, &Test_Stream.IStream_iface);
940 ok(ret, "ImageList_Write failed\n");
942 ok(Test_Stream.iml_data != 0, "ImageList_Write didn't write any data\n");
943 ok(Test_Stream.iml_data_size > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n");
945 check_ilhead_data(Test_Stream.iml_data, cx, cy, cur, max, grow, flags);
946 size = check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD),
947 Test_Stream.iml_data_size - sizeof(ILHEAD),
948 width, height, flags & 0xfe, comment);
949 if (size < Test_Stream.iml_data_size - sizeof(ILHEAD)) /* mask is present */
951 ok( flags & ILC_MASK, "extra data %u/%u but mask not expected\n",
952 Test_Stream.iml_data_size, size );
953 check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD) + size,
954 Test_Stream.iml_data_size - sizeof(ILHEAD) - size,
955 width, height, 1, comment);
959 static void image_list_init(HIMAGELIST himl)
961 HBITMAP hbm;
962 char comment[16];
963 INT n = 1;
964 DWORD i;
965 static const struct test_data
967 BYTE grey;
968 INT cx, cy, cur, max, grow, width, height, bpp;
969 const char *comment;
970 } td[] =
972 { 255, BMP_CX, BMP_CX, 1, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 1" },
973 { 170, BMP_CX, BMP_CX, 2, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 2" },
974 { 85, BMP_CX, BMP_CX, 3, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 3" },
975 { 0, BMP_CX, BMP_CX, 4, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 4" },
976 { 0, BMP_CX, BMP_CX, 5, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 5" },
977 { 85, BMP_CX, BMP_CX, 6, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 6" },
978 { 170, BMP_CX, BMP_CX, 7, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 7" },
979 { 255, BMP_CX, BMP_CX, 8, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 8" },
980 { 255, BMP_CX, BMP_CX, 9, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 9" },
981 { 170, BMP_CX, BMP_CX, 10, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 10" },
982 { 85, BMP_CX, BMP_CX, 11, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 11" },
983 { 0, BMP_CX, BMP_CX, 12, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 12" },
984 { 0, BMP_CX, BMP_CX, 13, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 13" },
985 { 85, BMP_CX, BMP_CX, 14, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 14" },
986 { 170, BMP_CX, BMP_CX, 15, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 15" },
987 { 255, BMP_CX, BMP_CX, 16, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 16" },
988 { 255, BMP_CX, BMP_CX, 17, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 17" },
989 { 170, BMP_CX, BMP_CX, 18, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 18" },
990 { 85, BMP_CX, BMP_CX, 19, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 19" },
991 { 0, BMP_CX, BMP_CX, 20, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 20" },
992 { 0, BMP_CX, BMP_CX, 21, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 21" },
993 { 85, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 22" },
994 { 170, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 23" },
995 { 255, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 24" }
998 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "total 0");
1000 #define add_bitmap(grey) \
1001 sprintf(comment, "%d", n++); \
1002 hbm = create_bitmap(BMP_CX, BMP_CX, RGB((grey),(grey),(grey)), comment); \
1003 ImageList_Add(himl, hbm, NULL); \
1004 DeleteObject(hbm);
1006 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
1008 add_bitmap(td[i].grey);
1009 check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, td[i].grow,
1010 td[i].width, td[i].height, td[i].bpp, td[i].comment);
1012 #undef add_bitmap
1015 static void test_imagelist_storage(void)
1017 HIMAGELIST himl;
1018 HBITMAP hbm;
1019 HICON icon;
1020 INT ret;
1022 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
1023 ok(himl != 0, "ImageList_Create failed\n");
1025 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "empty");
1027 image_list_init(himl);
1028 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "orig");
1030 ret = ImageList_Remove(himl, 4);
1031 ok(ret, "ImageList_Remove failed\n");
1032 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "1");
1034 ret = ImageList_Remove(himl, 5);
1035 ok(ret, "ImageList_Remove failed\n");
1036 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "2");
1038 ret = ImageList_Remove(himl, 6);
1039 ok(ret, "ImageList_Remove failed\n");
1040 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "3");
1042 ret = ImageList_Remove(himl, 7);
1043 ok(ret, "ImageList_Remove failed\n");
1044 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "4");
1046 ret = ImageList_Remove(himl, -2);
1047 ok(!ret, "ImageList_Remove(-2) should fail\n");
1048 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "5");
1050 ret = ImageList_Remove(himl, 20);
1051 ok(!ret, "ImageList_Remove(20) should fail\n");
1052 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "6");
1054 ret = ImageList_Remove(himl, -1);
1055 ok(ret, "ImageList_Remove(-1) failed\n");
1056 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "7");
1058 ret = ImageList_Destroy(himl);
1059 ok(ret, "ImageList_Destroy failed\n");
1061 iml_clear_stream_data();
1063 /* test ImageList_Create storage allocation */
1065 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 0, 32);
1066 ok(himl != 0, "ImageList_Create failed\n");
1067 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 32, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "init 0 grow 32");
1068 hbm = create_bitmap(BMP_CX * 9, BMP_CX, 0, "9");
1069 ret = ImageList_Add(himl, hbm, NULL);
1070 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1071 check_iml_data(himl, BMP_CX, BMP_CX, 1, 34, 32, BMP_CX * 4, BMP_CX * 9, ILC_COLOR24, "add 1 x 9");
1072 DeleteObject(hbm);
1073 ret = ImageList_Destroy(himl);
1074 ok(ret, "ImageList_Destroy failed\n");
1075 iml_clear_stream_data();
1077 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 4);
1078 ok(himl != 0, "ImageList_Create failed\n");
1079 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 4 grow 4");
1080 hbm = create_bitmap(BMP_CX, BMP_CX * 9, 0, "9");
1081 ret = ImageList_Add(himl, hbm, NULL);
1082 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1083 check_iml_data(himl, BMP_CX, BMP_CX, 9, 15, 4, BMP_CX * 4, BMP_CX * 4, ILC_COLOR24, "add 9 x 1");
1084 ret = ImageList_Add(himl, hbm, NULL);
1085 ok(ret == 9, "ImageList_Add returned %d, expected 9\n", ret);
1086 check_iml_data(himl, BMP_CX, BMP_CX, 18, 25, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "add 9 x 1");
1087 DeleteObject(hbm);
1088 ret = ImageList_Destroy(himl);
1089 ok(ret, "ImageList_Destroy failed\n");
1090 iml_clear_stream_data();
1092 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 207, 209);
1093 ok(himl != 0, "ImageList_Create failed\n");
1094 check_iml_data(himl, BMP_CX, BMP_CX, 0, 208, 212, BMP_CX * 4, BMP_CX * 52, ILC_COLOR24, "init 207 grow 209");
1095 ret = ImageList_Destroy(himl);
1096 ok(ret, "ImageList_Destroy failed\n");
1097 iml_clear_stream_data();
1099 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 209, 207);
1100 ok(himl != 0, "ImageList_Create failed\n");
1101 check_iml_data(himl, BMP_CX, BMP_CX, 0, 210, 208, BMP_CX * 4, BMP_CX * 53, ILC_COLOR24, "init 209 grow 207");
1102 ret = ImageList_Destroy(himl);
1103 ok(ret, "ImageList_Destroy failed\n");
1104 iml_clear_stream_data();
1106 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 14, 4);
1107 ok(himl != 0, "ImageList_Create failed\n");
1108 check_iml_data(himl, BMP_CX, BMP_CX, 0, 15, 4, BMP_CX * 4, BMP_CX * 4, ILC_COLOR24, "init 14 grow 4");
1109 ret = ImageList_Destroy(himl);
1110 ok(ret, "ImageList_Destroy failed\n");
1111 iml_clear_stream_data();
1113 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 5, 9);
1114 ok(himl != 0, "ImageList_Create failed\n");
1115 check_iml_data(himl, BMP_CX, BMP_CX, 0, 6, 12, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 5 grow 9");
1116 ret = ImageList_Destroy(himl);
1117 ok(ret, "ImageList_Destroy failed\n");
1118 iml_clear_stream_data();
1120 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 9, 5);
1121 ok(himl != 0, "ImageList_Create failed\n");
1122 check_iml_data(himl, BMP_CX, BMP_CX, 0, 10, 8, BMP_CX * 4, BMP_CX * 3, ILC_COLOR24, "init 9 grow 5");
1123 ret = ImageList_Destroy(himl);
1124 ok(ret, "ImageList_Destroy failed\n");
1125 iml_clear_stream_data();
1127 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 2, 4);
1128 ok(himl != 0, "ImageList_Create failed\n");
1129 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "init 2 grow 4");
1130 ret = ImageList_Destroy(himl);
1131 ok(ret, "ImageList_Destroy failed\n");
1132 iml_clear_stream_data();
1134 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 2);
1135 ok(himl != 0, "ImageList_Create failed\n");
1136 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 4 grow 2");
1137 ret = ImageList_Destroy(himl);
1138 ok(ret, "ImageList_Destroy failed\n");
1139 iml_clear_stream_data();
1141 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR8, 4, 2);
1142 ok(himl != 0, "ImageList_Create failed\n");
1143 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR8, "bpp 8");
1144 ret = ImageList_Destroy(himl);
1145 ok(ret, "ImageList_Destroy failed\n");
1146 iml_clear_stream_data();
1148 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4, 4, 2);
1149 ok(himl != 0, "ImageList_Create failed\n");
1150 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp 4");
1151 ret = ImageList_Destroy(himl);
1152 ok(ret, "ImageList_Destroy failed\n");
1153 iml_clear_stream_data();
1155 himl = ImageList_Create(BMP_CX, BMP_CX, 0, 4, 2);
1156 ok(himl != 0, "ImageList_Create failed\n");
1157 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp default");
1158 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1159 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1160 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1161 DestroyIcon( icon );
1162 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp default");
1163 ret = ImageList_Destroy(himl);
1164 ok(ret, "ImageList_Destroy failed\n");
1165 iml_clear_stream_data();
1167 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24|ILC_MASK, 4, 2);
1168 ok(himl != 0, "ImageList_Create failed\n");
1169 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24|ILC_MASK,
1170 "bpp 24 + mask");
1171 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1172 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1173 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1174 DestroyIcon( icon );
1175 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24|ILC_MASK,
1176 "bpp 24 + mask");
1177 ret = ImageList_Destroy(himl);
1178 ok(ret, "ImageList_Destroy failed\n");
1179 iml_clear_stream_data();
1181 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 4, 2);
1182 ok(himl != 0, "ImageList_Create failed\n");
1183 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4|ILC_MASK,
1184 "bpp 4 + mask");
1185 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1186 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1187 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1188 DestroyIcon( icon );
1189 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4|ILC_MASK,
1190 "bpp 4 + mask");
1191 ret = ImageList_Destroy(himl);
1192 ok(ret, "ImageList_Destroy failed\n");
1193 iml_clear_stream_data();
1195 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 99);
1196 ok(himl != 0, "ImageList_Create failed\n");
1197 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 100, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1198 "init 2 grow 99");
1199 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1200 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1201 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1202 check_iml_data(himl, BMP_CX, BMP_CX, 2, 3, 100, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1203 "init 2 grow 99 2 icons");
1204 ok( ImageList_AddIcon(himl, icon) == 2,"failed to add icon\n");
1205 DestroyIcon( icon );
1206 check_iml_data(himl, BMP_CX, BMP_CX, 3, 104, 100, BMP_CX * 4, BMP_CX * 104/4, ILC_COLOR4|ILC_MASK,
1207 "init 2 grow 99 3 icons");
1208 ok( ImageList_Remove(himl, -1) == TRUE,"failed to remove icon\n");
1209 check_iml_data(himl, BMP_CX, BMP_CX, 0, 100, 100, BMP_CX * 4, BMP_CX * 100/4, ILC_COLOR4|ILC_MASK,
1210 "init 2 grow 99 empty");
1211 ok( ImageList_SetImageCount(himl, 22) == TRUE,"failed to set image count\n");
1212 check_iml_data(himl, BMP_CX, BMP_CX, 22, 23, 100, BMP_CX * 4, BMP_CX * 24/4, ILC_COLOR4|ILC_MASK,
1213 "init 2 grow 99 set count 22");
1214 ok( ImageList_SetImageCount(himl, 0) == TRUE,"failed to set image count\n");
1215 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 100, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1216 "init 2 grow 99 set count 0");
1217 ok( ImageList_SetImageCount(himl, 42) == TRUE,"failed to set image count\n");
1218 check_iml_data(himl, BMP_CX, BMP_CX, 42, 43, 100, BMP_CX * 4, BMP_CX * 44/4, ILC_COLOR4|ILC_MASK,
1219 "init 2 grow 99 set count 42");
1220 ret = ImageList_Destroy(himl);
1221 ok(ret, "ImageList_Destroy failed\n");
1222 iml_clear_stream_data();
1224 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65536+12);
1225 ok(himl != 0, "ImageList_Create failed\n");
1226 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 12, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1227 "init 2 grow 65536+12");
1228 ret = ImageList_Destroy(himl);
1229 ok(ret, "ImageList_Destroy failed\n");
1230 iml_clear_stream_data();
1232 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65535);
1233 ok(himl != 0, "ImageList_Create failed\n");
1234 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 0, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1235 "init 2 grow 65535");
1236 ret = ImageList_Destroy(himl);
1237 ok(ret, "ImageList_Destroy failed\n");
1238 iml_clear_stream_data();
1240 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, -20);
1241 ok(himl != 0, "ImageList_Create failed\n");
1242 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1243 "init 2 grow -20");
1244 ret = ImageList_Destroy(himl);
1245 ok(ret, "ImageList_Destroy failed\n");
1246 iml_clear_stream_data();
1249 static void test_shell_imagelist(void)
1251 HRESULT (WINAPI *pSHGetImageList)(INT, REFIID, void**);
1252 IImageList *iml = NULL;
1253 HMODULE hShell32;
1254 HRESULT hr;
1255 int out = 0;
1256 RECT rect;
1257 int cx, cy;
1259 /* Try to load function from shell32 */
1260 hShell32 = LoadLibraryA("shell32.dll");
1261 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1263 if (!pSHGetImageList)
1265 win_skip("SHGetImageList not available, skipping test\n");
1266 FreeLibrary(hShell32);
1267 return;
1270 /* Get system image list */
1271 hr = pSHGetImageList(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1272 ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1274 if (hr != S_OK) {
1275 FreeLibrary(hShell32);
1276 return;
1279 IImageList_GetImageCount(iml, &out);
1280 ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1282 /* Fetch the small icon size */
1283 cx = GetSystemMetrics(SM_CXSMICON);
1284 cy = GetSystemMetrics(SM_CYSMICON);
1286 /* Check icon size matches */
1287 IImageList_GetImageRect(iml, 0, &rect);
1288 ok(((rect.right == cx) && (rect.bottom == cy)),
1289 "IImageList_GetImageRect returned r:%d,b:%d\n",
1290 rect.right, rect.bottom);
1292 IImageList_Release(iml);
1293 FreeLibrary(hShell32);
1296 static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
1298 HBITMAP hBitmap;
1299 UINT32 *buffer = NULL;
1300 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
1301 0, 0, 0, 0, 0}};
1303 hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1304 ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1306 if(!hBitmap || !buffer)
1308 DeleteObject(hBitmap);
1309 return NULL;
1312 buffer[0] = pixel1;
1313 buffer[1] = pixel2;
1315 return hBitmap;
1318 static BOOL colour_match(UINT32 x, UINT32 y)
1320 const INT32 tolerance = 8;
1322 const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1323 const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1324 const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1326 return (dr <= tolerance && dg <= tolerance && db <= tolerance);
1329 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1330 UINT32 expected, int line)
1332 bits[0] = 0x00FFFFFF;
1333 pImageList_DrawIndirect(ildp);
1334 ok(colour_match(bits[0], expected),
1335 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1336 bits[0] & 0x00FFFFFF, expected, line);
1340 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1341 UINT fStyle, UINT32 expected, int line)
1343 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1344 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1345 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1348 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1349 DWORD dwRop, UINT32 expected, int line)
1351 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1352 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1353 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1356 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1357 UINT fState, DWORD Frame, UINT32 expected, int line)
1359 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1360 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1361 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1364 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1365 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1366 UINT32 broken_expected, int line)
1368 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1369 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1370 bits[0] = 0x00FFFFFF;
1371 pImageList_DrawIndirect(&ildp);
1372 ok(colour_match(bits[0], expected) ||
1373 broken(colour_match(bits[0], broken_expected)),
1374 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1375 bits[0] & 0x00FFFFFF, expected, line);
1378 static void test_ImageList_DrawIndirect(void)
1380 HIMAGELIST himl = NULL;
1381 int ret;
1382 HDC hdcDst = NULL;
1383 HBITMAP hbmOld = NULL, hbmDst = NULL;
1384 HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1385 HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
1386 int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1387 UINT32 *bits = 0;
1388 UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1389 int bpp, broken_value;
1391 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1392 0, 0, 0, 0, 0}};
1394 hdcDst = CreateCompatibleDC(0);
1395 ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1396 if (!hdcDst)
1397 return;
1398 bpp = GetDeviceCaps(hdcDst, BITSPIXEL);
1400 hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1401 ok(hbmMask != 0, "CreateBitmap failed\n");
1402 if(!hbmMask) goto cleanup;
1404 hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1405 ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1406 if(!hbmInverseMask) goto cleanup;
1408 himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1409 ok(himl != 0, "ImageList_Create failed\n");
1410 if(!himl) goto cleanup;
1412 /* Add a no-alpha image */
1413 hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
1414 if(!hbmImage) goto cleanup;
1416 iImage = pImageList_Add(himl, hbmImage, hbmMask);
1417 ok(iImage != -1, "ImageList_Add failed\n");
1418 if(iImage == -1) goto cleanup;
1420 /* Add an alpha image */
1421 hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
1422 if(!hbmAlphaImage) goto cleanup;
1424 iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1425 ok(iAlphaImage != -1, "ImageList_Add failed\n");
1426 if(iAlphaImage == -1) goto cleanup;
1428 /* Add a transparent alpha image */
1429 hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
1430 if(!hbmTransparentImage) goto cleanup;
1432 iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1433 ok(iTransparentImage != -1, "ImageList_Add failed\n");
1434 if(iTransparentImage == -1) goto cleanup;
1436 /* 32-bit Tests */
1437 bitmapInfo.bmiHeader.biBitCount = 32;
1438 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1439 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1440 if (!hbmDst || !bits)
1441 goto cleanup;
1442 hbmOld = SelectObject(hdcDst, hbmDst);
1444 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1445 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1446 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
1447 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1448 else broken_value = 0x00B4BDC4;
1449 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1450 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1451 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1452 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1454 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
1455 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
1457 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1458 else broken_value = 0x009DA8B1;
1459 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1460 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1461 else broken_value = 0x008C99A3;
1462 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1463 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
1464 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
1465 todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
1467 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
1469 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1470 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
1472 /* ILD_ROP is ignored when the image has an alpha channel */
1473 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
1474 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
1476 todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
1477 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
1479 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
1480 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
1482 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
1483 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
1484 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
1486 cleanup:
1488 if(hbmOld)
1489 SelectObject(hdcDst, hbmOld);
1490 if(hbmDst)
1491 DeleteObject(hbmDst);
1493 if(hdcDst)
1494 DeleteDC(hdcDst);
1496 if(hbmMask)
1497 DeleteObject(hbmMask);
1498 if(hbmInverseMask)
1499 DeleteObject(hbmInverseMask);
1501 if(hbmImage)
1502 DeleteObject(hbmImage);
1503 if(hbmAlphaImage)
1504 DeleteObject(hbmAlphaImage);
1505 if(hbmTransparentImage)
1506 DeleteObject(hbmTransparentImage);
1508 if(himl)
1510 ret = ImageList_Destroy(himl);
1511 ok(ret, "ImageList_Destroy failed\n");
1515 static void test_iimagelist(void)
1517 IImageList *imgl, *imgl2;
1518 IImageList2 *imagelist;
1519 HIMAGELIST himl;
1520 HRESULT hr;
1521 ULONG ret;
1523 if (!pHIMAGELIST_QueryInterface)
1525 win_skip("XP imagelist functions not available\n");
1526 return;
1529 /* test reference counting on destruction */
1530 imgl = (IImageList*)createImageList(32, 32);
1531 ret = IImageList_AddRef(imgl);
1532 ok(ret == 2, "Expected 2, got %d\n", ret);
1533 ret = ImageList_Destroy((HIMAGELIST)imgl);
1534 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1535 ret = ImageList_Destroy((HIMAGELIST)imgl);
1536 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1537 ret = ImageList_Destroy((HIMAGELIST)imgl);
1538 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1540 imgl = (IImageList*)createImageList(32, 32);
1541 ret = IImageList_AddRef(imgl);
1542 ok(ret == 2, "Expected 2, got %d\n", ret);
1543 ret = ImageList_Destroy((HIMAGELIST)imgl);
1544 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1545 ret = IImageList_Release(imgl);
1546 ok(ret == 0, "Expected 0, got %d\n", ret);
1547 ret = ImageList_Destroy((HIMAGELIST)imgl);
1548 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1550 /* ref counting, HIMAGELIST_QueryInterface adds a reference */
1551 imgl = (IImageList*)createImageList(32, 32);
1552 hr = pHIMAGELIST_QueryInterface((HIMAGELIST)imgl, &IID_IImageList, (void**)&imgl2);
1553 ok(hr == S_OK, "got 0x%08x\n", hr);
1554 ok(imgl2 == imgl, "got different pointer\n");
1555 ret = IImageList_Release(imgl);
1556 ok(ret == 1, "got %u\n", ret);
1557 IImageList_Release(imgl);
1559 if (!pImageList_CoCreateInstance)
1561 win_skip("Vista imagelist functions not available\n");
1562 return;
1565 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1566 ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
1568 if (hr == S_OK)
1569 IImageList_Release(imgl);
1571 himl = createImageList(32, 32);
1573 if (!himl)
1574 return;
1576 hr = (pHIMAGELIST_QueryInterface)(himl, &IID_IImageList, (void **) &imgl);
1577 ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
1579 if (hr == S_OK)
1580 IImageList_Release(imgl);
1582 ImageList_Destroy(himl);
1584 /* IImageList2 */
1585 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList2, (void**)&imagelist);
1586 if (hr != S_OK)
1588 win_skip("IImageList2 is not supported.\n");
1589 return;
1591 ok(hr == S_OK, "got 0x%08x\n", hr);
1592 IImageList2_Release(imagelist);
1595 static void test_hotspot_v6(void)
1597 struct hotspot {
1598 int dx;
1599 int dy;
1602 #define SIZEX1 47
1603 #define SIZEY1 31
1604 #define SIZEX2 11
1605 #define SIZEY2 17
1606 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
1607 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
1608 { 10, 7 },
1609 { SIZEX1, SIZEY1 },
1610 { -9, -8 },
1611 { -7, 35 }
1613 int i, j;
1614 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
1615 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
1616 IImageList *imgl1, *imgl2;
1617 HRESULT hr;
1619 /* cast to IImageList */
1620 imgl1 = (IImageList *) himl1;
1621 imgl2 = (IImageList *) himl2;
1623 for (i = 0; i < HOTSPOTS_MAX; i++) {
1624 for (j = 0; j < HOTSPOTS_MAX; j++) {
1625 int dx1 = hotspots[i].dx;
1626 int dy1 = hotspots[i].dy;
1627 int dx2 = hotspots[j].dx;
1628 int dy2 = hotspots[j].dy;
1629 int correctx, correcty, newx, newy;
1630 char loc[256];
1631 IImageList *imglNew;
1632 POINT ppt;
1634 hr = IImageList_BeginDrag(imgl1, 0, dx1, dy1);
1635 ok(SUCCEEDED(hr), "BeginDrag failed for { %d, %d }\n", dx1, dy1);
1636 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
1638 /* check merging the dragged image with a second image */
1639 hr = IImageList_SetDragCursorImage(imgl2, (IUnknown *) imgl2, 0, dx2, dy2);
1640 ok(SUCCEEDED(hr), "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
1641 dx1, dy1, dx2, dy2);
1642 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
1644 /* check new hotspot, it should be the same like the old one */
1645 hr = IImageList_GetDragImage(imgl2, NULL, &ppt, &IID_IImageList, (PVOID *) &imglNew);
1646 ok(SUCCEEDED(hr), "GetDragImage failed\n");
1647 ok(ppt.x == dx1 && ppt.y == dy1,
1648 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
1649 dx1, dy1, ppt.x, ppt.y);
1650 /* check size of new dragged image */
1651 IImageList_GetIconSize(imglNew, &newx, &newy);
1652 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
1653 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
1654 ok(newx == correctx && newy == correcty,
1655 "Expected drag image size [%d,%d] got [%d,%d]\n",
1656 correctx, correcty, newx, newy);
1657 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
1658 IImageList_EndDrag(imgl2);
1661 #undef SIZEX1
1662 #undef SIZEY1
1663 #undef SIZEX2
1664 #undef SIZEY2
1665 #undef HOTSPOTS_MAX
1666 IImageList_Release(imgl2);
1667 IImageList_Release(imgl1);
1670 static void test_IImageList_Add_Remove(void)
1672 IImageList *imgl;
1673 HIMAGELIST himl;
1674 HRESULT hr;
1676 HICON hicon1;
1677 HICON hicon2;
1678 HICON hicon3;
1680 int ret;
1682 /* create an imagelist to play with */
1683 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1684 ok(himl != 0,"failed to create imagelist\n");
1686 imgl = (IImageList *) himl;
1688 /* load the icons to add to the image list */
1689 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1690 ok(hicon1 != 0, "no hicon1\n");
1691 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1692 ok(hicon2 != 0, "no hicon2\n");
1693 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1694 ok(hicon3 != 0, "no hicon3\n");
1696 /* remove when nothing exists */
1697 hr = IImageList_Remove(imgl, 0);
1698 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1700 /* removing everything from an empty imagelist should succeed */
1701 hr = IImageList_Remove(imgl, -1);
1702 ok(hr == S_OK, "removed nonexistent icon\n");
1704 /* add three */
1705 ret = -1;
1706 ok( IImageList_ReplaceIcon(imgl, -1, hicon1, &ret) == S_OK && (ret == 0),"failed to add icon1\n");
1707 ret = -1;
1708 ok( IImageList_ReplaceIcon(imgl, -1, hicon2, &ret) == S_OK && (ret == 1),"failed to add icon2\n");
1709 ret = -1;
1710 ok( IImageList_ReplaceIcon(imgl, -1, hicon3, &ret) == S_OK && (ret == 2),"failed to add icon3\n");
1712 /* remove an index out of range */
1713 ok( IImageList_Remove(imgl, 4711) == E_INVALIDARG, "got 0x%08x\n", hr);
1715 /* remove three */
1716 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1717 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1718 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1720 /* remove one extra */
1721 ok( IImageList_Remove(imgl, 0) == E_INVALIDARG, "got 0x%08x\n", hr);
1723 IImageList_Release(imgl);
1724 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1725 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1726 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1729 static void test_IImageList_Get_SetImageCount(void)
1731 IImageList *imgl;
1732 HIMAGELIST himl;
1733 HRESULT hr;
1734 INT ret;
1736 /* create an imagelist to play with */
1737 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1738 ok(himl != 0,"failed to create imagelist\n");
1740 imgl = (IImageList *) himl;
1742 /* check SetImageCount/GetImageCount */
1743 hr = IImageList_SetImageCount(imgl, 3);
1744 ok(hr == S_OK, "got 0x%08x\n", hr);
1745 ret = 0;
1746 hr = IImageList_GetImageCount(imgl, &ret);
1747 ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
1748 hr = IImageList_SetImageCount(imgl, 1);
1749 ok(hr == S_OK, "got 0x%08x\n", hr);
1750 ret = 0;
1751 hr = IImageList_GetImageCount(imgl, &ret);
1752 ok(hr == S_OK && ret == 1, "invalid image count after decrease to 1\n");
1753 hr = IImageList_SetImageCount(imgl, 0);
1754 ok(hr == S_OK, "got 0x%08x\n", hr);
1755 ret = -1;
1756 hr = IImageList_GetImageCount(imgl, &ret);
1757 ok(hr == S_OK && ret == 0, "invalid image count after decrease to 0\n");
1759 IImageList_Release(imgl);
1762 static void test_IImageList_Draw(void)
1764 IImageList *imgl;
1765 HIMAGELIST himl;
1767 HBITMAP hbm1;
1768 HBITMAP hbm2;
1769 HBITMAP hbm3;
1771 IMAGELISTDRAWPARAMS imldp;
1772 HWND hwndfortest;
1773 HRESULT hr;
1774 HDC hdc;
1775 int ret;
1777 hwndfortest = create_a_window();
1778 hdc = GetDC(hwndfortest);
1779 ok(hdc!=NULL, "couldn't get DC\n");
1781 /* create an imagelist to play with */
1782 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1783 ok(himl!=0,"failed to create imagelist\n");
1785 imgl = (IImageList *) himl;
1787 /* load the icons to add to the image list */
1788 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1789 ok(hbm1 != 0, "no bitmap 1\n");
1790 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1791 ok(hbm2 != 0, "no bitmap 2\n");
1792 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1793 ok(hbm3 != 0, "no bitmap 3\n");
1795 /* add three */
1796 ret = -1;
1797 ok( IImageList_Add(imgl, hbm1, 0, &ret) == S_OK && (ret == 0), "failed to add bitmap 1\n");
1798 ret = -1;
1799 ok( IImageList_Add(imgl, hbm2, 0, &ret) == S_OK && (ret == 1), "failed to add bitmap 2\n");
1801 ok( IImageList_SetImageCount(imgl, 3) == S_OK, "Setimage count failed\n");
1802 ok( IImageList_Replace(imgl, 2, hbm3, 0) == S_OK, "failed to replace bitmap 3\n");
1804 if (0)
1806 /* crashes on native */
1807 IImageList_Draw(imgl, NULL);
1810 memset(&imldp, 0, sizeof (imldp));
1811 hr = IImageList_Draw(imgl, &imldp);
1812 ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
1814 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
1815 imldp.hdcDst = hdc;
1816 imldp.himl = himl;
1818 force_redraw(hwndfortest);
1820 imldp.fStyle = SRCCOPY;
1821 imldp.rgbBk = CLR_DEFAULT;
1822 imldp.rgbFg = CLR_DEFAULT;
1823 imldp.y = 100;
1824 imldp.x = 100;
1825 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1826 imldp.i ++;
1827 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1828 imldp.i ++;
1829 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1830 imldp.i ++;
1831 ok( IImageList_Draw(imgl, &imldp) == E_INVALIDARG, "should fail\n");
1833 /* remove three */
1834 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 1st bitmap\n");
1835 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 2nd bitmap\n");
1836 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 3rd bitmap\n");
1838 /* destroy it */
1839 IImageList_Release(imgl);
1841 /* bitmaps should not be deleted by the imagelist */
1842 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1843 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1844 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1846 ReleaseDC(hwndfortest, hdc);
1847 DestroyWindow(hwndfortest);
1850 static void test_IImageList_Merge(void)
1852 HIMAGELIST himl1, himl2;
1853 IImageList *imgl1, *imgl2, *merge;
1854 HICON hicon1;
1855 HWND hwnd = create_a_window();
1856 HRESULT hr;
1857 int ret;
1859 himl1 = ImageList_Create(32,32,0,0,3);
1860 ok(himl1 != NULL,"failed to create himl1\n");
1862 himl2 = ImageList_Create(32,32,0,0,3);
1863 ok(himl2 != NULL,"failed to create himl2\n");
1865 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1866 ok(hicon1 != NULL, "failed to create hicon1\n");
1868 if (!himl1 || !himl2 || !hicon1)
1869 return;
1871 /* cast to IImageList */
1872 imgl1 = (IImageList *) himl1;
1873 imgl2 = (IImageList *) himl2;
1875 ret = -1;
1876 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl2 failed\n");
1878 if (0)
1880 /* null cases that crash on native */
1881 IImageList_Merge(imgl1, -1, NULL, 0, 0, 0, &IID_IImageList, (void**)&merge);
1882 IImageList_Merge(imgl1, -1, (IUnknown*) imgl2, 0, 0, 0, &IID_IImageList, NULL);
1885 /* If himl1 has no images, merge still succeeds */
1886 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1887 ok(hr == S_OK, "merge himl1,-1 failed\n");
1888 if (hr == S_OK) IImageList_Release(merge);
1890 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1891 ok(hr == S_OK, "merge himl1,0 failed\n");
1892 if (hr == S_OK) IImageList_Release(merge);
1894 /* Same happens if himl2 is empty */
1895 IImageList_Release(imgl2);
1896 himl2 = ImageList_Create(32,32,0,0,3);
1897 ok(himl2 != NULL,"failed to recreate himl2\n");
1899 imgl2 = (IImageList *) himl2;
1901 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
1902 ok(hr == S_OK, "merge himl2,-1 failed\n");
1903 if (hr == S_OK) IImageList_Release(merge);
1905 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1906 ok(hr == S_OK, "merge himl2,0 failed\n");
1907 if (hr == S_OK) IImageList_Release(merge);
1909 /* Now try merging an image with itself */
1910 ret = -1;
1911 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"re-add icon1 to himl2 failed\n");
1913 hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1914 ok(hr == S_OK, "merge himl2 with itself failed\n");
1915 if (hr == S_OK) IImageList_Release(merge);
1917 /* Try merging 2 different image lists */
1918 ret = -1;
1919 ok( IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl1 failed\n");
1921 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1922 ok(hr == S_OK, "merge himl1 with himl2 failed\n");
1923 if (hr == S_OK) IImageList_Release(merge);
1925 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
1926 ok(hr == S_OK, "merge himl1 with himl2 8,16 failed\n");
1927 if (hr == S_OK) IImageList_Release(merge);
1929 IImageList_Release(imgl1);
1930 IImageList_Release(imgl2);
1932 DestroyIcon(hicon1);
1933 DestroyWindow(hwnd);
1936 static void test_iconsize(void)
1938 HIMAGELIST himl;
1939 INT cx, cy;
1940 BOOL ret;
1942 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1943 /* null pointers, not zero imagelist dimensions */
1944 ret = ImageList_GetIconSize(himl, NULL, NULL);
1945 ok(!ret, "got %d\n", ret);
1947 /* doesn't touch return pointers */
1948 cx = 0x1abe11ed;
1949 ret = ImageList_GetIconSize(himl, &cx, NULL);
1950 ok(!ret, "got %d\n", ret);
1951 ok(cx == 0x1abe11ed, "got %d\n", cx);
1953 cy = 0x1abe11ed;
1954 ret = ImageList_GetIconSize(himl, NULL, &cy);
1955 ok(!ret, "got %d\n", ret);
1956 ok(cy == 0x1abe11ed, "got %d\n", cy);
1958 ImageList_Destroy(himl);
1960 ret = ImageList_GetIconSize((HIMAGELIST)0xdeadbeef, &cx, &cy);
1961 ok(!ret, "got %d\n", ret);
1964 static void test_create_destroy(void)
1966 HIMAGELIST himl;
1967 IImageList *imgl;
1968 INT cx, cy;
1969 BOOL rc;
1970 HRESULT hr;
1971 INT ret;
1973 /* list with zero or negative image dimensions */
1974 himl = ImageList_Create(0, 0, ILC_COLOR16, 0, 3);
1975 ok(himl == NULL, "got %p\n", himl);
1977 himl = ImageList_Create(0, 16, ILC_COLOR16, 0, 3);
1978 ok(himl == NULL, "got %p\n", himl);
1980 himl = ImageList_Create(16, 0, ILC_COLOR16, 0, 3);
1981 ok(himl == NULL, "got %p\n", himl);
1983 himl = ImageList_Create(16, -1, ILC_COLOR16, 0, 3);
1984 ok(himl == NULL, "got %p\n", himl);
1986 himl = ImageList_Create(-1, 16, ILC_COLOR16, 0, 3);
1987 ok(himl == NULL, "got %p\n", himl);
1989 rc = ImageList_Destroy((HIMAGELIST)0xdeadbeef);
1990 ok(rc == FALSE, "ImageList_Destroy(0xdeadbeef) should fail and not crash\n");
1992 /* DDB image lists */
1993 himl = ImageList_Create(0, 14, ILC_COLORDDB, 4, 4);
1994 ok(himl != NULL, "got %p\n", himl);
1995 imgl = (IImageList*)himl;
1996 IImageList_GetIconSize(imgl, &cx, &cy);
1997 ok (cx == 0, "Wrong cx (%i)\n", cx);
1998 ok (cy == 14, "Wrong cy (%i)\n", cy);
1999 ImageList_Destroy(himl);
2001 himl = ImageList_Create(0, 0, ILC_COLORDDB, 4, 4);
2002 ok(himl != NULL, "got %p\n", himl);
2003 imgl = (IImageList*)himl;
2004 IImageList_GetIconSize(imgl, &cx, &cy);
2005 ok (cx == 0, "Wrong cx (%i)\n", cx);
2006 ok (cy == 0, "Wrong cy (%i)\n", cy);
2007 ImageList_Destroy(himl);
2009 himl = ImageList_Create(0, 0, ILC_COLORDDB, 0, 4);
2010 ok(himl != NULL, "got %p\n", himl);
2011 imgl = (IImageList*)himl;
2012 IImageList_GetIconSize(imgl, &cx, &cy);
2013 ok (cx == 0, "Wrong cx (%i)\n", cx);
2014 ok (cy == 0, "Wrong cy (%i)\n", cy);
2016 hr = IImageList_SetImageCount(imgl, 3);
2017 ok(hr == S_OK, "got 0x%08x\n", hr);
2018 hr = IImageList_GetImageCount(imgl, &ret);
2019 ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
2021 /* Trying to actually add an image causes a crash on Windows */
2022 ImageList_Destroy(himl);
2024 /* Negative values fail */
2025 himl = ImageList_Create(-1, -1, ILC_COLORDDB, 4, 4);
2026 ok(himl == NULL, "got %p\n", himl);
2027 himl = ImageList_Create(-1, 1, ILC_COLORDDB, 4, 4);
2028 ok(himl == NULL, "got %p\n", himl);
2029 himl = ImageList_Create(1, -1, ILC_COLORDDB, 4, 4);
2030 ok(himl == NULL, "got %p\n", himl);
2033 static void test_IImageList_Clone(void)
2035 IImageList *imgl, *imgl2;
2036 HIMAGELIST himl;
2037 HRESULT hr;
2038 ULONG ref;
2040 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2041 imgl = (IImageList*)himl;
2043 if (0)
2045 /* crashes on native */
2046 IImageList_Clone(imgl, &IID_IImageList, NULL);
2049 hr = IImageList_Clone(imgl, &IID_IImageList, (void**)&imgl2);
2050 ok(hr == S_OK, "got 0x%08x\n", hr);
2051 ref = IImageList_Release(imgl2);
2052 ok(ref == 0, "got %u\n", ref);
2054 IImageList_Release(imgl);
2057 static void test_IImageList_GetBkColor(void)
2059 IImageList *imgl;
2060 HIMAGELIST himl;
2061 COLORREF color;
2062 HRESULT hr;
2064 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2065 imgl = (IImageList*)himl;
2067 if (0)
2069 /* crashes on native */
2070 IImageList_GetBkColor(imgl, NULL);
2073 hr = IImageList_GetBkColor(imgl, &color);
2074 ok(hr == S_OK, "got 0x%08x\n", hr);
2076 IImageList_Release(imgl);
2079 static void test_IImageList_SetBkColor(void)
2081 IImageList *imgl;
2082 HIMAGELIST himl;
2083 COLORREF color;
2084 HRESULT hr;
2086 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2087 imgl = (IImageList*)himl;
2089 if (0)
2091 /* crashes on native */
2092 IImageList_SetBkColor(imgl, RGB(0, 0, 0), NULL);
2095 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
2096 ok(hr == S_OK, "got 0x%08x\n", hr);
2098 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
2099 ok(hr == S_OK, "got 0x%08x\n", hr);
2101 color = 0xdeadbeef;
2102 hr = IImageList_GetBkColor(imgl, &color);
2103 ok(hr == S_OK, "got 0x%08x\n", hr);
2104 ok(color == CLR_NONE, "got %x\n", color);
2106 IImageList_Release(imgl);
2109 static void test_IImageList_GetImageCount(void)
2111 IImageList *imgl;
2112 HIMAGELIST himl;
2113 int count;
2114 HRESULT hr;
2116 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2117 imgl = (IImageList*)himl;
2119 if (0)
2121 /* crashes on native */
2122 IImageList_GetImageCount(imgl, NULL);
2125 count = -1;
2126 hr = IImageList_GetImageCount(imgl, &count);
2127 ok(hr == S_OK, "got 0x%08x\n", hr);
2128 ok(count == 0, "got %d\n", count);
2130 IImageList_Release(imgl);
2133 static void test_IImageList_GetIconSize(void)
2135 IImageList *imgl;
2136 HIMAGELIST himl;
2137 int cx, cy;
2138 HRESULT hr;
2140 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2141 imgl = (IImageList*)himl;
2143 hr = IImageList_GetIconSize(imgl, NULL, NULL);
2144 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2146 hr = IImageList_GetIconSize(imgl, &cx, NULL);
2147 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2149 hr = IImageList_GetIconSize(imgl, NULL, &cy);
2150 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2152 IImageList_Release(imgl);
2155 START_TEST(imagelist)
2157 ULONG_PTR ctx_cookie;
2158 HANDLE hCtx;
2160 HMODULE hComCtl32 = GetModuleHandleA("comctl32.dll");
2161 pImageList_Create = NULL; /* These are not needed for non-v6.0 tests*/
2162 pImageList_Add = NULL;
2163 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
2164 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
2166 hinst = GetModuleHandleA(NULL);
2168 InitCommonControls();
2170 test_create_destroy();
2171 test_begindrag();
2172 test_hotspot();
2173 test_add_remove();
2174 test_imagecount();
2175 test_DrawIndirect();
2176 test_merge();
2177 test_merge_colors();
2178 test_imagelist_storage();
2179 test_iconsize();
2181 FreeLibrary(hComCtl32);
2183 /* Now perform v6 tests */
2185 if (!load_v6_module(&ctx_cookie, &hCtx))
2186 return;
2188 /* Reload comctl32 */
2189 hComCtl32 = LoadLibraryA("comctl32.dll");
2190 pImageList_Create = (void*)GetProcAddress(hComCtl32, "ImageList_Create");
2191 pImageList_Add = (void*)GetProcAddress(hComCtl32, "ImageList_Add");
2192 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
2193 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
2194 pImageList_CoCreateInstance = (void*)GetProcAddress(hComCtl32, "ImageList_CoCreateInstance");
2195 pHIMAGELIST_QueryInterface = (void*)GetProcAddress(hComCtl32, "HIMAGELIST_QueryInterface");
2197 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2199 /* Do v6.0 tests */
2200 test_ImageList_DrawIndirect();
2201 test_shell_imagelist();
2202 test_iimagelist();
2204 test_hotspot_v6();
2205 test_IImageList_Add_Remove();
2206 test_IImageList_Get_SetImageCount();
2207 test_IImageList_Draw();
2208 test_IImageList_Merge();
2209 test_IImageList_Clone();
2210 test_IImageList_GetBkColor();
2211 test_IImageList_SetBkColor();
2212 test_IImageList_GetImageCount();
2213 test_IImageList_GetIconSize();
2215 CoUninitialize();
2217 unload_v6_module(ctx_cookie, hCtx);