comctl32: Remove the masked background when 32bpp bitmaps have no alpha values.
[wine.git] / dlls / comctl32 / tests / imagelist.c
blobed9b1cc97f200f7aebba76d90758f44fbf861ad3
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"
42 #include "resources.h"
44 #define IMAGELIST_MAGIC (('L' << 8) | 'I')
46 #include "pshpack2.h"
47 /* Header used by ImageList_Read() and ImageList_Write() */
48 typedef struct _ILHEAD
50 USHORT usMagic;
51 USHORT usVersion;
52 WORD cCurImage;
53 WORD cMaxImage;
54 WORD cGrow;
55 WORD cx;
56 WORD cy;
57 COLORREF bkcolor;
58 WORD flags;
59 SHORT ovls[4];
60 } ILHEAD;
61 #include "poppack.h"
63 static HIMAGELIST (WINAPI *pImageList_Create)(int, int, UINT, int, int);
64 static BOOL (WINAPI *pImageList_Destroy)(HIMAGELIST);
65 static int (WINAPI *pImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP);
66 static int (WINAPI *pImageList_AddMasked)(HIMAGELIST, HBITMAP, COLORREF);
67 static BOOL (WINAPI *pImageList_DrawIndirect)(IMAGELISTDRAWPARAMS*);
68 static BOOL (WINAPI *pImageList_SetImageCount)(HIMAGELIST,UINT);
69 static HRESULT (WINAPI *pImageList_CoCreateInstance)(REFCLSID,const IUnknown *,
70 REFIID,void **);
71 static HRESULT (WINAPI *pHIMAGELIST_QueryInterface)(HIMAGELIST,REFIID,void **);
72 static int (WINAPI *pImageList_SetColorTable)(HIMAGELIST,int,int,RGBQUAD*);
73 static DWORD (WINAPI *pImageList_GetFlags)(HIMAGELIST);
74 static BOOL (WINAPI *pImageList_BeginDrag)(HIMAGELIST, int, int, int);
75 static HIMAGELIST (WINAPI *pImageList_GetDragImage)(POINT *, POINT *);
76 static void (WINAPI *pImageList_EndDrag)(void);
77 static INT (WINAPI *pImageList_GetImageCount)(HIMAGELIST);
78 static BOOL (WINAPI *pImageList_SetDragCursorImage)(HIMAGELIST, int, int, int);
79 static BOOL (WINAPI *pImageList_GetIconSize)(HIMAGELIST, int *, int *);
80 static BOOL (WINAPI *pImageList_SetIconSize)(HIMAGELIST, INT, INT);
81 static BOOL (WINAPI *pImageList_Remove)(HIMAGELIST, int);
82 static INT (WINAPI *pImageList_ReplaceIcon)(HIMAGELIST, int, HICON);
83 static BOOL (WINAPI *pImageList_Replace)(HIMAGELIST, int, HBITMAP, HBITMAP);
84 static HIMAGELIST (WINAPI *pImageList_Merge)(HIMAGELIST, int, HIMAGELIST, int, int, int);
85 static BOOL (WINAPI *pImageList_GetImageInfo)(HIMAGELIST, int, IMAGEINFO *);
86 static BOOL (WINAPI *pImageList_Write)(HIMAGELIST, IStream *);
87 static HIMAGELIST (WINAPI *pImageList_Read)(IStream *);
88 static BOOL (WINAPI *pImageList_Copy)(HIMAGELIST, int, HIMAGELIST, int, UINT);
89 static HIMAGELIST (WINAPI *pImageList_LoadImageW)(HINSTANCE, LPCWSTR, int, int, COLORREF, UINT, UINT);
90 static BOOL (WINAPI *pImageList_Draw)(HIMAGELIST,INT,HDC,INT,INT,UINT);
92 static HINSTANCE hinst;
94 /* only used in interactive mode */
95 static void force_redraw(HWND hwnd)
97 if (!winetest_interactive)
98 return;
100 RedrawWindow(hwnd, NULL, 0, RDW_UPDATENOW);
101 Sleep(1000);
104 static BOOL is_v6_test(void)
106 return pHIMAGELIST_QueryInterface != NULL;
109 /* These macros build cursor/bitmap data in 4x4 pixel blocks */
110 #define B(x,y) ((x?0xf0:0)|(y?0xf:0))
111 #define ROW1(a,b,c,d,e,f,g,h) B(a,b),B(c,d),B(e,f),B(g,h)
112 #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), \
113 ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h)
114 #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)
115 #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), \
116 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), \
117 ROW2(a,b,c,d,e,f,g,h,i,j,k,l)
119 static const BYTE empty_bits[48*48/8];
121 static const BYTE icon_bits[32*32/8] =
123 ROW32(0,0,0,0,0,0,0,0),
124 ROW32(0,0,1,1,1,1,0,0),
125 ROW32(0,1,1,1,1,1,1,0),
126 ROW32(0,1,1,0,0,1,1,0),
127 ROW32(0,1,1,0,0,1,1,0),
128 ROW32(0,1,1,1,1,1,1,0),
129 ROW32(0,0,1,1,1,1,0,0),
130 ROW32(0,0,0,0,0,0,0,0)
133 static const BYTE bitmap_bits[48*48/8] =
135 ROW48(0,0,0,0,0,0,0,0,0,0,0,0),
136 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
137 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
138 ROW48(0,1,0,0,0,0,0,0,1,0,1,0),
139 ROW48(0,1,0,0,0,0,0,1,0,0,1,0),
140 ROW48(0,1,0,0,0,0,1,0,0,0,1,0),
141 ROW48(0,1,0,0,0,1,0,0,0,0,1,0),
142 ROW48(0,1,0,0,1,0,0,0,0,0,1,0),
143 ROW48(0,1,0,1,0,0,0,0,0,0,1,0),
144 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
145 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
146 ROW48(0,0,0,0,0,0,0,0,0,0,0,0)
149 static HIMAGELIST createImageList(int cx, int cy)
151 /* Create an ImageList and put an image into it */
152 HIMAGELIST himl = pImageList_Create(cx, cy, ILC_COLOR, 1, 1);
153 HBITMAP hbm = CreateBitmap(48, 48, 1, 1, bitmap_bits);
155 ok(himl != NULL, "Failed to create image list, %d x %d.\n", cx, cy);
156 pImageList_Add(himl, hbm, NULL);
157 DeleteObject(hbm);
158 return himl;
161 static HWND create_window(void)
163 char className[] = "bmwnd";
164 char winName[] = "Test Bitmap";
165 HWND hWnd;
166 static BOOL registered = FALSE;
168 if (!registered)
170 WNDCLASSA cls;
172 cls.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
173 cls.lpfnWndProc = DefWindowProcA;
174 cls.cbClsExtra = 0;
175 cls.cbWndExtra = 0;
176 cls.hInstance = 0;
177 cls.hIcon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
178 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
179 cls.hbrBackground = GetStockObject (WHITE_BRUSH);
180 cls.lpszMenuName = 0;
181 cls.lpszClassName = className;
183 RegisterClassA (&cls);
184 registered = TRUE;
187 /* Setup window */
188 hWnd = CreateWindowA (className, winName,
189 WS_OVERLAPPEDWINDOW ,
190 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
191 0, hinst, 0);
193 if (winetest_interactive)
195 ShowWindow (hWnd, SW_SHOW);
196 force_redraw (hWnd);
199 return hWnd;
202 static HDC show_image(HWND hwnd, HIMAGELIST himl, int idx, int size,
203 LPCSTR loc, BOOL clear)
205 HDC hdc;
207 if (!winetest_interactive || !himl) return NULL;
209 SetWindowTextA(hwnd, loc);
210 hdc = GetDC(hwnd);
211 pImageList_Draw(himl, idx, hdc, 0, 0, ILD_TRANSPARENT);
213 force_redraw(hwnd);
215 if (clear)
217 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
218 ReleaseDC(hwnd, hdc);
219 hdc = NULL;
222 return hdc;
225 /* Useful for checking differences */
226 static void dump_bits(const BYTE *p, const BYTE *q, int size)
228 int i, j;
230 size /= 8;
232 for (i = 0; i < size * 2; i++)
234 printf("|");
235 for (j = 0; j < size; j++)
236 printf("%c%c", p[j] & 0xf0 ? 'X' : ' ', p[j] & 0xf ? 'X' : ' ');
237 printf(" -- ");
238 for (j = 0; j < size; j++)
239 printf("%c%c", q[j] & 0xf0 ? 'X' : ' ', q[j] & 0xf ? 'X' : ' ');
240 printf("|\n");
241 p += size * 4;
242 q += size * 4;
244 printf("\n");
247 static void check_bits(HWND hwnd, HIMAGELIST himl, int idx, int size,
248 const BYTE *checkbits, LPCSTR loc)
250 BYTE bits[100*100/8];
251 COLORREF c;
252 HDC hdc;
253 int x, y, i = -1;
255 if (!winetest_interactive || !himl) return;
257 memset(bits, 0, sizeof(bits));
258 hdc = show_image(hwnd, himl, idx, size, loc, FALSE);
260 c = GetPixel(hdc, 0, 0);
262 for (y = 0; y < size; y ++)
264 for (x = 0; x < size; x++)
266 if (!(x & 0x7)) i++;
267 if (GetPixel(hdc, x, y) != c) bits[i] |= (0x80 >> (x & 0x7));
271 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
272 ReleaseDC(hwnd, hdc);
274 ok (memcmp(bits, checkbits, (size * size)/8) == 0,
275 "%s: bits different\n", loc);
276 if (memcmp(bits, checkbits, (size * size)/8))
277 dump_bits(bits, checkbits, size);
280 static void test_begindrag(void)
282 HIMAGELIST himl = createImageList(7,13);
283 HIMAGELIST drag;
284 BOOL ret;
285 int count;
286 POINT hotspot;
288 count = pImageList_GetImageCount(himl);
289 ok(count > 2, "Tests need an ImageList with more than 2 images\n");
291 /* Two BeginDrag() without EndDrag() in between */
292 ret = pImageList_BeginDrag(himl, 1, 0, 0);
293 drag = pImageList_GetDragImage(NULL, NULL);
294 ok(ret && drag, "ImageList_BeginDrag() failed\n");
295 ret = pImageList_BeginDrag(himl, 0, 3, 5);
296 ok(!ret, "ImageList_BeginDrag() returned TRUE\n");
297 drag = pImageList_GetDragImage(NULL, &hotspot);
298 ok(!!drag, "No active ImageList drag left\n");
299 ok(hotspot.x == 0 && hotspot.y == 0, "New ImageList drag was created\n");
300 pImageList_EndDrag();
301 drag = pImageList_GetDragImage(NULL, NULL);
302 ok(!drag, "ImageList drag was not destroyed\n");
304 /* Invalid image index */
305 pImageList_BeginDrag(himl, 0, 0, 0);
306 ret = pImageList_BeginDrag(himl, count, 3, 5);
307 ok(!ret, "ImageList_BeginDrag() returned TRUE\n");
308 drag = pImageList_GetDragImage(NULL, &hotspot);
309 ok(drag && hotspot.x == 0 && hotspot.y == 0, "Active drag should not have been canceled\n");
310 pImageList_EndDrag();
311 drag = pImageList_GetDragImage(NULL, NULL);
312 ok(!drag, "ImageList drag was not destroyed\n");
313 /* Invalid negative image indexes succeed */
314 ret = pImageList_BeginDrag(himl, -17, 0, 0);
315 drag = pImageList_GetDragImage(NULL, NULL);
316 ok(ret && drag, "ImageList drag was created\n");
317 pImageList_EndDrag();
318 ret = pImageList_BeginDrag(himl, -1, 0, 0);
319 drag = pImageList_GetDragImage(NULL, NULL);
320 ok(ret && drag, "ImageList drag was created\n");
321 pImageList_EndDrag();
322 pImageList_Destroy(himl);
325 static void test_hotspot(void)
327 struct hotspot {
328 int dx;
329 int dy;
332 #define SIZEX1 47
333 #define SIZEY1 31
334 #define SIZEX2 11
335 #define SIZEY2 17
336 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
337 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
338 { 10, 7 },
339 { SIZEX1, SIZEY1 },
340 { -9, -8 },
341 { -7, 35 }
343 int i, j, ret;
344 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
345 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
346 HWND hwnd = create_window();
349 for (i = 0; i < HOTSPOTS_MAX; i++) {
350 for (j = 0; j < HOTSPOTS_MAX; j++) {
351 int dx1 = hotspots[i].dx;
352 int dy1 = hotspots[i].dy;
353 int dx2 = hotspots[j].dx;
354 int dy2 = hotspots[j].dy;
355 int correctx, correcty, newx, newy;
356 char loc[256];
357 HIMAGELIST himlNew;
358 POINT ppt;
360 ret = pImageList_BeginDrag(himl1, 0, dx1, dy1);
361 ok(ret != 0, "BeginDrag failed for { %d, %d }\n", dx1, dy1);
362 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
363 show_image(hwnd, himl1, 0, max(SIZEX1, SIZEY1), loc, TRUE);
365 /* check merging the dragged image with a second image */
366 ret = pImageList_SetDragCursorImage(himl2, 0, dx2, dy2);
367 ok(ret != 0, "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
368 dx1, dy1, dx2, dy2);
369 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
370 show_image(hwnd, himl2, 0, max(SIZEX2, SIZEY2), loc, TRUE);
372 /* check new hotspot, it should be the same like the old one */
373 himlNew = pImageList_GetDragImage(NULL, &ppt);
374 ok(ppt.x == dx1 && ppt.y == dy1,
375 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
376 dx1, dy1, ppt.x, ppt.y);
377 /* check size of new dragged image */
378 pImageList_GetIconSize(himlNew, &newx, &newy);
379 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
380 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
381 ok(newx == correctx && newy == correcty,
382 "Expected drag image size [%d,%d] got [%d,%d]\n",
383 correctx, correcty, newx, newy);
384 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
385 show_image(hwnd, himlNew, 0, max(correctx, correcty), loc, TRUE);
386 pImageList_EndDrag();
389 #undef SIZEX1
390 #undef SIZEY1
391 #undef SIZEX2
392 #undef SIZEY2
393 #undef HOTSPOTS_MAX
394 pImageList_Destroy(himl2);
395 pImageList_Destroy(himl1);
396 DestroyWindow(hwnd);
399 static void test_add_remove(void)
401 HIMAGELIST himl ;
403 HICON hicon1 ;
404 HICON hicon2 ;
405 HICON hicon3 ;
407 /* create an imagelist to play with */
408 himl = pImageList_Create(84, 84, ILC_COLOR16, 0, 3);
409 ok(himl!=0,"failed to create imagelist\n");
411 /* load the icons to add to the image list */
412 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
413 ok(hicon1 != 0, "no hicon1\n");
414 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
415 ok(hicon2 != 0, "no hicon2\n");
416 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
417 ok(hicon3 != 0, "no hicon3\n");
419 /* remove when nothing exists */
420 ok(!pImageList_Remove(himl, 0), "Removed nonexistent icon.\n");
421 /* removing everything from an empty imagelist should succeed */
422 ok(pImageList_Remove(himl, -1), "Removed nonexistent icon\n");
424 /* add three */
425 ok(0 == pImageList_ReplaceIcon(himl, -1, hicon1), "Failed to add icon1.\n");
426 ok(1 == pImageList_ReplaceIcon(himl, -1, hicon2), "Failed to add icon2.\n");
427 ok(2 == pImageList_ReplaceIcon(himl, -1, hicon3), "Failed to add icon3.\n");
429 /* remove an index out of range */
430 ok(!pImageList_Remove(himl, 4711), "removed nonexistent icon\n");
432 /* remove three */
433 ok(pImageList_Remove(himl, 0), "Can't remove 0\n");
434 ok(pImageList_Remove(himl, 0), "Can't remove 0\n");
435 ok(pImageList_Remove(himl, 0), "Can't remove 0\n");
437 /* remove one extra */
438 ok(!pImageList_Remove(himl, 0), "Removed nonexistent icon.\n");
440 /* destroy it */
441 ok(pImageList_Destroy(himl), "Failed to destroy imagelist.\n");
443 ok(-1 == pImageList_ReplaceIcon((HIMAGELIST)0xdeadbeef, -1, hicon1), "Don't crash on bad handle\n");
445 ok(DestroyIcon(hicon1), "Failed to destroy icon 1.\n");
446 ok(DestroyIcon(hicon2), "Failed to destroy icon 2.\n");
447 ok(DestroyIcon(hicon3), "Failed to destroy icon 3.\n");
450 static void test_imagecount(void)
452 HIMAGELIST himl;
454 ok(0 == pImageList_GetImageCount((HIMAGELIST)0xdeadbeef), "don't crash on bad handle\n");
456 if (!pImageList_SetImageCount)
458 win_skip("ImageList_SetImageCount not available\n");
459 return;
462 himl = pImageList_Create(84, 84, ILC_COLOR16, 0, 3);
463 ok(himl != 0, "Failed to create imagelist.\n");
465 ok(pImageList_SetImageCount(himl, 3), "couldn't increase image count\n");
466 ok(pImageList_GetImageCount(himl) == 3, "invalid image count after increase\n");
467 ok(pImageList_SetImageCount(himl, 1), "couldn't decrease image count\n");
468 ok(pImageList_GetImageCount(himl) == 1, "invalid image count after decrease to 1\n");
469 ok(pImageList_SetImageCount(himl, 0), "couldn't decrease image count\n");
470 ok(pImageList_GetImageCount(himl) == 0, "invalid image count after decrease to 0\n");
472 ok(pImageList_Destroy(himl), "Failed to destroy imagelist.\n");
475 static void test_DrawIndirect(void)
477 HIMAGELIST himl;
479 HBITMAP hbm1;
480 HBITMAP hbm2;
481 HBITMAP hbm3;
483 IMAGELISTDRAWPARAMS imldp;
484 HDC hdc;
485 HWND hwndfortest;
487 if (!pImageList_DrawIndirect)
489 win_skip("ImageList_DrawIndirect not available, skipping test\n");
490 return;
493 hwndfortest = create_window();
494 hdc = GetDC(hwndfortest);
495 ok(hdc!=NULL, "couldn't get DC\n");
497 /* create an imagelist to play with */
498 himl = pImageList_Create(48, 48, ILC_COLOR16, 0, 3);
499 ok(himl != 0, "Failed to create imagelist.\n");
501 /* load the icons to add to the image list */
502 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
503 ok(hbm1 != 0, "no bitmap 1\n");
504 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
505 ok(hbm2 != 0, "no bitmap 2\n");
506 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
507 ok(hbm3 != 0, "no bitmap 3\n");
509 /* add three */
510 ok(0 == pImageList_Add(himl, hbm1, 0),"failed to add bitmap 1\n");
511 ok(1 == pImageList_Add(himl, hbm2, 0),"failed to add bitmap 2\n");
513 if (pImageList_SetImageCount)
515 ok(pImageList_SetImageCount(himl,3),"Setimage count failed\n");
516 /*ok(2==ImageList_Add(himl, hbm3, NULL),"failed to add bitmap 3\n"); */
517 ok(pImageList_Replace(himl, 2, hbm3, 0),"failed to replace bitmap 3\n");
520 memset(&imldp, 0, sizeof (imldp));
521 ok(!pImageList_DrawIndirect(&imldp), "zero data succeeded!\n");
522 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
523 ok(!pImageList_DrawIndirect(&imldp), "zero hdc succeeded!\n");
524 imldp.hdcDst = hdc;
525 ok(!pImageList_DrawIndirect(&imldp),"zero himl succeeded!\n");
526 imldp.himl = (HIMAGELIST)0xdeadbeef;
527 ok(!pImageList_DrawIndirect(&imldp),"bad himl succeeded!\n");
528 imldp.himl = himl;
530 force_redraw(hwndfortest);
532 imldp.fStyle = SRCCOPY;
533 imldp.rgbBk = CLR_DEFAULT;
534 imldp.rgbFg = CLR_DEFAULT;
535 imldp.y = 100;
536 imldp.x = 100;
537 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
538 imldp.i ++;
539 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
540 imldp.i ++;
541 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
542 imldp.i ++;
543 ok(!pImageList_DrawIndirect(&imldp),"should fail\n");
545 /* remove three */
546 ok(pImageList_Remove(himl, 0), "removing 1st bitmap\n");
547 ok(pImageList_Remove(himl, 0), "removing 2nd bitmap\n");
548 ok(pImageList_Remove(himl, 0), "removing 3rd bitmap\n");
550 /* destroy it */
551 ok(pImageList_Destroy(himl), "Failed to destroy imagelist.\n");
553 /* bitmaps should not be deleted by the imagelist */
554 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
555 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
556 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
558 ReleaseDC(hwndfortest, hdc);
559 DestroyWindow(hwndfortest);
562 static int get_color_format(HBITMAP bmp)
564 BITMAPINFO bmi;
565 HDC hdc = CreateCompatibleDC(0);
566 HBITMAP hOldBmp = SelectObject(hdc, bmp);
567 int ret;
569 memset(&bmi, 0, sizeof(bmi));
570 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
571 ret = GetDIBits(hdc, bmp, 0, 0, 0, &bmi, DIB_RGB_COLORS);
572 ok(ret, "GetDIBits failed\n");
574 SelectObject(hdc, hOldBmp);
575 DeleteDC(hdc);
576 return bmi.bmiHeader.biBitCount;
579 static void test_merge_colors(void)
581 HIMAGELIST himl[8], hmerge;
582 int sizes[] = { ILC_COLOR, ILC_COLOR | ILC_MASK, ILC_COLOR4, ILC_COLOR8, ILC_COLOR16, ILC_COLOR24, ILC_COLOR32, ILC_COLORDDB };
583 HICON hicon1;
584 IMAGEINFO info;
585 int bpp, i, j;
587 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
588 ok(hicon1 != NULL, "failed to create hicon1\n");
590 for (i = 0; i < 8; i++)
592 himl[i] = pImageList_Create(32, 32, sizes[i], 0, 3);
593 ok(himl[i] != NULL, "failed to create himl[%d]\n", i);
594 ok(0 == pImageList_ReplaceIcon(himl[i], -1, hicon1), "Failed to add icon1 to himl[%d].\n", i);
595 if (i == 0 || i == 1 || i == 7)
597 pImageList_GetImageInfo(himl[i], 0, &info);
598 sizes[i] = get_color_format(info.hbmImage);
601 DestroyIcon(hicon1);
602 for (i = 0; i < 8; i++)
603 for (j = 0; j < 8; j++)
605 hmerge = pImageList_Merge(himl[i], 0, himl[j], 0, 0, 0);
606 ok(hmerge != NULL, "merge himl[%d], himl[%d] failed\n", i, j);
608 pImageList_GetImageInfo(hmerge, 0, &info);
609 bpp = get_color_format(info.hbmImage);
610 /* ILC_COLOR[X] is defined as [X] */
611 if (i == 4 && j == 7)
612 ok(bpp == 16, /* merging ILC_COLOR16 with ILC_COLORDDB seems to be a special case */
613 "wrong biBitCount %d when merging lists %d (%d) and %d (%d)\n", bpp, i, sizes[i], j, sizes[j]);
614 else
615 ok(bpp == (i > j ? sizes[i] : sizes[j]),
616 "wrong biBitCount %d when merging lists %d (%d) and %d (%d)\n", bpp, i, sizes[i], j, sizes[j]);
617 ok(info.hbmMask != 0, "Imagelist merged from %d and %d had no mask\n", i, j);
619 pImageList_Destroy(hmerge);
622 for (i = 0; i < 8; i++)
623 pImageList_Destroy(himl[i]);
626 static void test_merge(void)
628 HIMAGELIST himl1, himl2, hmerge;
629 HICON hicon1;
630 HWND hwnd = create_window();
632 himl1 = pImageList_Create(32, 32, 0, 0, 3);
633 ok(himl1 != NULL,"failed to create himl1\n");
635 himl2 = pImageList_Create(32, 32, 0, 0, 3);
636 ok(himl2 != NULL,"failed to create himl2\n");
638 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
639 ok(hicon1 != NULL, "failed to create hicon1\n");
641 if (!himl1 || !himl2 || !hicon1)
642 return;
644 ok(0 == pImageList_ReplaceIcon(himl2, -1, hicon1), "Failed to add icon1 to himl2.\n");
645 check_bits(hwnd, himl2, 0, 32, icon_bits, "add icon1 to himl2");
647 /* If himl1 has no images, merge still succeeds */
648 hmerge = pImageList_Merge(himl1, -1, himl2, 0, 0, 0);
649 ok(hmerge != NULL, "merge himl1,-1 failed\n");
650 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,-1");
651 pImageList_Destroy(hmerge);
653 hmerge = pImageList_Merge(himl1, 0, himl2, 0, 0, 0);
654 ok(hmerge != NULL,"merge himl1,0 failed\n");
655 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,0");
656 pImageList_Destroy(hmerge);
658 /* Same happens if himl2 is empty */
659 pImageList_Destroy(himl2);
660 himl2 = pImageList_Create(32, 32, 0, 0, 3);
661 ok(himl2 != NULL,"failed to recreate himl2\n");
662 if (!himl2)
663 return;
665 hmerge = pImageList_Merge(himl1, -1, himl2, -1, 0, 0);
666 ok(hmerge != NULL, "merge himl2,-1 failed\n");
667 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,-1");
668 pImageList_Destroy(hmerge);
670 hmerge = pImageList_Merge(himl1, -1, himl2, 0, 0, 0);
671 ok(hmerge != NULL, "merge himl2,0 failed\n");
672 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,0");
673 pImageList_Destroy(hmerge);
675 /* Now try merging an image with itself */
676 ok(0 == pImageList_ReplaceIcon(himl2, -1, hicon1), "Failed to re-add icon1 to himl2.\n");
678 hmerge = pImageList_Merge(himl2, 0, himl2, 0, 0, 0);
679 ok(hmerge != NULL, "merge himl2 with itself failed\n");
680 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2 with itself");
681 pImageList_Destroy(hmerge);
683 /* Try merging 2 different image lists */
684 ok(0 == pImageList_ReplaceIcon(himl1, -1, hicon1), "Failed to add icon1 to himl1.\n");
686 hmerge = pImageList_Merge(himl1, 0, himl2, 0, 0, 0);
687 ok(hmerge != NULL, "merge himl1 with himl2 failed\n");
688 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2");
689 pImageList_Destroy(hmerge);
691 hmerge = pImageList_Merge(himl1, 0, himl2, 0, 8, 16);
692 ok(hmerge != NULL, "merge himl1 with himl2 8,16 failed\n");
693 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2, 8,16");
694 pImageList_Destroy(hmerge);
696 pImageList_Destroy(himl1);
697 pImageList_Destroy(himl2);
698 DestroyIcon(hicon1);
699 DestroyWindow(hwnd);
702 /*********************** imagelist storage test ***************************/
704 #define BMP_CX 48
706 struct memstream
708 IStream IStream_iface;
709 IStream *stream;
712 static struct memstream *impl_from_IStream(IStream *iface)
714 return CONTAINING_RECORD(iface, struct memstream, IStream_iface);
717 static HRESULT STDMETHODCALLTYPE Test_Stream_QueryInterface(IStream *iface, REFIID riid,
718 void **ppvObject)
720 ok(0, "unexpected call\n");
721 return E_NOTIMPL;
724 static ULONG STDMETHODCALLTYPE Test_Stream_AddRef(IStream *iface)
726 ok(0, "unexpected call\n");
727 return 2;
730 static ULONG STDMETHODCALLTYPE Test_Stream_Release(IStream *iface)
732 ok(0, "unexpected call\n");
733 return 1;
736 static HRESULT STDMETHODCALLTYPE Test_Stream_Read(IStream *iface, void *pv, ULONG cb,
737 ULONG *pcbRead)
739 struct memstream *stream = impl_from_IStream(iface);
740 return IStream_Read(stream->stream, pv, cb, pcbRead);
743 static HRESULT STDMETHODCALLTYPE Test_Stream_Write(IStream *iface, const void *pv, ULONG cb,
744 ULONG *pcbWritten)
746 struct memstream *stream = impl_from_IStream(iface);
747 return IStream_Write(stream->stream, pv, cb, pcbWritten);
750 static HRESULT STDMETHODCALLTYPE Test_Stream_Seek(IStream *iface, LARGE_INTEGER offset, DWORD origin,
751 ULARGE_INTEGER *new_pos)
753 struct memstream *stream = impl_from_IStream(iface);
755 if (is_v6_test())
757 ok(origin == STREAM_SEEK_CUR, "Unexpected origin %d.\n", origin);
758 ok(offset.QuadPart == 0, "Unexpected offset %s.\n", wine_dbgstr_longlong(offset.QuadPart));
759 ok(new_pos != NULL, "Unexpected out position pointer.\n");
760 return IStream_Seek(stream->stream, offset, origin, new_pos);
762 else
764 ok(0, "unexpected call\n");
765 return E_NOTIMPL;
769 static HRESULT STDMETHODCALLTYPE Test_Stream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
771 ok(0, "unexpected call\n");
772 return E_NOTIMPL;
775 static HRESULT STDMETHODCALLTYPE Test_Stream_CopyTo(IStream *iface, IStream *pstm,
776 ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead,
777 ULARGE_INTEGER *pcbWritten)
779 ok(0, "unexpected call\n");
780 return E_NOTIMPL;
783 static HRESULT STDMETHODCALLTYPE Test_Stream_Commit(IStream *iface, DWORD grfCommitFlags)
785 ok(0, "unexpected call\n");
786 return E_NOTIMPL;
789 static HRESULT STDMETHODCALLTYPE Test_Stream_Revert(IStream *iface)
791 ok(0, "unexpected call\n");
792 return E_NOTIMPL;
795 static HRESULT STDMETHODCALLTYPE Test_Stream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset,
796 ULARGE_INTEGER cb, DWORD dwLockType)
798 ok(0, "unexpected call\n");
799 return E_NOTIMPL;
802 static HRESULT STDMETHODCALLTYPE Test_Stream_UnlockRegion(IStream *iface, ULARGE_INTEGER libOffset,
803 ULARGE_INTEGER cb, DWORD dwLockType)
805 ok(0, "unexpected call\n");
806 return E_NOTIMPL;
809 static HRESULT STDMETHODCALLTYPE Test_Stream_Stat(IStream *iface, STATSTG *pstatstg,
810 DWORD grfStatFlag)
812 ok(0, "unexpected call\n");
813 return E_NOTIMPL;
816 static HRESULT STDMETHODCALLTYPE Test_Stream_Clone(IStream *iface, IStream **ppstm)
818 ok(0, "unexpected call\n");
819 return E_NOTIMPL;
822 static const IStreamVtbl Test_Stream_Vtbl =
824 Test_Stream_QueryInterface,
825 Test_Stream_AddRef,
826 Test_Stream_Release,
827 Test_Stream_Read,
828 Test_Stream_Write,
829 Test_Stream_Seek,
830 Test_Stream_SetSize,
831 Test_Stream_CopyTo,
832 Test_Stream_Commit,
833 Test_Stream_Revert,
834 Test_Stream_LockRegion,
835 Test_Stream_UnlockRegion,
836 Test_Stream_Stat,
837 Test_Stream_Clone
840 static void init_memstream(struct memstream *stream)
842 HRESULT hr;
844 stream->IStream_iface.lpVtbl = &Test_Stream_Vtbl;
845 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream->stream);
846 ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
849 static void cleanup_memstream(struct memstream *stream)
851 IStream_Release(stream->stream);
854 static INT DIB_GetWidthBytes( int width, int bpp )
856 return ((width * bpp + 31) / 8) & ~3;
859 static ULONG check_bitmap_data(const ILHEAD *header, const char *bm_data,
860 ULONG bm_data_size, const SIZE *bmpsize, INT bpp, const char *comment)
862 const BITMAPFILEHEADER *bmfh = (const BITMAPFILEHEADER *)bm_data;
863 const BITMAPINFOHEADER *bmih = (const BITMAPINFOHEADER *)(bm_data + sizeof(*bmfh));
864 ULONG hdr_size, image_size;
866 hdr_size = sizeof(*bmfh) + sizeof(*bmih);
867 if (bmih->biBitCount <= 8) hdr_size += (1 << bpp) * sizeof(RGBQUAD);
869 ok(bmfh->bfType == (('M' << 8) | 'B'), "wrong bfType 0x%02x\n", bmfh->bfType);
870 ok(bmfh->bfSize == hdr_size, "wrong bfSize 0x%02x\n", bmfh->bfSize);
871 ok(bmfh->bfReserved1 == 0, "wrong bfReserved1 0x%02x\n", bmfh->bfReserved1);
872 ok(bmfh->bfReserved2 == 0, "wrong bfReserved2 0x%02x\n", bmfh->bfReserved2);
873 ok(bmfh->bfOffBits == hdr_size, "wrong bfOffBits 0x%02x\n", bmfh->bfOffBits);
875 ok(bmih->biSize == sizeof(*bmih), "wrong biSize %d\n", bmih->biSize);
876 ok(bmih->biPlanes == 1, "wrong biPlanes %d\n", bmih->biPlanes);
877 ok(bmih->biBitCount == bpp, "wrong biBitCount %d\n", bmih->biBitCount);
879 image_size = DIB_GetWidthBytes(bmih->biWidth, bmih->biBitCount) * bmih->biHeight;
880 ok(bmih->biSizeImage == image_size, "wrong biSizeImage %u\n", bmih->biSizeImage);
881 ok(bmih->biWidth == bmpsize->cx && bmih->biHeight == bmpsize->cy, "Unexpected bitmap size %d x %d, "
882 "expected %d x %d\n", bmih->biWidth, bmih->biHeight, bmpsize->cx, bmpsize->cy);
884 if (0)
886 char fname[256];
887 FILE *f;
888 sprintf(fname, "bmp_%s.bmp", comment);
889 f = fopen(fname, "wb");
890 fwrite(bm_data, 1, bm_data_size, f);
891 fclose(f);
894 return hdr_size + image_size;
897 static BOOL is_v6_header(const ILHEAD *header)
899 return (header->usVersion & 0xff00) == 0x600;
902 static void check_ilhead_data(const ILHEAD *ilh, INT cx, INT cy, INT cur, INT max, INT grow, INT flags)
904 INT grow_aligned;
906 ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
907 ok(ilh->usVersion == 0x101 ||
908 ilh->usVersion == 0x600 || /* WinXP/W2k3 */
909 ilh->usVersion == 0x620, "Unknown usVersion %#x.\n", ilh->usVersion);
910 ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
912 grow = max(grow, 1);
913 grow_aligned = (WORD)(grow + 3) & ~3;
915 if (is_v6_header(ilh))
917 grow = (WORD)(grow + 2 + 3) & ~3;
918 ok(ilh->cGrow == grow || broken(ilh->cGrow == grow_aligned) /* XP/Vista */,
919 "Unexpected cGrow %d, expected %d\n", ilh->cGrow, grow);
921 else
923 ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
924 ok(ilh->cGrow == grow_aligned, "Unexpected cGrow %d, expected %d\n", ilh->cGrow, grow_aligned);
927 ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
928 ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
929 ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
930 ok(ilh->flags == flags || broken(!(ilh->flags & 0xfe) && (flags & 0xfe) == ILC_COLOR4), /* <= w2k */
931 "wrong flags %04x\n", ilh->flags);
932 ok(ilh->ovls[0] == -1, "wrong ovls[0] %04x\n", ilh->ovls[0]);
933 ok(ilh->ovls[1] == -1, "wrong ovls[1] %04x\n", ilh->ovls[1]);
934 ok(ilh->ovls[2] == -1, "wrong ovls[2] %04x\n", ilh->ovls[2]);
935 ok(ilh->ovls[3] == -1, "wrong ovls[3] %04x\n", ilh->ovls[3]);
938 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
940 HDC hdc;
941 BITMAPINFO bmi;
942 HBITMAP hbmp, hbmp_old;
943 HBRUSH hbrush;
944 RECT rc = { 0, 0, cx, cy };
946 hdc = CreateCompatibleDC(0);
948 memset(&bmi, 0, sizeof(bmi));
949 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
950 bmi.bmiHeader.biHeight = cx;
951 bmi.bmiHeader.biWidth = cy;
952 bmi.bmiHeader.biBitCount = 24;
953 bmi.bmiHeader.biPlanes = 1;
954 bmi.bmiHeader.biCompression = BI_RGB;
955 hbmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
957 hbmp_old = SelectObject(hdc, hbmp);
959 hbrush = CreateSolidBrush(color);
960 FillRect(hdc, &rc, hbrush);
961 DeleteObject(hbrush);
963 DrawTextA(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
965 SelectObject(hdc, hbmp_old);
966 DeleteDC(hdc);
968 return hbmp;
971 static inline void imagelist_get_bitmap_size(const ILHEAD *header, SIZE *sz)
973 const int tile_count = 4;
975 if (is_v6_header(header))
977 sz->cx = header->cx;
978 sz->cy = header->cMaxImage * header->cy;
980 else
982 sz->cx = header->cx * tile_count;
983 sz->cy = ((header->cMaxImage + tile_count - 1) / tile_count) * header->cy;
987 /* Grow argument matches what was used when imagelist was created. */
988 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, INT grow,
989 INT flags, const char *comment)
991 INT ret, cxx, cyy, size;
992 struct memstream stream;
993 const ILHEAD *header;
994 LARGE_INTEGER mv;
995 HIMAGELIST himl2;
996 HGLOBAL hglobal;
997 STATSTG stat;
998 char *data;
999 HRESULT hr;
1000 SIZE bmpsize;
1001 BOOL b;
1003 ret = pImageList_GetImageCount(himl);
1004 ok(ret == cur, "%s: expected image count %d got %d\n", comment, cur, ret);
1006 ret = pImageList_GetIconSize(himl, &cxx, &cyy);
1007 ok(ret, "ImageList_GetIconSize failed\n");
1008 ok(cxx == cx, "%s: wrong cx %d (expected %d)\n", comment, cxx, cx);
1009 ok(cyy == cy, "%s: wrong cy %d (expected %d)\n", comment, cyy, cy);
1011 init_memstream(&stream);
1012 b = pImageList_Write(himl, &stream.IStream_iface);
1013 ok(b, "%s: ImageList_Write failed\n", comment);
1015 hr = GetHGlobalFromStream(stream.stream, &hglobal);
1016 ok(hr == S_OK, "%s: Failed to get hglobal, %#x\n", comment, hr);
1018 hr = IStream_Stat(stream.stream, &stat, STATFLAG_NONAME);
1019 ok(hr == S_OK, "Stat() failed, hr %#x.\n", hr);
1021 data = GlobalLock(hglobal);
1023 ok(data != 0, "%s: ImageList_Write didn't write any data\n", comment);
1024 ok(stat.cbSize.LowPart > sizeof(ILHEAD), "%s: ImageList_Write wrote not enough data\n", comment);
1026 header = (const ILHEAD *)data;
1027 check_ilhead_data(header, cx, cy, cur, max, grow, flags);
1028 imagelist_get_bitmap_size(header, &bmpsize);
1029 size = check_bitmap_data(header, data + sizeof(ILHEAD), stat.cbSize.LowPart - sizeof(ILHEAD),
1030 &bmpsize, flags & 0xfe, comment);
1031 if (!is_v6_header(header) && size < stat.cbSize.LowPart - sizeof(ILHEAD)) /* mask is present */
1033 ok( flags & ILC_MASK, "%s: extra data %u/%u but mask not expected\n", comment, stat.cbSize.LowPart, size );
1034 check_bitmap_data(header, data + sizeof(ILHEAD) + size, stat.cbSize.LowPart - sizeof(ILHEAD) - size,
1035 &bmpsize, 1, comment);
1038 /* rewind and reconstruct from stream */
1039 mv.QuadPart = 0;
1040 IStream_Seek(stream.stream, mv, STREAM_SEEK_SET, NULL);
1041 himl2 = pImageList_Read(&stream.IStream_iface);
1042 ok(himl2 != NULL, "%s: Failed to deserialize imagelist\n", comment);
1043 pImageList_Destroy(himl2);
1045 GlobalUnlock(hglobal);
1046 cleanup_memstream(&stream);
1049 static void image_list_add_bitmap(HIMAGELIST himl, BYTE grey, int i)
1051 char comment[16];
1052 HBITMAP hbm;
1053 int ret;
1055 sprintf(comment, "%d", i);
1056 hbm = create_bitmap(BMP_CX, BMP_CX, RGB(grey, grey, grey), comment);
1057 ret = pImageList_Add(himl, hbm, NULL);
1058 ok(ret != -1, "Failed to add image to imagelist.\n");
1059 DeleteObject(hbm);
1062 static void image_list_init(HIMAGELIST himl, INT grow)
1064 unsigned int i;
1065 static const struct test_data
1067 BYTE grey;
1068 INT cx, cy, cur, max, bpp;
1069 const char *comment;
1070 } td[] =
1072 { 255, BMP_CX, BMP_CX, 1, 2, 24, "total 1" },
1073 { 170, BMP_CX, BMP_CX, 2, 7, 24, "total 2" },
1074 { 85, BMP_CX, BMP_CX, 3, 7, 24, "total 3" },
1075 { 0, BMP_CX, BMP_CX, 4, 7, 24, "total 4" },
1076 { 0, BMP_CX, BMP_CX, 5, 7, 24, "total 5" },
1077 { 85, BMP_CX, BMP_CX, 6, 7, 24, "total 6" },
1078 { 170, BMP_CX, BMP_CX, 7, 12, 24, "total 7" },
1079 { 255, BMP_CX, BMP_CX, 8, 12, 24, "total 8" },
1080 { 255, BMP_CX, BMP_CX, 9, 12, 24, "total 9" },
1081 { 170, BMP_CX, BMP_CX, 10, 12, 24, "total 10" },
1082 { 85, BMP_CX, BMP_CX, 11, 12, 24, "total 11" },
1083 { 0, BMP_CX, BMP_CX, 12, 17, 24, "total 12" },
1084 { 0, BMP_CX, BMP_CX, 13, 17, 24, "total 13" },
1085 { 85, BMP_CX, BMP_CX, 14, 17, 24, "total 14" },
1086 { 170, BMP_CX, BMP_CX, 15, 17, 24, "total 15" },
1087 { 255, BMP_CX, BMP_CX, 16, 17, 24, "total 16" },
1088 { 255, BMP_CX, BMP_CX, 17, 22, 24, "total 17" },
1089 { 170, BMP_CX, BMP_CX, 18, 22, 24, "total 18" },
1090 { 85, BMP_CX, BMP_CX, 19, 22, 24, "total 19" },
1091 { 0, BMP_CX, BMP_CX, 20, 22, 24, "total 20" },
1092 { 0, BMP_CX, BMP_CX, 21, 22, 24, "total 21" },
1093 { 85, BMP_CX, BMP_CX, 22, 27, 24, "total 22" },
1094 { 170, BMP_CX, BMP_CX, 23, 27, 24, "total 23" },
1095 { 255, BMP_CX, BMP_CX, 24, 27, 24, "total 24" }
1098 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, grow, ILC_COLOR24, "total 0");
1100 for (i = 0; i < ARRAY_SIZE(td); i++)
1102 image_list_add_bitmap(himl, td[i].grey, i + 1);
1103 check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, grow, td[i].bpp, td[i].comment);
1107 static void test_imagelist_storage(void)
1109 HIMAGELIST himl;
1110 INT ret, grow;
1111 HBITMAP hbm;
1112 HICON icon;
1114 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
1115 ok(himl != 0, "ImageList_Create failed\n");
1117 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 1, ILC_COLOR24, "empty");
1119 image_list_init(himl, 1);
1120 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, 1, ILC_COLOR24, "orig");
1122 ret = pImageList_Remove(himl, 4);
1123 ok(ret, "ImageList_Remove failed\n");
1124 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, 1, ILC_COLOR24, "1");
1126 ret = pImageList_Remove(himl, 5);
1127 ok(ret, "ImageList_Remove failed\n");
1128 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, 1, ILC_COLOR24, "2");
1130 ret = pImageList_Remove(himl, 6);
1131 ok(ret, "ImageList_Remove failed\n");
1132 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, 1, ILC_COLOR24, "3");
1134 ret = pImageList_Remove(himl, 7);
1135 ok(ret, "ImageList_Remove failed\n");
1136 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 1, ILC_COLOR24, "4");
1138 ret = pImageList_Remove(himl, -2);
1139 ok(!ret, "ImageList_Remove(-2) should fail\n");
1140 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 1, ILC_COLOR24, "5");
1142 ret = pImageList_Remove(himl, 20);
1143 ok(!ret, "ImageList_Remove(20) should fail\n");
1144 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 1, ILC_COLOR24, "6");
1146 ret = pImageList_Remove(himl, -1);
1147 ok(ret, "ImageList_Remove(-1) failed\n");
1148 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, 1, ILC_COLOR24, "7");
1150 ret = pImageList_Destroy(himl);
1151 ok(ret, "ImageList_Destroy failed\n");
1153 /* test ImageList_Create storage allocation */
1155 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 0, 32);
1156 ok(himl != 0, "ImageList_Create failed\n");
1157 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 32, ILC_COLOR24, "init 0 grow 32");
1158 hbm = create_bitmap(BMP_CX * 9, BMP_CX, 0, "9");
1159 ret = pImageList_Add(himl, hbm, NULL);
1160 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1161 check_iml_data(himl, BMP_CX, BMP_CX, 1, 34, 32, ILC_COLOR24, "add 1 x 9");
1162 DeleteObject(hbm);
1163 ret = pImageList_Destroy(himl);
1164 ok(ret, "ImageList_Destroy failed\n");
1166 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 4);
1167 ok(himl != 0, "ImageList_Create failed\n");
1168 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, ILC_COLOR24, "init 4 grow 4");
1169 hbm = create_bitmap(BMP_CX, BMP_CX * 9, 0, "9");
1170 ret = pImageList_Add(himl, hbm, NULL);
1171 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1172 check_iml_data(himl, BMP_CX, BMP_CX, 9, 15, 4, ILC_COLOR24, "add 9 x 1");
1173 ret = pImageList_Add(himl, hbm, NULL);
1174 ok(ret == 9, "ImageList_Add returned %d, expected 9\n", ret);
1175 check_iml_data(himl, BMP_CX, BMP_CX, 18, 25, 4, ILC_COLOR24, "add 9 x 1");
1176 DeleteObject(hbm);
1177 ret = pImageList_Destroy(himl);
1178 ok(ret, "ImageList_Destroy failed\n");
1180 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 207, 209);
1181 ok(himl != 0, "ImageList_Create failed\n");
1182 check_iml_data(himl, BMP_CX, BMP_CX, 0, 208, 209, ILC_COLOR24, "init 207 grow 209");
1183 ret = pImageList_Destroy(himl);
1184 ok(ret, "ImageList_Destroy failed\n");
1186 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 209, 207);
1187 ok(himl != 0, "ImageList_Create failed\n");
1188 check_iml_data(himl, BMP_CX, BMP_CX, 0, 210, 207, ILC_COLOR24, "init 209 grow 207");
1189 ret = pImageList_Destroy(himl);
1190 ok(ret, "ImageList_Destroy failed\n");
1192 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 14, 4);
1193 ok(himl != 0, "ImageList_Create failed\n");
1194 check_iml_data(himl, BMP_CX, BMP_CX, 0, 15, 4, ILC_COLOR24, "init 14 grow 4");
1195 ret = pImageList_Destroy(himl);
1196 ok(ret, "ImageList_Destroy failed\n");
1198 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 5, 9);
1199 ok(himl != 0, "ImageList_Create failed\n");
1200 check_iml_data(himl, BMP_CX, BMP_CX, 0, 6, 9, ILC_COLOR24, "init 5 grow 9");
1201 ret = pImageList_Destroy(himl);
1202 ok(ret, "ImageList_Destroy failed\n");
1204 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 9, 5);
1205 ok(himl != 0, "ImageList_Create failed\n");
1206 check_iml_data(himl, BMP_CX, BMP_CX, 0, 10, 5, ILC_COLOR24, "init 9 grow 5");
1207 ret = pImageList_Destroy(himl);
1208 ok(ret, "ImageList_Destroy failed\n");
1210 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 2, 4);
1211 ok(himl != 0, "ImageList_Create failed\n");
1212 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, ILC_COLOR24, "init 2 grow 4");
1213 ret = pImageList_Destroy(himl);
1214 ok(ret, "ImageList_Destroy failed\n");
1216 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 2);
1217 ok(himl != 0, "ImageList_Create failed\n");
1218 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR24, "init 4 grow 2");
1219 ret = pImageList_Destroy(himl);
1220 ok(ret, "ImageList_Destroy failed\n");
1222 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR8, 4, 2);
1223 ok(himl != 0, "ImageList_Create failed\n");
1224 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR8, "bpp 8");
1225 ret = pImageList_Destroy(himl);
1226 ok(ret, "ImageList_Destroy failed\n");
1228 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4, 4, 2);
1229 ok(himl != 0, "ImageList_Create failed\n");
1230 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR4, "bpp 4");
1231 ret = pImageList_Destroy(himl);
1232 ok(ret, "ImageList_Destroy failed\n");
1234 himl = pImageList_Create(BMP_CX, BMP_CX, 0, 4, 2);
1235 ok(himl != 0, "ImageList_Create failed\n");
1236 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR4, "bpp default");
1237 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1238 ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1239 ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1240 DestroyIcon( icon );
1241 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 2, ILC_COLOR4, "bpp default");
1242 ret = pImageList_Destroy(himl);
1243 ok(ret, "ImageList_Destroy failed\n");
1245 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24|ILC_MASK, 4, 2);
1246 ok(himl != 0, "ImageList_Create failed\n");
1247 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR24|ILC_MASK, "bpp 24 + mask");
1248 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1249 ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1250 ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1251 DestroyIcon( icon );
1252 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 2, ILC_COLOR24|ILC_MASK, "bpp 24 + mask");
1253 ret = pImageList_Destroy(himl);
1254 ok(ret, "ImageList_Destroy failed\n");
1256 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 4, 2);
1257 ok(himl != 0, "ImageList_Create failed\n");
1258 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR4|ILC_MASK, "bpp 4 + mask");
1259 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1260 ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1261 ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1262 DestroyIcon( icon );
1263 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 2, ILC_COLOR4|ILC_MASK, "bpp 4 + mask");
1264 ret = pImageList_Destroy(himl);
1265 ok(ret, "ImageList_Destroy failed\n");
1267 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 99);
1268 ok(himl != 0, "ImageList_Create failed\n");
1269 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99");
1270 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1271 ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1272 ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1273 check_iml_data(himl, BMP_CX, BMP_CX, 2, 3, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 2 icons");
1274 ok( pImageList_ReplaceIcon(himl, -1, icon) == 2, "Failed to add icon\n");
1275 DestroyIcon( icon );
1276 check_iml_data(himl, BMP_CX, BMP_CX, 3, 104, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 3 icons");
1277 ok( pImageList_Remove(himl, -1) == TRUE, "Failed to remove icon.\n");
1278 check_iml_data(himl, BMP_CX, BMP_CX, 0, 100, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 empty");
1279 ok( pImageList_SetImageCount(himl, 22) == TRUE, "Failed to set image count.\n");
1280 check_iml_data(himl, BMP_CX, BMP_CX, 22, 23, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 set count 22");
1281 ok( pImageList_SetImageCount(himl, 0) == TRUE, "Failed to set image count.\n");
1282 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 set count 0");
1283 ok( pImageList_SetImageCount(himl, 42) == TRUE, "Failed to set image count.\n");
1284 check_iml_data(himl, BMP_CX, BMP_CX, 42, 43, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 set count 42");
1285 ret = pImageList_Destroy(himl);
1286 ok(ret, "ImageList_Destroy failed\n");
1288 for (grow = 1; grow <= 16; grow++)
1290 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, grow);
1291 ok(himl != 0, "ImageList_Create failed\n");
1292 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, grow, ILC_COLOR4|ILC_MASK, "grow test");
1293 ret = pImageList_Destroy(himl);
1294 ok(ret, "ImageList_Destroy failed\n");
1297 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, -20);
1298 ok(himl != 0, "ImageList_Create failed\n");
1299 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, -20, ILC_COLOR4|ILC_MASK, "init 2 grow -20");
1300 ret = pImageList_Destroy(himl);
1301 ok(ret, "ImageList_Destroy failed\n");
1303 /* Version 6 implementation hangs on large grow values. */
1304 if (!is_v6_test())
1306 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65536+12);
1307 ok(himl != 0, "ImageList_Create failed\n");
1308 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 65536+12, ILC_COLOR4|ILC_MASK, "init 2 grow 65536+12");
1309 ret = pImageList_Destroy(himl);
1310 ok(ret, "ImageList_Destroy failed\n");
1312 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65535);
1313 ok(himl != 0, "ImageList_Create failed\n");
1314 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 65535, ILC_COLOR4|ILC_MASK, "init 2 grow 65535");
1315 ret = pImageList_Destroy(himl);
1316 ok(ret, "ImageList_Destroy failed\n");
1320 static void test_shell_imagelist(void)
1322 HRESULT (WINAPI *pSHGetImageList)(INT, REFIID, void**);
1323 IImageList *iml = NULL;
1324 HMODULE hShell32;
1325 HRESULT hr;
1326 int out = 0;
1327 RECT rect;
1328 int cx, cy;
1330 /* Try to load function from shell32 */
1331 hShell32 = LoadLibraryA("shell32.dll");
1332 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1334 if (!pSHGetImageList)
1336 win_skip("SHGetImageList not available, skipping test\n");
1337 FreeLibrary(hShell32);
1338 return;
1341 /* Get system image list */
1342 hr = pSHGetImageList(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1343 ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1345 if (hr != S_OK) {
1346 FreeLibrary(hShell32);
1347 return;
1350 IImageList_GetImageCount(iml, &out);
1351 ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1353 /* Fetch the small icon size */
1354 cx = GetSystemMetrics(SM_CXSMICON);
1355 cy = GetSystemMetrics(SM_CYSMICON);
1357 /* Check icon size matches */
1358 IImageList_GetImageRect(iml, 0, &rect);
1359 ok(((rect.right == cx) && (rect.bottom == cy)),
1360 "IImageList_GetImageRect returned r:%d,b:%d\n",
1361 rect.right, rect.bottom);
1363 IImageList_Release(iml);
1364 FreeLibrary(hShell32);
1367 static HBITMAP create_test_bitmap(HDC hdc, UINT width, UINT height, WORD bpp, const UINT32 *bits)
1369 HBITMAP hBitmap;
1370 UINT32 *buffer = NULL;
1371 UINT stride = ((width * bpp + 31) >> 3) & ~3;
1372 BITMAPINFO bitmapInfo = { { sizeof(BITMAPINFOHEADER), width, - height, 1, bpp, BI_RGB, 0, 0, 0, 0, 0 } };
1374 hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1375 ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1377 if(!hBitmap || !buffer)
1379 DeleteObject(hBitmap);
1380 return NULL;
1383 memcpy(buffer, bits, stride * height);
1385 return hBitmap;
1388 static BOOL colour_match(UINT32 x, UINT32 y)
1390 const INT32 tolerance = 8;
1392 const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1393 const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1394 const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1395 const INT32 da = abs((INT32)((x & 0xFF000000) >> 24) - (INT32)((y & 0xFF000000) >> 24));
1397 return (dr <= tolerance && dg <= tolerance && db <= tolerance && da <= tolerance);
1400 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1401 UINT32 expected, int line)
1403 bits[0] = 0xFFFFFFFF;
1404 pImageList_DrawIndirect(ildp);
1405 ok(colour_match(bits[0], expected),
1406 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1407 bits[0], expected, line);
1411 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1412 UINT fStyle, UINT32 expected, int line)
1414 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1415 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1416 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1419 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1420 DWORD dwRop, UINT32 expected, int line)
1422 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1423 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1424 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1427 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1428 UINT fState, DWORD Frame, UINT32 expected, int line)
1430 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1431 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1432 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1435 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1436 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1437 UINT32 broken_expected, int line)
1439 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1440 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1441 bits[0] = 0xFFFFFFFF;
1442 pImageList_DrawIndirect(&ildp);
1443 ok(colour_match(bits[0], expected) ||
1444 broken(colour_match(bits[0], broken_expected)),
1445 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1446 bits[0], expected, line);
1449 static void check_ImageList_DrawIndirect_grayscale(HDC hdc, HIMAGELIST himl, UINT32 *dst_bits, const UINT32 *bitmap_bits,
1450 int index, UINT width, UINT height, int line)
1452 int i;
1453 BOOL has_alpha = FALSE;
1454 IMAGELISTDRAWPARAMS ildp = { sizeof(IMAGELISTDRAWPARAMS), himl, index, hdc,
1455 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL, 0, ILS_SATURATE, 0, 0x00000000 };
1456 memset(dst_bits, 0, width * height * sizeof(*dst_bits));
1457 pImageList_DrawIndirect(&ildp);
1459 for (i = 0; i < width * height; i++)
1460 if ((has_alpha = ((bitmap_bits[i] & 0xFF000000) != 0))) break;
1462 for (i = 0; i < width * height; i++)
1464 UINT32 expected, expected_winxp;
1465 UINT32 red = (bitmap_bits[i] & 0x00FF0000) >> 16;
1466 UINT32 green = (bitmap_bits[i] & 0x0000FF00) >> 8;
1467 UINT32 blue = (bitmap_bits[i] & 0x000000FF) >> 0;
1468 UINT32 gray = (red * 299 + green * 587 + blue * 114 + 500) / 1000;
1469 UINT32 gray_winxp = (red + green + blue) / 3;
1470 if (has_alpha)
1472 UINT32 alpha = (bitmap_bits[i] & 0xFF000000) >> 24;
1473 gray = gray * alpha / 0xff * alpha / 0xff;
1474 gray_winxp = gray_winxp * alpha / 0xff * 0x96 / 0xff;
1475 expected = (alpha << 24) | (gray << 16) | (gray << 8) | gray;
1476 expected_winxp = ((alpha * 0x96 / 0xff) << 24) | (gray_winxp << 16) | (gray_winxp << 8) | gray_winxp;
1478 else
1480 expected = ((UINT32)0xFF << 24) | (gray << 16) | (gray << 8) | gray;
1481 expected_winxp = (gray_winxp << 16) | (gray_winxp << 8) | gray_winxp;
1484 ok(colour_match(dst_bits[i], expected) || broken(colour_match(dst_bits[i], expected_winxp)),
1485 "ImageList_DrawIndirect: got Pixel(%d,%d) %08X, Expected a close match to %08X from line %d\n",
1486 i % width, i / width, dst_bits[i], expected, line);
1490 static void test_ImageList_DrawIndirect(void)
1492 const UINT32 bits_image[] = { 0x00ABCDEF, 0x00ABCDEF };
1493 const UINT32 bits_alpha[] = { 0x89ABCDEF, 0x89ABCDEF };
1494 const UINT32 bits_transparent[] = { 0x00ABCDEF, 0x89ABCDEF };
1496 const UINT32 bits_4x4[] = { 0x00ABCDEF, 0x89ABCDEF, 0xFFABCDEF, 0xFEDCBA98,
1497 0x00345678, 0x12345678, 0xFF345678, 0x87654321,
1498 0x00987654, 0xBA987654, 0xFF987654, 0x456789AB,
1499 0x00000000, 0xFF000000, 0xFFFFFFFF, 0x00FFFFFF };
1501 HIMAGELIST himl = NULL;
1502 int ret;
1503 HDC hdcDst = NULL;
1504 HBITMAP hbmOld = NULL, hbmDst = NULL;
1505 HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1506 HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL, hbm4x4 = NULL;
1507 int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1508 UINT32 *bits = 0;
1509 UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1510 IImageList *imgl;
1511 DWORD flags;
1512 HRESULT hr;
1514 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1515 0, 0, 0, 0, 0}};
1517 hdcDst = CreateCompatibleDC(0);
1518 ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1519 if (!hdcDst)
1520 return;
1522 hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1523 ok(hbmMask != 0, "CreateBitmap failed\n");
1525 hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1526 ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1528 himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1529 ok(himl != 0, "ImageList_Create failed\n");
1531 hr = pHIMAGELIST_QueryInterface(himl, &IID_IImageList, (void **) &imgl);
1532 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
1534 /* Add a no-alpha image */
1535 hbmImage = create_test_bitmap(hdcDst, 2, 1, 32, bits_image);
1536 ok(hbmImage != NULL, "Failed to create test bitmap.\n");
1538 iImage = pImageList_Add(himl, hbmImage, hbmMask);
1539 ok(iImage != -1, "ImageList_Add failed\n");
1541 hr = IImageList_GetItemFlags(imgl, 1000, &flags);
1542 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
1544 hr = IImageList_GetItemFlags(imgl, 1000, NULL);
1545 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
1547 hr = IImageList_GetItemFlags(imgl, iImage, &flags);
1548 ok(hr == S_OK, "Failed to get item flags, hr %#x.\n", hr);
1549 ok(!flags, "Unexpected flags %#x.\n", flags);
1551 /* Add an alpha image */
1552 hbmAlphaImage = create_test_bitmap(hdcDst, 2, 1, 32, bits_alpha);
1553 ok(hbmAlphaImage != NULL, "Failed to create test bitmap.\n");
1555 iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1556 ok(iAlphaImage != -1, "ImageList_Add failed\n");
1558 hr = IImageList_GetItemFlags(imgl, iAlphaImage, &flags);
1559 ok(hr == S_OK, "Failed to get item flags, hr %#x.\n", hr);
1560 ok(flags & ILIF_ALPHA, "Unexpected flags %#x.\n", flags);
1562 /* Add a transparent alpha image */
1563 hbmTransparentImage = create_test_bitmap(hdcDst, 2, 1, 32, bits_transparent);
1564 ok(hbmTransparentImage != NULL, "Failed to create test bitmap.\n");
1566 iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1567 ok(iTransparentImage != -1, "ImageList_Add failed\n");
1569 hr = IImageList_GetItemFlags(imgl, iTransparentImage, &flags);
1570 ok(hr == S_OK, "Failed to get item flags, hr %#x.\n", hr);
1571 ok(flags & ILIF_ALPHA, "Unexpected flags %#x.\n", flags);
1573 /* 32-bit Tests */
1574 bitmapInfo.bmiHeader.biBitCount = 32;
1575 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1576 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1577 hbmOld = SelectObject(hdcDst, hbmDst);
1579 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1580 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1581 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1582 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1583 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1585 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0xFFD3E5F7, __LINE__);
1586 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0xFFD3E5F7, __LINE__);
1588 /* broken on winxp */
1589 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0xFFE8F1FA, 0xFFD4D9DD, __LINE__);
1590 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0xFFE8F1FA, 0xFFB4BDC4, __LINE__);
1592 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0xFFD3E5F7, __LINE__);
1593 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0xFFD3E5F7, __LINE__);
1595 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x895D6F81, __LINE__);
1596 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, ILS_ALPHA, 127, 0xFFE9F2FB, 0xFFAEB7C0, __LINE__);
1597 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, ILS_SATURATE, 0, 0xFFAFAFAF, 0xFFF0F0F0, __LINE__);
1599 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0xFFFFFFFF, __LINE__);
1601 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1602 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0xFF543210, __LINE__);
1604 /* ILD_ROP is ignored when the image has an alpha channel */
1605 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0xFFD3E5F7, __LINE__);
1606 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0xFFD3E5F7, __LINE__);
1608 check_ImageList_DrawIndirect_grayscale(hdcDst, himl, bits, bits_image, iImage, 2, 1, __LINE__);
1609 check_ImageList_DrawIndirect_grayscale(hdcDst, himl, bits, bits_alpha, iAlphaImage, 2, 1, __LINE__);
1610 check_ImageList_DrawIndirect_grayscale(hdcDst, himl, bits, bits_transparent, iTransparentImage, 2, 1, __LINE__);
1612 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, 0xFFABCDEF, __LINE__);
1613 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, 0xFFABCDEF, __LINE__);
1615 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0xFFD5E6F7, __LINE__);
1616 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0xFFE9F2FB, 0xFFAEB7C0, __LINE__);
1617 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0xFFD3E5F7, __LINE__);
1619 /* 4x4 bitmap tests */
1620 SelectObject(hdcDst, hbmOld);
1621 DeleteObject(hbmDst);
1622 bitmapInfo.bmiHeader.biWidth = 4;
1623 bitmapInfo.bmiHeader.biHeight = -4;
1624 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1625 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1626 SelectObject(hdcDst, hbmDst);
1628 hbm4x4 = create_test_bitmap(hdcDst, 4, 4, 32, bits_4x4);
1629 ok(hbm4x4 != NULL, "Failed to create a test bitmap.\n");
1631 ret = pImageList_SetIconSize(himl, 4, 4);
1632 ok(ret, "ImageList_SetIconSize failed\n");
1634 ret = pImageList_Add(himl, hbm4x4, NULL);
1635 ok(ret != -1, "ImageList_Add failed\n");
1637 check_ImageList_DrawIndirect_grayscale(hdcDst, himl, bits, bits_4x4, 0, 4, 4, __LINE__);
1639 if(hbmOld)
1640 SelectObject(hdcDst, hbmOld);
1641 if(hbmDst)
1642 DeleteObject(hbmDst);
1644 DeleteDC(hdcDst);
1646 if(hbmMask)
1647 DeleteObject(hbmMask);
1648 if(hbmInverseMask)
1649 DeleteObject(hbmInverseMask);
1651 if(hbmImage)
1652 DeleteObject(hbmImage);
1653 if(hbmAlphaImage)
1654 DeleteObject(hbmAlphaImage);
1655 if(hbmTransparentImage)
1656 DeleteObject(hbmTransparentImage);
1657 if(hbm4x4)
1658 DeleteObject(hbm4x4);
1660 if(himl)
1662 ret = pImageList_Destroy(himl);
1663 ok(ret, "ImageList_Destroy failed\n");
1667 static void test_iimagelist(void)
1669 IImageList *imgl, *imgl2;
1670 IImageList2 *imagelist;
1671 HIMAGELIST himl;
1672 HRESULT hr;
1673 ULONG ret;
1675 if (!pHIMAGELIST_QueryInterface)
1677 win_skip("XP imagelist functions not available\n");
1678 return;
1681 /* test reference counting on destruction */
1682 imgl = (IImageList*)createImageList(32, 32);
1683 ret = IImageList_AddRef(imgl);
1684 ok(ret == 2, "Expected 2, got %d\n", ret);
1685 ret = pImageList_Destroy((HIMAGELIST)imgl);
1686 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1687 ret = pImageList_Destroy((HIMAGELIST)imgl);
1688 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1689 ret = pImageList_Destroy((HIMAGELIST)imgl);
1690 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1692 imgl = (IImageList*)createImageList(32, 32);
1693 ret = IImageList_AddRef(imgl);
1694 ok(ret == 2, "Expected 2, got %d\n", ret);
1695 ret = pImageList_Destroy((HIMAGELIST)imgl);
1696 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1697 ret = IImageList_Release(imgl);
1698 ok(ret == 0, "Expected 0, got %d\n", ret);
1699 ret = pImageList_Destroy((HIMAGELIST)imgl);
1700 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1702 /* ref counting, HIMAGELIST_QueryInterface adds a reference */
1703 imgl = (IImageList*)createImageList(32, 32);
1704 hr = pHIMAGELIST_QueryInterface((HIMAGELIST)imgl, &IID_IImageList, (void**)&imgl2);
1705 ok(hr == S_OK, "got 0x%08x\n", hr);
1706 ok(imgl2 == imgl, "got different pointer\n");
1707 ret = IImageList_Release(imgl);
1708 ok(ret == 1, "got %u\n", ret);
1709 IImageList_Release(imgl);
1711 if (!pImageList_CoCreateInstance)
1713 win_skip("Vista imagelist functions not available\n");
1714 return;
1717 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1718 ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
1720 if (hr == S_OK)
1721 IImageList_Release(imgl);
1723 himl = createImageList(32, 32);
1725 if (!himl)
1726 return;
1728 hr = pHIMAGELIST_QueryInterface(himl, &IID_IImageList, (void **) &imgl);
1729 ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
1731 if (hr == S_OK)
1732 IImageList_Release(imgl);
1734 pImageList_Destroy(himl);
1736 /* IImageList2 */
1737 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList2, (void**)&imagelist);
1738 if (hr != S_OK)
1740 win_skip("IImageList2 is not supported.\n");
1741 return;
1743 ok(hr == S_OK, "got 0x%08x\n", hr);
1744 IImageList2_Release(imagelist);
1747 static void test_IImageList_Add_Remove(void)
1749 IImageList *imgl;
1750 HIMAGELIST himl;
1751 HRESULT hr;
1753 HICON hicon1;
1754 HICON hicon2;
1755 HICON hicon3;
1757 int ret;
1759 /* create an imagelist to play with */
1760 himl = pImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1761 ok(himl != 0,"failed to create imagelist\n");
1763 imgl = (IImageList *) himl;
1765 /* load the icons to add to the image list */
1766 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1767 ok(hicon1 != 0, "no hicon1\n");
1768 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1769 ok(hicon2 != 0, "no hicon2\n");
1770 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1771 ok(hicon3 != 0, "no hicon3\n");
1773 /* remove when nothing exists */
1774 hr = IImageList_Remove(imgl, 0);
1775 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1777 /* removing everything from an empty imagelist should succeed */
1778 hr = IImageList_Remove(imgl, -1);
1779 ok(hr == S_OK, "removed nonexistent icon\n");
1781 /* add three */
1782 ret = -1;
1783 ok( IImageList_ReplaceIcon(imgl, -1, hicon1, &ret) == S_OK && (ret == 0),"failed to add icon1\n");
1784 ret = -1;
1785 ok( IImageList_ReplaceIcon(imgl, -1, hicon2, &ret) == S_OK && (ret == 1),"failed to add icon2\n");
1786 ret = -1;
1787 ok( IImageList_ReplaceIcon(imgl, -1, hicon3, &ret) == S_OK && (ret == 2),"failed to add icon3\n");
1789 /* remove an index out of range */
1790 ok( IImageList_Remove(imgl, 4711) == E_INVALIDARG, "got 0x%08x\n", hr);
1792 /* remove three */
1793 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1794 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1795 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1797 /* remove one extra */
1798 ok( IImageList_Remove(imgl, 0) == E_INVALIDARG, "got 0x%08x\n", hr);
1800 IImageList_Release(imgl);
1801 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1802 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1803 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1806 static void test_IImageList_Get_SetImageCount(void)
1808 IImageList *imgl;
1809 HIMAGELIST himl;
1810 HRESULT hr;
1811 INT ret;
1813 /* create an imagelist to play with */
1814 himl = pImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1815 ok(himl != 0,"failed to create imagelist\n");
1817 imgl = (IImageList *) himl;
1819 /* check SetImageCount/GetImageCount */
1820 hr = IImageList_SetImageCount(imgl, 3);
1821 ok(hr == S_OK, "got 0x%08x\n", hr);
1822 ret = 0;
1823 hr = IImageList_GetImageCount(imgl, &ret);
1824 ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
1825 hr = IImageList_SetImageCount(imgl, 1);
1826 ok(hr == S_OK, "got 0x%08x\n", hr);
1827 ret = 0;
1828 hr = IImageList_GetImageCount(imgl, &ret);
1829 ok(hr == S_OK && ret == 1, "invalid image count after decrease to 1\n");
1830 hr = IImageList_SetImageCount(imgl, 0);
1831 ok(hr == S_OK, "got 0x%08x\n", hr);
1832 ret = -1;
1833 hr = IImageList_GetImageCount(imgl, &ret);
1834 ok(hr == S_OK && ret == 0, "invalid image count after decrease to 0\n");
1836 IImageList_Release(imgl);
1839 static void test_IImageList_Draw(void)
1841 IImageList *imgl;
1842 HIMAGELIST himl;
1844 HBITMAP hbm1;
1845 HBITMAP hbm2;
1846 HBITMAP hbm3;
1848 IMAGELISTDRAWPARAMS imldp;
1849 HWND hwndfortest;
1850 HRESULT hr;
1851 HDC hdc;
1852 int ret;
1854 hwndfortest = create_window();
1855 hdc = GetDC(hwndfortest);
1856 ok(hdc!=NULL, "couldn't get DC\n");
1858 /* create an imagelist to play with */
1859 himl = pImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1860 ok(himl!=0,"failed to create imagelist\n");
1862 imgl = (IImageList *) himl;
1864 /* load the icons to add to the image list */
1865 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1866 ok(hbm1 != 0, "no bitmap 1\n");
1867 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1868 ok(hbm2 != 0, "no bitmap 2\n");
1869 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1870 ok(hbm3 != 0, "no bitmap 3\n");
1872 /* add three */
1873 ret = -1;
1874 ok( IImageList_Add(imgl, hbm1, 0, &ret) == S_OK && (ret == 0), "failed to add bitmap 1\n");
1875 ret = -1;
1876 ok( IImageList_Add(imgl, hbm2, 0, &ret) == S_OK && (ret == 1), "failed to add bitmap 2\n");
1878 ok( IImageList_SetImageCount(imgl, 3) == S_OK, "Setimage count failed\n");
1879 ok( IImageList_Replace(imgl, 2, hbm3, 0) == S_OK, "failed to replace bitmap 3\n");
1881 if (0)
1883 /* crashes on native */
1884 IImageList_Draw(imgl, NULL);
1887 memset(&imldp, 0, sizeof (imldp));
1888 hr = IImageList_Draw(imgl, &imldp);
1889 ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
1891 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
1892 imldp.hdcDst = hdc;
1893 imldp.himl = himl;
1895 force_redraw(hwndfortest);
1897 imldp.fStyle = SRCCOPY;
1898 imldp.rgbBk = CLR_DEFAULT;
1899 imldp.rgbFg = CLR_DEFAULT;
1900 imldp.y = 100;
1901 imldp.x = 100;
1902 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1903 imldp.i ++;
1904 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1905 imldp.i ++;
1906 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1907 imldp.i ++;
1908 ok( IImageList_Draw(imgl, &imldp) == E_INVALIDARG, "should fail\n");
1910 /* remove three */
1911 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 1st bitmap\n");
1912 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 2nd bitmap\n");
1913 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 3rd bitmap\n");
1915 /* destroy it */
1916 IImageList_Release(imgl);
1918 /* bitmaps should not be deleted by the imagelist */
1919 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1920 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1921 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1923 ReleaseDC(hwndfortest, hdc);
1924 DestroyWindow(hwndfortest);
1927 static void test_IImageList_Merge(void)
1929 HIMAGELIST himl1, himl2;
1930 IImageList *imgl1, *imgl2, *merge;
1931 HICON hicon1;
1932 HWND hwnd = create_window();
1933 HRESULT hr;
1934 int ret;
1936 himl1 = pImageList_Create(32,32,0,0,3);
1937 ok(himl1 != NULL,"failed to create himl1\n");
1939 himl2 = pImageList_Create(32,32,0,0,3);
1940 ok(himl2 != NULL,"failed to create himl2\n");
1942 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1943 ok(hicon1 != NULL, "failed to create hicon1\n");
1945 if (!himl1 || !himl2 || !hicon1)
1946 return;
1948 /* cast to IImageList */
1949 imgl1 = (IImageList *) himl1;
1950 imgl2 = (IImageList *) himl2;
1952 ret = -1;
1953 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl2 failed\n");
1955 if (0)
1957 /* null cases that crash on native */
1958 IImageList_Merge(imgl1, -1, NULL, 0, 0, 0, &IID_IImageList, (void**)&merge);
1959 IImageList_Merge(imgl1, -1, (IUnknown*) imgl2, 0, 0, 0, &IID_IImageList, NULL);
1962 /* If himl1 has no images, merge still succeeds */
1963 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1964 ok(hr == S_OK, "merge himl1,-1 failed\n");
1965 if (hr == S_OK) IImageList_Release(merge);
1967 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1968 ok(hr == S_OK, "merge himl1,0 failed\n");
1969 if (hr == S_OK) IImageList_Release(merge);
1971 /* Same happens if himl2 is empty */
1972 IImageList_Release(imgl2);
1973 himl2 = pImageList_Create(32,32,0,0,3);
1974 ok(himl2 != NULL,"failed to recreate himl2\n");
1976 imgl2 = (IImageList *) himl2;
1978 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
1979 ok(hr == S_OK, "merge himl2,-1 failed\n");
1980 if (hr == S_OK) IImageList_Release(merge);
1982 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1983 ok(hr == S_OK, "merge himl2,0 failed\n");
1984 if (hr == S_OK) IImageList_Release(merge);
1986 /* Now try merging an image with itself */
1987 ret = -1;
1988 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"re-add icon1 to himl2 failed\n");
1990 hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1991 ok(hr == S_OK, "merge himl2 with itself failed\n");
1992 if (hr == S_OK) IImageList_Release(merge);
1994 /* Try merging 2 different image lists */
1995 ret = -1;
1996 ok( IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl1 failed\n");
1998 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1999 ok(hr == S_OK, "merge himl1 with himl2 failed\n");
2000 if (hr == S_OK) IImageList_Release(merge);
2002 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
2003 ok(hr == S_OK, "merge himl1 with himl2 8,16 failed\n");
2004 if (hr == S_OK) IImageList_Release(merge);
2006 IImageList_Release(imgl1);
2007 IImageList_Release(imgl2);
2009 DestroyIcon(hicon1);
2010 DestroyWindow(hwnd);
2013 static void test_iconsize(void)
2015 HIMAGELIST himl;
2016 INT cx, cy;
2017 BOOL ret;
2019 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2020 /* null pointers, not zero imagelist dimensions */
2021 ret = pImageList_GetIconSize(himl, NULL, NULL);
2022 ok(!ret, "got %d\n", ret);
2024 /* doesn't touch return pointers */
2025 cx = 0x1abe11ed;
2026 ret = pImageList_GetIconSize(himl, &cx, NULL);
2027 ok(!ret, "got %d\n", ret);
2028 ok(cx == 0x1abe11ed, "got %d\n", cx);
2030 cy = 0x1abe11ed;
2031 ret = pImageList_GetIconSize(himl, NULL, &cy);
2032 ok(!ret, "got %d\n", ret);
2033 ok(cy == 0x1abe11ed, "got %d\n", cy);
2035 pImageList_Destroy(himl);
2037 ret = pImageList_GetIconSize((HIMAGELIST)0xdeadbeef, &cx, &cy);
2038 ok(!ret, "got %d\n", ret);
2041 static void test_create_destroy(void)
2043 HIMAGELIST himl;
2044 INT cx, cy;
2045 BOOL rc;
2046 INT ret;
2048 /* list with zero or negative image dimensions */
2049 himl = pImageList_Create(0, 0, ILC_COLOR16, 0, 3);
2050 ok(himl == NULL, "got %p\n", himl);
2052 himl = pImageList_Create(0, 16, ILC_COLOR16, 0, 3);
2053 ok(himl == NULL, "got %p\n", himl);
2055 himl = pImageList_Create(16, 0, ILC_COLOR16, 0, 3);
2056 ok(himl == NULL, "got %p\n", himl);
2058 himl = pImageList_Create(16, -1, ILC_COLOR16, 0, 3);
2059 ok(himl == NULL, "got %p\n", himl);
2061 himl = pImageList_Create(-1, 16, ILC_COLOR16, 0, 3);
2062 ok(himl == NULL, "got %p\n", himl);
2064 rc = pImageList_Destroy((HIMAGELIST)0xdeadbeef);
2065 ok(rc == FALSE, "ImageList_Destroy(0xdeadbeef) should fail and not crash\n");
2067 /* DDB image lists */
2068 himl = pImageList_Create(0, 14, ILC_COLORDDB, 4, 4);
2069 ok(himl != NULL, "got %p\n", himl);
2071 pImageList_GetIconSize(himl, &cx, &cy);
2072 ok (cx == 0, "Wrong cx (%i)\n", cx);
2073 ok (cy == 14, "Wrong cy (%i)\n", cy);
2074 pImageList_Destroy(himl);
2076 himl = pImageList_Create(0, 0, ILC_COLORDDB, 4, 4);
2077 ok(himl != NULL, "got %p\n", himl);
2078 pImageList_GetIconSize(himl, &cx, &cy);
2079 ok (cx == 0, "Wrong cx (%i)\n", cx);
2080 ok (cy == 0, "Wrong cy (%i)\n", cy);
2081 pImageList_Destroy(himl);
2083 himl = pImageList_Create(0, 0, ILC_COLORDDB, 0, 4);
2084 ok(himl != NULL, "got %p\n", himl);
2085 pImageList_GetIconSize(himl, &cx, &cy);
2086 ok (cx == 0, "Wrong cx (%i)\n", cx);
2087 ok (cy == 0, "Wrong cy (%i)\n", cy);
2089 pImageList_SetImageCount(himl, 3);
2090 ret = pImageList_GetImageCount(himl);
2091 ok(ret == 3, "Unexpected image count after increase\n");
2093 /* Trying to actually add an image causes a crash on Windows */
2094 pImageList_Destroy(himl);
2096 /* Negative values fail */
2097 himl = pImageList_Create(-1, -1, ILC_COLORDDB, 4, 4);
2098 ok(himl == NULL, "got %p\n", himl);
2099 himl = pImageList_Create(-1, 1, ILC_COLORDDB, 4, 4);
2100 ok(himl == NULL, "got %p\n", himl);
2101 himl = pImageList_Create(1, -1, ILC_COLORDDB, 4, 4);
2102 ok(himl == NULL, "got %p\n", himl);
2105 static void check_color_table(const char *name, HDC hdc, HIMAGELIST himl, UINT ilc,
2106 RGBQUAD *expect, RGBQUAD *broken_expect)
2108 IMAGEINFO info;
2109 INT ret;
2110 char bmi_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
2111 BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
2112 int i, depth = ilc & 0xfe;
2114 ret = pImageList_GetImageInfo(himl, 0, &info);
2115 ok(ret, "got %d\n", ret);
2116 ok(info.hbmImage != NULL, "got %p\n", info.hbmImage);
2118 memset(bmi_buffer, 0, sizeof(bmi_buffer));
2119 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
2120 ret = GetDIBits(hdc, info.hbmImage, 0, 0, NULL, bmi, DIB_RGB_COLORS);
2121 ok(ret, "got %d\n", ret);
2122 ok(bmi->bmiHeader.biBitCount == depth, "got %d\n", bmi->bmiHeader.biBitCount);
2124 ret = GetDIBits(hdc, info.hbmImage, 0, 0, NULL, bmi, DIB_RGB_COLORS);
2125 ok(ret, "got %d\n", ret);
2126 ok(bmi->bmiHeader.biBitCount == depth, "got %d\n", bmi->bmiHeader.biBitCount);
2128 for (i = 0; i < (1 << depth); i++)
2129 ok((bmi->bmiColors[i].rgbRed == expect[i].rgbRed &&
2130 bmi->bmiColors[i].rgbGreen == expect[i].rgbGreen &&
2131 bmi->bmiColors[i].rgbBlue == expect[i].rgbBlue) ||
2132 (broken_expect && broken(bmi->bmiColors[i].rgbRed == broken_expect[i].rgbRed &&
2133 bmi->bmiColors[i].rgbGreen == broken_expect[i].rgbGreen &&
2134 bmi->bmiColors[i].rgbBlue == broken_expect[i].rgbBlue)),
2135 "%d: %s: got color[%d] %02x %02x %02x expect %02x %02x %02x\n", depth, name, i,
2136 bmi->bmiColors[i].rgbRed, bmi->bmiColors[i].rgbGreen, bmi->bmiColors[i].rgbBlue,
2137 expect[i].rgbRed, expect[i].rgbGreen, expect[i].rgbBlue);
2140 static void get_default_color_table(HDC hdc, int bpp, RGBQUAD *table)
2142 char bmi_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
2143 BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
2144 HBITMAP tmp;
2145 int i;
2146 HPALETTE pal;
2147 PALETTEENTRY entries[256];
2149 switch (bpp)
2151 case 4:
2152 tmp = CreateBitmap( 1, 1, 1, 1, NULL );
2153 memset(bmi_buffer, 0, sizeof(bmi_buffer));
2154 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
2155 bmi->bmiHeader.biHeight = 1;
2156 bmi->bmiHeader.biWidth = 1;
2157 bmi->bmiHeader.biBitCount = bpp;
2158 bmi->bmiHeader.biPlanes = 1;
2159 bmi->bmiHeader.biCompression = BI_RGB;
2160 GetDIBits( hdc, tmp, 0, 0, NULL, bmi, DIB_RGB_COLORS );
2162 memcpy(table, bmi->bmiColors, (1 << bpp) * sizeof(RGBQUAD));
2163 table[7] = bmi->bmiColors[8];
2164 table[8] = bmi->bmiColors[7];
2165 DeleteObject( tmp );
2166 break;
2168 case 8:
2169 pal = CreateHalftonePalette(hdc);
2170 GetPaletteEntries(pal, 0, 256, entries);
2171 for (i = 0; i < 256; i++)
2173 table[i].rgbRed = entries[i].peRed;
2174 table[i].rgbGreen = entries[i].peGreen;
2175 table[i].rgbBlue = entries[i].peBlue;
2176 table[i].rgbReserved = 0;
2178 DeleteObject(pal);
2179 break;
2181 default:
2182 ok(0, "unhandled depth %d\n", bpp);
2186 static void test_color_table(UINT ilc)
2188 HIMAGELIST himl;
2189 INT ret;
2190 char bmi_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
2191 BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
2192 HDC hdc = CreateCompatibleDC(0);
2193 HBITMAP dib4, dib8, dib32;
2194 RGBQUAD rgb[256], default_table[256];
2196 get_default_color_table(hdc, ilc & 0xfe, default_table);
2198 himl = pImageList_Create(16, 16, ilc, 0, 3);
2199 ok(himl != NULL, "got %p\n", himl);
2201 memset(bmi_buffer, 0, sizeof(bmi_buffer));
2202 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
2203 bmi->bmiHeader.biHeight = 16;
2204 bmi->bmiHeader.biWidth = 16;
2205 bmi->bmiHeader.biBitCount = 8;
2206 bmi->bmiHeader.biPlanes = 1;
2207 bmi->bmiHeader.biCompression = BI_RGB;
2208 bmi->bmiColors[0].rgbRed = 0xff;
2209 bmi->bmiColors[1].rgbGreen = 0xff;
2210 bmi->bmiColors[2].rgbBlue = 0xff;
2212 dib8 = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
2214 bmi->bmiHeader.biBitCount = 4;
2215 bmi->bmiColors[0].rgbRed = 0xff;
2216 bmi->bmiColors[0].rgbGreen = 0x00;
2217 bmi->bmiColors[0].rgbBlue = 0xff;
2218 bmi->bmiColors[1].rgbRed = 0xff;
2219 bmi->bmiColors[1].rgbGreen = 0xff;
2220 bmi->bmiColors[1].rgbBlue = 0x00;
2221 bmi->bmiColors[2].rgbRed = 0x00;
2222 bmi->bmiColors[2].rgbGreen = 0xff;
2223 bmi->bmiColors[2].rgbBlue = 0xff;
2225 dib4 = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
2227 bmi->bmiHeader.biBitCount = 32;
2229 dib32 = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
2231 /* add 32 first then 8. This won't set the color table */
2232 ret = pImageList_Add(himl, dib32, NULL);
2233 ok(ret == 0, "got %d\n", ret);
2234 ret = pImageList_Add(himl, dib8, NULL);
2235 ok(ret == 1, "got %d\n", ret);
2237 check_color_table("add 32, 8", hdc, himl, ilc, default_table, NULL);
2239 /* since the previous _Adds didn't set the color table, this one will */
2240 ret = pImageList_Remove(himl, -1);
2241 ok(ret, "got %d\n", ret);
2242 ret = pImageList_Add(himl, dib8, NULL);
2243 ok(ret == 0, "got %d\n", ret);
2245 memset(rgb, 0, sizeof(rgb));
2246 rgb[0].rgbRed = 0xff;
2247 rgb[1].rgbGreen = 0xff;
2248 rgb[2].rgbBlue = 0xff;
2249 check_color_table("remove all, add 8", hdc, himl, ilc, rgb, default_table);
2251 /* remove all, add 4. Color table remains the same since it's implicitly
2252 been set by the previous _Add */
2253 ret = pImageList_Remove(himl, -1);
2254 ok(ret, "got %d\n", ret);
2255 ret = pImageList_Add(himl, dib4, NULL);
2256 ok(ret == 0, "got %d\n", ret);
2257 check_color_table("remove all, add 4", hdc, himl, ilc, rgb, default_table);
2259 pImageList_Destroy(himl);
2260 himl = pImageList_Create(16, 16, ilc, 0, 3);
2261 ok(himl != NULL, "got %p\n", himl);
2263 /* add 4 */
2264 ret = pImageList_Add(himl, dib4, NULL);
2265 ok(ret == 0, "got %d\n", ret);
2267 memset(rgb, 0, 16 * sizeof(rgb[0]));
2268 rgb[0].rgbRed = 0xff;
2269 rgb[0].rgbBlue = 0xff;
2270 rgb[1].rgbRed = 0xff;
2271 rgb[1].rgbGreen = 0xff;
2272 rgb[2].rgbGreen = 0xff;
2273 rgb[2].rgbBlue = 0xff;
2274 memcpy(rgb + 16, default_table + 16, 240 * sizeof(rgb[0]));
2276 check_color_table("add 4", hdc, himl, ilc, rgb, default_table);
2278 pImageList_Destroy(himl);
2279 himl = pImageList_Create(16, 16, ilc, 0, 3);
2280 ok(himl != NULL, "got %p\n", himl);
2282 /* set color table, add 8 */
2283 ret = pImageList_Remove(himl, -1);
2284 ok(ret, "got %d\n", ret);
2285 memset(rgb, 0, sizeof(rgb));
2286 rgb[0].rgbRed = 0xcc;
2287 rgb[1].rgbBlue = 0xcc;
2288 ret = pImageList_SetColorTable(himl, 0, 2, rgb);
2289 ok(ret == 2, "got %d\n", ret);
2290 /* the table is set, so this doesn't change it */
2291 ret = pImageList_Add(himl, dib8, NULL);
2292 ok(ret == 0, "got %d\n", ret);
2294 memcpy(rgb + 2, default_table + 2, 254 * sizeof(rgb[0]));
2295 check_color_table("SetColorTable", hdc, himl, ilc, rgb, NULL);
2297 DeleteObject(dib32);
2298 DeleteObject(dib8);
2299 DeleteObject(dib4);
2300 DeleteDC(hdc);
2301 pImageList_Destroy(himl);
2304 static void test_copy(void)
2306 HIMAGELIST dst, src;
2307 BOOL ret;
2308 int count;
2310 dst = pImageList_Create(5, 11, ILC_COLOR, 1, 1);
2311 count = pImageList_GetImageCount(dst);
2312 ok(!count, "ImageList not empty.\n");
2313 src = createImageList(7, 13);
2314 count = pImageList_GetImageCount(src);
2315 ok(count > 2, "Tests need an ImageList with more than 2 images\n");
2317 /* ImageList_Copy() cannot copy between two ImageLists */
2318 ret = pImageList_Copy(dst, 0, src, 2, ILCF_MOVE);
2319 ok(!ret, "ImageList_Copy() should have returned FALSE\n");
2320 count = pImageList_GetImageCount(dst);
2321 ok(count == 0, "Expected no image in dst ImageList, got %d\n", count);
2323 pImageList_Destroy(dst);
2324 pImageList_Destroy(src);
2327 static void test_loadimage(void)
2329 HIMAGELIST list;
2330 DWORD flags;
2332 list = pImageList_LoadImageW( hinst, MAKEINTRESOURCEW(IDB_BITMAP_128x15), 16, 1, CLR_DEFAULT,
2333 IMAGE_BITMAP, LR_CREATEDIBSECTION );
2334 ok( list != NULL, "got %p\n", list );
2335 flags = pImageList_GetFlags( list );
2336 ok( flags == (ILC_COLOR4 | ILC_MASK), "got %08x\n", flags );
2337 pImageList_Destroy( list );
2339 list = pImageList_LoadImageW( hinst, MAKEINTRESOURCEW(IDB_BITMAP_128x15), 16, 1, CLR_NONE,
2340 IMAGE_BITMAP, LR_CREATEDIBSECTION );
2341 ok( list != NULL, "got %p\n", list );
2342 flags = pImageList_GetFlags( list );
2343 ok( flags == ILC_COLOR4, "got %08x\n", flags );
2344 pImageList_Destroy( list );
2347 #define GetAValue(argb) ((BYTE) ((argb) >> 24))
2349 static void get_image_bits(HIMAGELIST himl, int index, int width, int height, UINT32 *bits)
2351 HBITMAP hbm_dst;
2352 void *bitmap_bits;
2353 BITMAPINFO bitmap_info = {{sizeof(BITMAPINFOHEADER), width, height, 1, 32, BI_RGB, 0, 0, 0, 0, 0}};
2355 HDC hdc_dst = CreateCompatibleDC(0);
2356 hbm_dst = CreateDIBSection(hdc_dst, &bitmap_info, DIB_RGB_COLORS, &bitmap_bits, NULL, 0);
2357 SelectObject(hdc_dst, hbm_dst);
2359 pImageList_Draw(himl, index, hdc_dst, 0, 0, ILD_TRANSPARENT);
2360 memcpy(bits, bitmap_bits, (size_t)(width * height * 32 / 8));
2362 DeleteObject(hbm_dst);
2363 DeleteDC(hdc_dst);
2366 static void test_alpha(void)
2368 /* each line is a 2*1 bitmap */
2369 const static UINT32 test_bitmaps[] =
2371 0x00654321, 0x00ABCDEF,
2372 0x00654321, 0x00654321,
2373 0x00ABCDEF, 0x00654321,
2374 0x00ABCDEF, 0x00ABCDEF,
2375 0x00654321, 0x01ABCDEF,
2376 0x01654321, 0x00ABCDEF,
2377 0x00654321, 0xFFABCDEF,
2378 0x00654321, 0x89ABCDEF,
2379 0xFF654321, 0x00ABCDEF,
2380 0xFF654321, 0xFFABCDEF,
2381 0xFF654321, 0x89ABCDEF,
2382 0x87654321, 0x00ABCDEF,
2383 0x87654321, 0xFFABCDEF,
2384 0x87654321, 0x89ABCDEF
2386 const static BYTE mask_bits = 0xAA;
2388 int i, ret;
2389 HDC hdc;
2390 HBITMAP hbm_test, hbm_mask;
2391 HIMAGELIST himl;
2392 UINT32 bits[2];
2394 hdc = CreateCompatibleDC(0);
2395 himl = pImageList_Create(2, 1, ILC_COLOR32 | ILC_MASK, 0, 15);
2397 for (i = 0; i < ARRAY_SIZE(test_bitmaps); i += 2)
2399 hbm_test = create_test_bitmap(hdc, 2, 1, 32, test_bitmaps + i);
2400 ret = pImageList_AddMasked(himl, hbm_test, RGB(0x65,0x43,0x21));
2401 ok(ret == i / 2, "ImageList_AddMasked returned %d, expected %d\n", ret, i / 2);
2402 DeleteObject(hbm_test);
2404 get_image_bits(himl, i / 2, 2, 1, bits);
2405 ok(GetAValue(bits[0]) == GetAValue(test_bitmaps[i]) && GetAValue(bits[1]) == GetAValue(test_bitmaps[i + 1]),
2406 "Bitmap [%08X, %08X] returned alpha value [%02X, %02X], expected [%02X, %02X]\n",
2407 test_bitmaps[i], test_bitmaps[i + 1], GetAValue(bits[0]), GetAValue(bits[1]),
2408 GetAValue(test_bitmaps[i]), GetAValue(test_bitmaps[i + 1]));
2410 /* If all alpha values are zero, the image is considered to have no alpha and gets masked */
2411 if (!GetAValue(bits[0]) && !GetAValue(bits[1]))
2412 ok(bits[0] == (test_bitmaps[i] == 0x654321 ? 0 : test_bitmaps[i]) &&
2413 bits[1] == (test_bitmaps[i + 1] == 0x654321 ? 0 : test_bitmaps[i + 1]),
2414 "Bitmap [%08X, %08X] returned [%08X, %08X], expected [%08X, %08X]\n",
2415 test_bitmaps[i], test_bitmaps[i + 1], bits[0], bits[1],
2416 test_bitmaps[i] == 0x654321 ? 0 : test_bitmaps[i],
2417 test_bitmaps[i + 1] == 0x654321 ? 0 : test_bitmaps[i + 1]);
2420 pImageList_Destroy(himl);
2421 hbm_mask = CreateBitmap(2, 1, 1, 1, &mask_bits);
2422 himl = pImageList_Create(2, 1, ILC_COLOR32 | ILC_MASK, 0, 15);
2424 for (i = 0; i < ARRAY_SIZE(test_bitmaps); i += 2)
2426 hbm_test = create_test_bitmap(hdc, 2, 1, 32, test_bitmaps + i);
2427 ret = pImageList_Add(himl, hbm_test, hbm_mask);
2428 ok(ret == i / 2, "ImageList_Add returned %d, expected %d\n", ret, i / 2);
2429 DeleteObject(hbm_test);
2431 get_image_bits(himl, i / 2, 2, 1, bits);
2432 ok(GetAValue(bits[0]) == GetAValue(test_bitmaps[i]) && GetAValue(bits[1]) == GetAValue(test_bitmaps[i + 1]),
2433 "Bitmap [%08X, %08X] returned alpha value [%02X, %02X], expected [%02X, %02X]\n",
2434 test_bitmaps[i], test_bitmaps[i + 1], GetAValue(bits[0]), GetAValue(bits[1]),
2435 GetAValue(test_bitmaps[i]), GetAValue(test_bitmaps[i + 1]));
2437 /* If all alpha values are zero, the image is considered to have no alpha and gets masked */
2438 if (!GetAValue(bits[0]) && !GetAValue(bits[1]))
2439 ok(!bits[0] && bits[1] == test_bitmaps[i + 1],
2440 "Bitmap [%08X, %08X] returned [%08X, %08X], expected [%08X, %08X]\n",
2441 test_bitmaps[i], test_bitmaps[i + 1], bits[0], bits[1], 0, test_bitmaps[i + 1]);
2442 else
2444 if (GetAValue(bits[0]) >= 0x80)
2445 ok(bits[0] & 0x00FFFFFF, "Bitmap [%08X, %08X] has alpha and masked first pixel [%08X]\n",
2446 test_bitmaps[i], test_bitmaps[i + 1], bits[0]);
2450 pImageList_Destroy(himl);
2451 DeleteObject(hbm_mask);
2452 DeleteDC(hdc);
2455 static void test_IImageList_Clone(void)
2457 IImageList *imgl, *imgl2;
2458 HIMAGELIST himl;
2459 HRESULT hr;
2460 ULONG ref;
2462 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2463 imgl = (IImageList*)himl;
2465 if (0)
2467 /* crashes on native */
2468 IImageList_Clone(imgl, &IID_IImageList, NULL);
2471 hr = IImageList_Clone(imgl, &IID_IImageList, (void**)&imgl2);
2472 ok(hr == S_OK, "got 0x%08x\n", hr);
2473 ref = IImageList_Release(imgl2);
2474 ok(ref == 0, "got %u\n", ref);
2476 IImageList_Release(imgl);
2479 static void test_IImageList_GetBkColor(void)
2481 IImageList *imgl;
2482 HIMAGELIST himl;
2483 COLORREF color;
2484 HRESULT hr;
2486 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2487 imgl = (IImageList*)himl;
2489 if (0)
2491 /* crashes on native */
2492 IImageList_GetBkColor(imgl, NULL);
2495 hr = IImageList_GetBkColor(imgl, &color);
2496 ok(hr == S_OK, "got 0x%08x\n", hr);
2498 IImageList_Release(imgl);
2501 static void test_IImageList_SetBkColor(void)
2503 IImageList *imgl;
2504 HIMAGELIST himl;
2505 COLORREF color;
2506 HRESULT hr;
2508 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2509 imgl = (IImageList*)himl;
2511 if (0)
2513 /* crashes on native */
2514 IImageList_SetBkColor(imgl, RGB(0, 0, 0), NULL);
2517 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
2518 ok(hr == S_OK, "got 0x%08x\n", hr);
2520 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
2521 ok(hr == S_OK, "got 0x%08x\n", hr);
2523 color = 0xdeadbeef;
2524 hr = IImageList_GetBkColor(imgl, &color);
2525 ok(hr == S_OK, "got 0x%08x\n", hr);
2526 ok(color == CLR_NONE, "got %x\n", color);
2528 IImageList_Release(imgl);
2531 static void test_IImageList_GetImageCount(void)
2533 IImageList *imgl;
2534 HIMAGELIST himl;
2535 int count;
2536 HRESULT hr;
2538 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2539 imgl = (IImageList*)himl;
2541 if (0)
2543 /* crashes on native */
2544 IImageList_GetImageCount(imgl, NULL);
2547 count = -1;
2548 hr = IImageList_GetImageCount(imgl, &count);
2549 ok(hr == S_OK, "got 0x%08x\n", hr);
2550 ok(count == 0, "got %d\n", count);
2552 IImageList_Release(imgl);
2555 static void test_IImageList_GetIconSize(void)
2557 IImageList *imgl;
2558 HIMAGELIST himl;
2559 int cx, cy;
2560 HRESULT hr;
2562 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2563 imgl = (IImageList*)himl;
2565 hr = IImageList_GetIconSize(imgl, NULL, NULL);
2566 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2568 hr = IImageList_GetIconSize(imgl, &cx, NULL);
2569 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2571 hr = IImageList_GetIconSize(imgl, NULL, &cy);
2572 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2574 IImageList_Release(imgl);
2577 static void init_functions(void)
2579 HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
2581 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
2582 #define X2(f, ord) p##f = (void*)GetProcAddress(hComCtl32, (const char *)ord);
2583 X(ImageList_Create);
2584 X(ImageList_Destroy);
2585 X(ImageList_Add);
2586 X(ImageList_AddMasked);
2587 X(ImageList_DrawIndirect);
2588 X(ImageList_SetImageCount);
2589 X2(ImageList_SetColorTable, 390);
2590 X(ImageList_GetFlags);
2591 X(ImageList_BeginDrag);
2592 X(ImageList_GetDragImage);
2593 X(ImageList_EndDrag);
2594 X(ImageList_GetImageCount);
2595 X(ImageList_SetDragCursorImage);
2596 X(ImageList_GetIconSize);
2597 X(ImageList_SetIconSize);
2598 X(ImageList_Remove);
2599 X(ImageList_ReplaceIcon);
2600 X(ImageList_Replace);
2601 X(ImageList_Merge);
2602 X(ImageList_GetImageInfo);
2603 X(ImageList_Write);
2604 X(ImageList_Read);
2605 X(ImageList_Copy);
2606 X(ImageList_LoadImageW);
2607 X(ImageList_CoCreateInstance);
2608 X(HIMAGELIST_QueryInterface);
2609 X(ImageList_Draw);
2610 #undef X
2611 #undef X2
2614 START_TEST(imagelist)
2616 ULONG_PTR ctx_cookie;
2617 HANDLE hCtx;
2619 init_functions();
2621 hinst = GetModuleHandleA(NULL);
2623 test_create_destroy();
2624 test_begindrag();
2625 test_hotspot();
2626 test_add_remove();
2627 test_imagecount();
2628 test_DrawIndirect();
2629 test_merge();
2630 test_merge_colors();
2631 test_imagelist_storage();
2632 test_iconsize();
2633 test_color_table(ILC_COLOR4);
2634 test_color_table(ILC_COLOR8);
2635 test_copy();
2636 test_loadimage();
2638 /* Now perform v6 tests */
2639 if (!load_v6_module(&ctx_cookie, &hCtx))
2640 return;
2642 init_functions();
2644 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2646 /* Do v6.0 tests */
2647 test_add_remove();
2648 test_imagecount();
2649 test_DrawIndirect();
2650 test_merge();
2651 test_imagelist_storage();
2652 test_iconsize();
2653 test_color_table(ILC_COLOR4);
2654 test_color_table(ILC_COLOR8);
2655 test_copy();
2656 test_loadimage();
2657 test_alpha();
2659 test_ImageList_DrawIndirect();
2660 test_shell_imagelist();
2661 test_iimagelist();
2663 test_IImageList_Add_Remove();
2664 test_IImageList_Get_SetImageCount();
2665 test_IImageList_Draw();
2666 test_IImageList_Merge();
2667 test_IImageList_Clone();
2668 test_IImageList_GetBkColor();
2669 test_IImageList_SetBkColor();
2670 test_IImageList_GetImageCount();
2671 test_IImageList_GetIconSize();
2673 CoUninitialize();
2675 unload_v6_module(ctx_cookie, hCtx);