ucrtbase: Store exception record in ExceptionInformation[6] during unwinding.
[wine.git] / dlls / comctl32 / tests / imagelist.c
blobde0b0dd4c08ebcf335bce71549526e1e23752ad8
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);
91 static HRESULT (WINAPI *pImageList_WriteEx)(HIMAGELIST himl, DWORD flags, IStream *stream);
93 static HINSTANCE hinst;
95 /* only used in interactive mode */
96 static void force_redraw(HWND hwnd)
98 if (!winetest_interactive)
99 return;
101 RedrawWindow(hwnd, NULL, 0, RDW_UPDATENOW);
102 Sleep(1000);
105 static BOOL is_v6_test(void)
107 return pHIMAGELIST_QueryInterface != NULL;
110 /* These macros build cursor/bitmap data in 4x4 pixel blocks */
111 #define B(x,y) ((x?0xf0:0)|(y?0xf:0))
112 #define ROW1(a,b,c,d,e,f,g,h) B(a,b),B(c,d),B(e,f),B(g,h)
113 #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), \
114 ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h)
115 #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)
116 #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), \
117 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), \
118 ROW2(a,b,c,d,e,f,g,h,i,j,k,l)
120 static const BYTE empty_bits[48*48/8];
122 static const BYTE icon_bits[32*32/8] =
124 ROW32(0,0,0,0,0,0,0,0),
125 ROW32(0,0,1,1,1,1,0,0),
126 ROW32(0,1,1,1,1,1,1,0),
127 ROW32(0,1,1,0,0,1,1,0),
128 ROW32(0,1,1,0,0,1,1,0),
129 ROW32(0,1,1,1,1,1,1,0),
130 ROW32(0,0,1,1,1,1,0,0),
131 ROW32(0,0,0,0,0,0,0,0)
134 static const BYTE bitmap_bits[48*48/8] =
136 ROW48(0,0,0,0,0,0,0,0,0,0,0,0),
137 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
138 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
139 ROW48(0,1,0,0,0,0,0,0,1,0,1,0),
140 ROW48(0,1,0,0,0,0,0,1,0,0,1,0),
141 ROW48(0,1,0,0,0,0,1,0,0,0,1,0),
142 ROW48(0,1,0,0,0,1,0,0,0,0,1,0),
143 ROW48(0,1,0,0,1,0,0,0,0,0,1,0),
144 ROW48(0,1,0,1,0,0,0,0,0,0,1,0),
145 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
146 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
147 ROW48(0,0,0,0,0,0,0,0,0,0,0,0)
150 static HIMAGELIST createImageList(int cx, int cy)
152 /* Create an ImageList and put an image into it */
153 HIMAGELIST himl = pImageList_Create(cx, cy, ILC_COLOR, 1, 1);
154 HBITMAP hbm = CreateBitmap(48, 48, 1, 1, bitmap_bits);
156 ok(himl != NULL, "Failed to create image list, %d x %d.\n", cx, cy);
157 pImageList_Add(himl, hbm, NULL);
158 DeleteObject(hbm);
159 return himl;
162 static HWND create_window(void)
164 char className[] = "bmwnd";
165 char winName[] = "Test Bitmap";
166 HWND hWnd;
167 static BOOL registered = FALSE;
169 if (!registered)
171 WNDCLASSA cls;
173 cls.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
174 cls.lpfnWndProc = DefWindowProcA;
175 cls.cbClsExtra = 0;
176 cls.cbWndExtra = 0;
177 cls.hInstance = 0;
178 cls.hIcon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
179 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
180 cls.hbrBackground = GetStockObject (WHITE_BRUSH);
181 cls.lpszMenuName = 0;
182 cls.lpszClassName = className;
184 RegisterClassA (&cls);
185 registered = TRUE;
188 /* Setup window */
189 hWnd = CreateWindowA (className, winName,
190 WS_OVERLAPPEDWINDOW ,
191 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
192 0, hinst, 0);
194 if (winetest_interactive)
196 ShowWindow (hWnd, SW_SHOW);
197 force_redraw (hWnd);
200 return hWnd;
203 static HDC show_image(HWND hwnd, HIMAGELIST himl, int idx, int size,
204 LPCSTR loc, BOOL clear)
206 HDC hdc;
208 if (!winetest_interactive || !himl) return NULL;
210 SetWindowTextA(hwnd, loc);
211 hdc = GetDC(hwnd);
212 pImageList_Draw(himl, idx, hdc, 0, 0, ILD_TRANSPARENT);
214 force_redraw(hwnd);
216 if (clear)
218 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
219 ReleaseDC(hwnd, hdc);
220 hdc = NULL;
223 return hdc;
226 /* Useful for checking differences */
227 static void dump_bits(const BYTE *p, const BYTE *q, int size)
229 int i, j;
231 size /= 8;
233 for (i = 0; i < size * 2; i++)
235 printf("|");
236 for (j = 0; j < size; j++)
237 printf("%c%c", p[j] & 0xf0 ? 'X' : ' ', p[j] & 0xf ? 'X' : ' ');
238 printf(" -- ");
239 for (j = 0; j < size; j++)
240 printf("%c%c", q[j] & 0xf0 ? 'X' : ' ', q[j] & 0xf ? 'X' : ' ');
241 printf("|\n");
242 p += size * 4;
243 q += size * 4;
245 printf("\n");
248 static void check_bits(HWND hwnd, HIMAGELIST himl, int idx, int size,
249 const BYTE *checkbits, LPCSTR loc)
251 BYTE bits[100*100/8];
252 COLORREF c;
253 HDC hdc;
254 int x, y, i = -1;
256 if (!winetest_interactive || !himl) return;
258 memset(bits, 0, sizeof(bits));
259 hdc = show_image(hwnd, himl, idx, size, loc, FALSE);
261 c = GetPixel(hdc, 0, 0);
263 for (y = 0; y < size; y ++)
265 for (x = 0; x < size; x++)
267 if (!(x & 0x7)) i++;
268 if (GetPixel(hdc, x, y) != c) bits[i] |= (0x80 >> (x & 0x7));
272 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
273 ReleaseDC(hwnd, hdc);
275 ok (memcmp(bits, checkbits, (size * size)/8) == 0,
276 "%s: bits different\n", loc);
277 if (memcmp(bits, checkbits, (size * size)/8))
278 dump_bits(bits, checkbits, size);
281 static void test_begindrag(void)
283 HIMAGELIST himl = createImageList(7,13);
284 HIMAGELIST drag;
285 BOOL ret;
286 int count;
287 POINT hotspot;
289 count = pImageList_GetImageCount(himl);
290 ok(count > 2, "Tests need an ImageList with more than 2 images\n");
292 /* Two BeginDrag() without EndDrag() in between */
293 ret = pImageList_BeginDrag(himl, 1, 0, 0);
294 drag = pImageList_GetDragImage(NULL, NULL);
295 ok(ret && drag, "ImageList_BeginDrag() failed\n");
296 ret = pImageList_BeginDrag(himl, 0, 3, 5);
297 ok(!ret, "ImageList_BeginDrag() returned TRUE\n");
298 drag = pImageList_GetDragImage(NULL, &hotspot);
299 ok(!!drag, "No active ImageList drag left\n");
300 ok(hotspot.x == 0 && hotspot.y == 0, "New ImageList drag was created\n");
301 pImageList_EndDrag();
302 drag = pImageList_GetDragImage(NULL, NULL);
303 ok(!drag, "ImageList drag was not destroyed\n");
305 /* Invalid image index */
306 pImageList_BeginDrag(himl, 0, 0, 0);
307 ret = pImageList_BeginDrag(himl, count, 3, 5);
308 ok(!ret, "ImageList_BeginDrag() returned TRUE\n");
309 drag = pImageList_GetDragImage(NULL, &hotspot);
310 ok(drag && hotspot.x == 0 && hotspot.y == 0, "Active drag should not have been canceled\n");
311 pImageList_EndDrag();
312 drag = pImageList_GetDragImage(NULL, NULL);
313 ok(!drag, "ImageList drag was not destroyed\n");
314 /* Invalid negative image indexes succeed */
315 ret = pImageList_BeginDrag(himl, -17, 0, 0);
316 drag = pImageList_GetDragImage(NULL, NULL);
317 ok(ret && drag, "ImageList drag was created\n");
318 pImageList_EndDrag();
319 ret = pImageList_BeginDrag(himl, -1, 0, 0);
320 drag = pImageList_GetDragImage(NULL, NULL);
321 ok(ret && drag, "ImageList drag was created\n");
322 pImageList_EndDrag();
323 pImageList_Destroy(himl);
326 static void test_hotspot(void)
328 struct hotspot {
329 int dx;
330 int dy;
333 #define SIZEX1 47
334 #define SIZEY1 31
335 #define SIZEX2 11
336 #define SIZEY2 17
337 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
338 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
339 { 10, 7 },
340 { SIZEX1, SIZEY1 },
341 { -9, -8 },
342 { -7, 35 }
344 int i, j, ret;
345 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
346 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
347 HWND hwnd = create_window();
350 for (i = 0; i < HOTSPOTS_MAX; i++) {
351 for (j = 0; j < HOTSPOTS_MAX; j++) {
352 int dx1 = hotspots[i].dx;
353 int dy1 = hotspots[i].dy;
354 int dx2 = hotspots[j].dx;
355 int dy2 = hotspots[j].dy;
356 int correctx, correcty, newx, newy;
357 char loc[256];
358 HIMAGELIST himlNew;
359 POINT ppt;
361 ret = pImageList_BeginDrag(himl1, 0, dx1, dy1);
362 ok(ret != 0, "BeginDrag failed for { %d, %d }\n", dx1, dy1);
363 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
364 show_image(hwnd, himl1, 0, max(SIZEX1, SIZEY1), loc, TRUE);
366 /* check merging the dragged image with a second image */
367 ret = pImageList_SetDragCursorImage(himl2, 0, dx2, dy2);
368 ok(ret != 0, "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
369 dx1, dy1, dx2, dy2);
370 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
371 show_image(hwnd, himl2, 0, max(SIZEX2, SIZEY2), loc, TRUE);
373 /* check new hotspot, it should be the same like the old one */
374 himlNew = pImageList_GetDragImage(NULL, &ppt);
375 ok(ppt.x == dx1 && ppt.y == dy1,
376 "Expected drag hotspot [%d,%d] got [%ld,%ld]\n",
377 dx1, dy1, ppt.x, ppt.y);
378 /* check size of new dragged image */
379 pImageList_GetIconSize(himlNew, &newx, &newy);
380 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
381 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
382 ok(newx == correctx && newy == correcty,
383 "Expected drag image size [%d,%d] got [%d,%d]\n",
384 correctx, correcty, newx, newy);
385 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
386 show_image(hwnd, himlNew, 0, max(correctx, correcty), loc, TRUE);
387 pImageList_EndDrag();
390 #undef SIZEX1
391 #undef SIZEY1
392 #undef SIZEX2
393 #undef SIZEY2
394 #undef HOTSPOTS_MAX
395 pImageList_Destroy(himl2);
396 pImageList_Destroy(himl1);
397 DestroyWindow(hwnd);
400 static void test_add_remove(void)
402 HIMAGELIST himl ;
404 HICON hicon1 ;
405 HICON hicon2 ;
406 HICON hicon3 ;
408 /* create an imagelist to play with */
409 himl = pImageList_Create(84, 84, ILC_COLOR16, 0, 3);
410 ok(himl!=0,"failed to create imagelist\n");
412 /* load the icons to add to the image list */
413 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
414 ok(hicon1 != 0, "no hicon1\n");
415 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
416 ok(hicon2 != 0, "no hicon2\n");
417 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
418 ok(hicon3 != 0, "no hicon3\n");
420 /* remove when nothing exists */
421 ok(!pImageList_Remove(himl, 0), "Removed nonexistent icon.\n");
422 /* removing everything from an empty imagelist should succeed */
423 ok(pImageList_Remove(himl, -1), "Removed nonexistent icon\n");
425 /* add three */
426 ok(0 == pImageList_ReplaceIcon(himl, -1, hicon1), "Failed to add icon1.\n");
427 ok(1 == pImageList_ReplaceIcon(himl, -1, hicon2), "Failed to add icon2.\n");
428 ok(2 == pImageList_ReplaceIcon(himl, -1, hicon3), "Failed to add icon3.\n");
430 /* remove an index out of range */
431 ok(!pImageList_Remove(himl, 4711), "removed nonexistent icon\n");
433 /* remove three */
434 ok(pImageList_Remove(himl, 0), "Can't remove 0\n");
435 ok(pImageList_Remove(himl, 0), "Can't remove 0\n");
436 ok(pImageList_Remove(himl, 0), "Can't remove 0\n");
438 /* remove one extra */
439 ok(!pImageList_Remove(himl, 0), "Removed nonexistent icon.\n");
441 /* destroy it */
442 ok(pImageList_Destroy(himl), "Failed to destroy imagelist.\n");
444 ok(-1 == pImageList_ReplaceIcon((HIMAGELIST)0xdeadbeef, -1, hicon1), "Don't crash on bad handle\n");
446 ok(DestroyIcon(hicon1), "Failed to destroy icon 1.\n");
447 ok(DestroyIcon(hicon2), "Failed to destroy icon 2.\n");
448 ok(DestroyIcon(hicon3), "Failed to destroy icon 3.\n");
451 static void test_imagecount(void)
453 HIMAGELIST himl;
455 ok(0 == pImageList_GetImageCount((HIMAGELIST)0xdeadbeef), "don't crash on bad handle\n");
457 if (!pImageList_SetImageCount)
459 win_skip("ImageList_SetImageCount not available\n");
460 return;
463 himl = pImageList_Create(84, 84, ILC_COLOR16, 0, 3);
464 ok(himl != 0, "Failed to create imagelist.\n");
466 ok(pImageList_SetImageCount(himl, 3), "couldn't increase image count\n");
467 ok(pImageList_GetImageCount(himl) == 3, "invalid image count after increase\n");
468 ok(pImageList_SetImageCount(himl, 1), "couldn't decrease image count\n");
469 ok(pImageList_GetImageCount(himl) == 1, "invalid image count after decrease to 1\n");
470 ok(pImageList_SetImageCount(himl, 0), "couldn't decrease image count\n");
471 ok(pImageList_GetImageCount(himl) == 0, "invalid image count after decrease to 0\n");
473 ok(pImageList_Destroy(himl), "Failed to destroy imagelist.\n");
476 static void test_DrawIndirect(void)
478 HIMAGELIST himl;
480 HBITMAP hbm1;
481 HBITMAP hbm2;
482 HBITMAP hbm3;
484 IMAGELISTDRAWPARAMS imldp;
485 HDC hdc;
486 HWND hwndfortest;
488 if (!pImageList_DrawIndirect)
490 win_skip("ImageList_DrawIndirect not available, skipping test\n");
491 return;
494 hwndfortest = create_window();
495 hdc = GetDC(hwndfortest);
496 ok(hdc!=NULL, "couldn't get DC\n");
498 /* create an imagelist to play with */
499 himl = pImageList_Create(48, 48, ILC_COLOR16, 0, 3);
500 ok(himl != 0, "Failed to create imagelist.\n");
502 /* load the icons to add to the image list */
503 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
504 ok(hbm1 != 0, "no bitmap 1\n");
505 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
506 ok(hbm2 != 0, "no bitmap 2\n");
507 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
508 ok(hbm3 != 0, "no bitmap 3\n");
510 /* add three */
511 ok(0 == pImageList_Add(himl, hbm1, 0),"failed to add bitmap 1\n");
512 ok(1 == pImageList_Add(himl, hbm2, 0),"failed to add bitmap 2\n");
514 if (pImageList_SetImageCount)
516 ok(pImageList_SetImageCount(himl,3),"Setimage count failed\n");
517 /*ok(2==ImageList_Add(himl, hbm3, NULL),"failed to add bitmap 3\n"); */
518 ok(pImageList_Replace(himl, 2, hbm3, 0),"failed to replace bitmap 3\n");
521 memset(&imldp, 0, sizeof (imldp));
522 ok(!pImageList_DrawIndirect(&imldp), "zero data succeeded!\n");
523 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
524 ok(!pImageList_DrawIndirect(&imldp), "zero hdc succeeded!\n");
525 imldp.hdcDst = hdc;
526 ok(!pImageList_DrawIndirect(&imldp),"zero himl succeeded!\n");
527 imldp.himl = (HIMAGELIST)0xdeadbeef;
528 ok(!pImageList_DrawIndirect(&imldp),"bad himl succeeded!\n");
529 imldp.himl = himl;
531 force_redraw(hwndfortest);
533 imldp.fStyle = SRCCOPY;
534 imldp.rgbBk = CLR_DEFAULT;
535 imldp.rgbFg = CLR_DEFAULT;
536 imldp.y = 100;
537 imldp.x = 100;
538 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
539 imldp.i ++;
540 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
541 imldp.i ++;
542 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
543 imldp.i ++;
544 ok(!pImageList_DrawIndirect(&imldp),"should fail\n");
546 /* remove three */
547 ok(pImageList_Remove(himl, 0), "removing 1st bitmap\n");
548 ok(pImageList_Remove(himl, 0), "removing 2nd bitmap\n");
549 ok(pImageList_Remove(himl, 0), "removing 3rd bitmap\n");
551 /* destroy it */
552 ok(pImageList_Destroy(himl), "Failed to destroy imagelist.\n");
554 /* bitmaps should not be deleted by the imagelist */
555 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
556 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
557 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
559 ReleaseDC(hwndfortest, hdc);
560 DestroyWindow(hwndfortest);
563 static int get_color_format(HBITMAP bmp)
565 BITMAPINFO bmi;
566 HDC hdc = CreateCompatibleDC(0);
567 HBITMAP hOldBmp = SelectObject(hdc, bmp);
568 int ret;
570 memset(&bmi, 0, sizeof(bmi));
571 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
572 ret = GetDIBits(hdc, bmp, 0, 0, 0, &bmi, DIB_RGB_COLORS);
573 ok(ret, "GetDIBits failed\n");
575 SelectObject(hdc, hOldBmp);
576 DeleteDC(hdc);
577 return bmi.bmiHeader.biBitCount;
580 static void test_merge_colors(void)
582 HIMAGELIST himl[8], hmerge;
583 int sizes[] = { ILC_COLOR, ILC_COLOR | ILC_MASK, ILC_COLOR4, ILC_COLOR8, ILC_COLOR16, ILC_COLOR24, ILC_COLOR32, ILC_COLORDDB };
584 HICON hicon1;
585 IMAGEINFO info;
586 int bpp, i, j;
588 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
589 ok(hicon1 != NULL, "failed to create hicon1\n");
591 for (i = 0; i < 8; i++)
593 himl[i] = pImageList_Create(32, 32, sizes[i], 0, 3);
594 ok(himl[i] != NULL, "failed to create himl[%d]\n", i);
595 ok(0 == pImageList_ReplaceIcon(himl[i], -1, hicon1), "Failed to add icon1 to himl[%d].\n", i);
596 if (i == 0 || i == 1 || i == 7)
598 pImageList_GetImageInfo(himl[i], 0, &info);
599 sizes[i] = get_color_format(info.hbmImage);
602 DestroyIcon(hicon1);
603 for (i = 0; i < 8; i++)
604 for (j = 0; j < 8; j++)
606 hmerge = pImageList_Merge(himl[i], 0, himl[j], 0, 0, 0);
607 ok(hmerge != NULL, "merge himl[%d], himl[%d] failed\n", i, j);
609 pImageList_GetImageInfo(hmerge, 0, &info);
610 bpp = get_color_format(info.hbmImage);
611 /* ILC_COLOR[X] is defined as [X] */
612 if (i == 4 && j == 7)
613 ok(bpp == 16, /* merging ILC_COLOR16 with ILC_COLORDDB seems to be a special case */
614 "wrong biBitCount %d when merging lists %d (%d) and %d (%d)\n", bpp, i, sizes[i], j, sizes[j]);
615 else
616 ok(bpp == (i > j ? sizes[i] : sizes[j]),
617 "wrong biBitCount %d when merging lists %d (%d) and %d (%d)\n", bpp, i, sizes[i], j, sizes[j]);
618 ok(info.hbmMask != 0, "Imagelist merged from %d and %d had no mask\n", i, j);
620 pImageList_Destroy(hmerge);
623 for (i = 0; i < 8; i++)
624 pImageList_Destroy(himl[i]);
627 static void test_merge(void)
629 HIMAGELIST himl1, himl2, hmerge;
630 HICON hicon1;
631 HWND hwnd = create_window();
633 himl1 = pImageList_Create(32, 32, 0, 0, 3);
634 ok(himl1 != NULL,"failed to create himl1\n");
636 himl2 = pImageList_Create(32, 32, 0, 0, 3);
637 ok(himl2 != NULL,"failed to create himl2\n");
639 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
640 ok(hicon1 != NULL, "failed to create hicon1\n");
642 if (!himl1 || !himl2 || !hicon1)
643 return;
645 ok(0 == pImageList_ReplaceIcon(himl2, -1, hicon1), "Failed to add icon1 to himl2.\n");
646 check_bits(hwnd, himl2, 0, 32, icon_bits, "add icon1 to himl2");
648 /* If himl1 has no images, merge still succeeds */
649 hmerge = pImageList_Merge(himl1, -1, himl2, 0, 0, 0);
650 ok(hmerge != NULL, "merge himl1,-1 failed\n");
651 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,-1");
652 pImageList_Destroy(hmerge);
654 hmerge = pImageList_Merge(himl1, 0, himl2, 0, 0, 0);
655 ok(hmerge != NULL,"merge himl1,0 failed\n");
656 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,0");
657 pImageList_Destroy(hmerge);
659 /* Same happens if himl2 is empty */
660 pImageList_Destroy(himl2);
661 himl2 = pImageList_Create(32, 32, 0, 0, 3);
662 ok(himl2 != NULL,"failed to recreate himl2\n");
663 if (!himl2)
664 return;
666 hmerge = pImageList_Merge(himl1, -1, himl2, -1, 0, 0);
667 ok(hmerge != NULL, "merge himl2,-1 failed\n");
668 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,-1");
669 pImageList_Destroy(hmerge);
671 hmerge = pImageList_Merge(himl1, -1, himl2, 0, 0, 0);
672 ok(hmerge != NULL, "merge himl2,0 failed\n");
673 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,0");
674 pImageList_Destroy(hmerge);
676 /* Now try merging an image with itself */
677 ok(0 == pImageList_ReplaceIcon(himl2, -1, hicon1), "Failed to re-add icon1 to himl2.\n");
679 hmerge = pImageList_Merge(himl2, 0, himl2, 0, 0, 0);
680 ok(hmerge != NULL, "merge himl2 with itself failed\n");
681 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2 with itself");
682 pImageList_Destroy(hmerge);
684 /* Try merging 2 different image lists */
685 ok(0 == pImageList_ReplaceIcon(himl1, -1, hicon1), "Failed to add icon1 to himl1.\n");
687 hmerge = pImageList_Merge(himl1, 0, himl2, 0, 0, 0);
688 ok(hmerge != NULL, "merge himl1 with himl2 failed\n");
689 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2");
690 pImageList_Destroy(hmerge);
692 hmerge = pImageList_Merge(himl1, 0, himl2, 0, 8, 16);
693 ok(hmerge != NULL, "merge himl1 with himl2 8,16 failed\n");
694 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2, 8,16");
695 pImageList_Destroy(hmerge);
697 pImageList_Destroy(himl1);
698 pImageList_Destroy(himl2);
699 DestroyIcon(hicon1);
700 DestroyWindow(hwnd);
703 /*********************** imagelist storage test ***************************/
705 #define BMP_CX 48
707 struct memstream
709 IStream IStream_iface;
710 IStream *stream;
713 static struct memstream *impl_from_IStream(IStream *iface)
715 return CONTAINING_RECORD(iface, struct memstream, IStream_iface);
718 static HRESULT STDMETHODCALLTYPE Test_Stream_QueryInterface(IStream *iface, REFIID riid,
719 void **ppvObject)
721 ok(0, "unexpected call\n");
722 return E_NOTIMPL;
725 static ULONG STDMETHODCALLTYPE Test_Stream_AddRef(IStream *iface)
727 ok(0, "unexpected call\n");
728 return 2;
731 static ULONG STDMETHODCALLTYPE Test_Stream_Release(IStream *iface)
733 ok(0, "unexpected call\n");
734 return 1;
737 static HRESULT STDMETHODCALLTYPE Test_Stream_Read(IStream *iface, void *pv, ULONG cb,
738 ULONG *pcbRead)
740 struct memstream *stream = impl_from_IStream(iface);
741 return IStream_Read(stream->stream, pv, cb, pcbRead);
744 static HRESULT STDMETHODCALLTYPE Test_Stream_Write(IStream *iface, const void *pv, ULONG cb,
745 ULONG *pcbWritten)
747 struct memstream *stream = impl_from_IStream(iface);
748 return IStream_Write(stream->stream, pv, cb, pcbWritten);
751 static HRESULT STDMETHODCALLTYPE Test_Stream_Seek(IStream *iface, LARGE_INTEGER offset, DWORD origin,
752 ULARGE_INTEGER *new_pos)
754 struct memstream *stream = impl_from_IStream(iface);
756 if (is_v6_test())
758 ok(origin == STREAM_SEEK_CUR, "Unexpected origin %ld.\n", origin);
759 ok(offset.QuadPart == 0, "Unexpected offset %s.\n", wine_dbgstr_longlong(offset.QuadPart));
760 ok(new_pos != NULL, "Unexpected out position pointer.\n");
761 return IStream_Seek(stream->stream, offset, origin, new_pos);
763 else
765 ok(0, "unexpected call\n");
766 return E_NOTIMPL;
770 static HRESULT STDMETHODCALLTYPE Test_Stream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
772 ok(0, "unexpected call\n");
773 return E_NOTIMPL;
776 static HRESULT STDMETHODCALLTYPE Test_Stream_CopyTo(IStream *iface, IStream *pstm,
777 ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead,
778 ULARGE_INTEGER *pcbWritten)
780 ok(0, "unexpected call\n");
781 return E_NOTIMPL;
784 static HRESULT STDMETHODCALLTYPE Test_Stream_Commit(IStream *iface, DWORD grfCommitFlags)
786 ok(0, "unexpected call\n");
787 return E_NOTIMPL;
790 static HRESULT STDMETHODCALLTYPE Test_Stream_Revert(IStream *iface)
792 ok(0, "unexpected call\n");
793 return E_NOTIMPL;
796 static HRESULT STDMETHODCALLTYPE Test_Stream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset,
797 ULARGE_INTEGER cb, DWORD dwLockType)
799 ok(0, "unexpected call\n");
800 return E_NOTIMPL;
803 static HRESULT STDMETHODCALLTYPE Test_Stream_UnlockRegion(IStream *iface, ULARGE_INTEGER libOffset,
804 ULARGE_INTEGER cb, DWORD dwLockType)
806 ok(0, "unexpected call\n");
807 return E_NOTIMPL;
810 static HRESULT STDMETHODCALLTYPE Test_Stream_Stat(IStream *iface, STATSTG *pstatstg,
811 DWORD grfStatFlag)
813 ok(0, "unexpected call\n");
814 return E_NOTIMPL;
817 static HRESULT STDMETHODCALLTYPE Test_Stream_Clone(IStream *iface, IStream **ppstm)
819 ok(0, "unexpected call\n");
820 return E_NOTIMPL;
823 static const IStreamVtbl Test_Stream_Vtbl =
825 Test_Stream_QueryInterface,
826 Test_Stream_AddRef,
827 Test_Stream_Release,
828 Test_Stream_Read,
829 Test_Stream_Write,
830 Test_Stream_Seek,
831 Test_Stream_SetSize,
832 Test_Stream_CopyTo,
833 Test_Stream_Commit,
834 Test_Stream_Revert,
835 Test_Stream_LockRegion,
836 Test_Stream_UnlockRegion,
837 Test_Stream_Stat,
838 Test_Stream_Clone
841 static void init_memstream(struct memstream *stream)
843 HRESULT hr;
845 stream->IStream_iface.lpVtbl = &Test_Stream_Vtbl;
846 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream->stream);
847 ok(hr == S_OK, "Failed to create a stream, hr %#lx.\n", hr);
850 static void cleanup_memstream(struct memstream *stream)
852 IStream_Release(stream->stream);
855 static INT DIB_GetWidthBytes( int width, int bpp )
857 return ((width * bpp + 31) / 8) & ~3;
860 static ULONG check_bitmap_data(const ILHEAD *header, const char *bm_data,
861 ULONG bm_data_size, const SIZE *bmpsize, INT bpp, const char *comment)
863 const BITMAPFILEHEADER *bmfh = (const BITMAPFILEHEADER *)bm_data;
864 const BITMAPINFOHEADER *bmih = (const BITMAPINFOHEADER *)(bm_data + sizeof(*bmfh));
865 ULONG hdr_size, image_size;
867 hdr_size = sizeof(*bmfh) + sizeof(*bmih);
868 if (bmih->biBitCount <= 8) hdr_size += (1 << bpp) * sizeof(RGBQUAD);
870 ok(bmfh->bfType == (('M' << 8) | 'B'), "wrong bfType 0x%02x\n", bmfh->bfType);
871 ok(bmfh->bfSize == hdr_size, "wrong bfSize 0x%02lx\n", bmfh->bfSize);
872 ok(bmfh->bfReserved1 == 0, "wrong bfReserved1 0x%02x\n", bmfh->bfReserved1);
873 ok(bmfh->bfReserved2 == 0, "wrong bfReserved2 0x%02x\n", bmfh->bfReserved2);
874 ok(bmfh->bfOffBits == hdr_size, "wrong bfOffBits 0x%02lx\n", bmfh->bfOffBits);
876 ok(bmih->biSize == sizeof(*bmih), "wrong biSize %ld\n", bmih->biSize);
877 ok(bmih->biPlanes == 1, "wrong biPlanes %d\n", bmih->biPlanes);
878 ok(bmih->biBitCount == bpp, "wrong biBitCount %d\n", bmih->biBitCount);
880 image_size = DIB_GetWidthBytes(bmih->biWidth, bmih->biBitCount) * bmih->biHeight;
881 ok(bmih->biSizeImage == image_size, "wrong biSizeImage %lu\n", bmih->biSizeImage);
882 ok(bmih->biWidth == bmpsize->cx && bmih->biHeight == bmpsize->cy, "Unexpected bitmap size %ld x %ld, "
883 "expected %ld x %ld\n", bmih->biWidth, bmih->biHeight, bmpsize->cx, bmpsize->cy);
885 if (0)
887 char fname[256];
888 FILE *f;
889 sprintf(fname, "bmp_%s.bmp", comment);
890 f = fopen(fname, "wb");
891 fwrite(bm_data, 1, bm_data_size, f);
892 fclose(f);
895 return hdr_size + image_size;
898 static BOOL is_v6_header(const ILHEAD *header)
900 return (header->usVersion & 0xff00) == 0x600;
903 static void check_ilhead_data(const ILHEAD *ilh, INT cx, INT cy, INT cur, INT max, INT grow, INT flags)
905 INT grow_aligned;
907 ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
908 ok(ilh->usVersion == 0x101 ||
909 ilh->usVersion == 0x600 || /* WinXP/W2k3 */
910 ilh->usVersion == 0x620, "Unknown usVersion %#x.\n", ilh->usVersion);
911 ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
913 grow = max(grow, 1);
914 grow_aligned = (WORD)(grow + 3) & ~3;
916 if (is_v6_header(ilh))
918 grow = (WORD)(grow + 2 + 3) & ~3;
919 ok(ilh->cGrow == grow || broken(ilh->cGrow == grow_aligned) /* XP/Vista */,
920 "Unexpected cGrow %d, expected %d\n", ilh->cGrow, grow);
922 else
924 ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
925 ok(ilh->cGrow == grow_aligned, "Unexpected cGrow %d, expected %d\n", ilh->cGrow, grow_aligned);
928 ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
929 ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
930 ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %lx\n", ilh->bkcolor);
931 ok(ilh->flags == flags || broken(!(ilh->flags & 0xfe) && (flags & 0xfe) == ILC_COLOR4), /* <= w2k */
932 "wrong flags %04x\n", ilh->flags);
933 ok(ilh->ovls[0] == -1, "wrong ovls[0] %04x\n", ilh->ovls[0]);
934 ok(ilh->ovls[1] == -1, "wrong ovls[1] %04x\n", ilh->ovls[1]);
935 ok(ilh->ovls[2] == -1, "wrong ovls[2] %04x\n", ilh->ovls[2]);
936 ok(ilh->ovls[3] == -1, "wrong ovls[3] %04x\n", ilh->ovls[3]);
939 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
941 HDC hdc;
942 BITMAPINFO bmi;
943 HBITMAP hbmp, hbmp_old;
944 HBRUSH hbrush;
945 RECT rc = { 0, 0, cx, cy };
947 hdc = CreateCompatibleDC(0);
949 memset(&bmi, 0, sizeof(bmi));
950 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
951 bmi.bmiHeader.biWidth = cx;
952 bmi.bmiHeader.biHeight = cy;
953 bmi.bmiHeader.biBitCount = 24;
954 bmi.bmiHeader.biPlanes = 1;
955 bmi.bmiHeader.biCompression = BI_RGB;
956 hbmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
958 hbmp_old = SelectObject(hdc, hbmp);
960 hbrush = CreateSolidBrush(color);
961 FillRect(hdc, &rc, hbrush);
962 DeleteObject(hbrush);
964 DrawTextA(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
966 SelectObject(hdc, hbmp_old);
967 DeleteDC(hdc);
969 return hbmp;
972 static inline void imagelist_get_bitmap_size(const ILHEAD *header, SIZE *sz)
974 const int tile_count = 4;
976 if (is_v6_header(header))
978 sz->cx = header->cx;
979 sz->cy = header->cMaxImage * header->cy;
981 else
983 sz->cx = header->cx * tile_count;
984 sz->cy = ((header->cMaxImage + tile_count - 1) / tile_count) * header->cy;
988 /* Grow argument matches what was used when imagelist was created. */
989 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, INT grow,
990 INT flags, const char *comment)
992 INT ret, cxx, cyy, size;
993 struct memstream stream;
994 const ILHEAD *header;
995 LARGE_INTEGER mv;
996 HIMAGELIST himl2;
997 HGLOBAL hglobal;
998 STATSTG stat;
999 char *data;
1000 HRESULT hr;
1001 SIZE bmpsize;
1002 BOOL b;
1004 ret = pImageList_GetImageCount(himl);
1005 ok(ret == cur, "%s: expected image count %d got %d\n", comment, cur, ret);
1007 ret = pImageList_GetIconSize(himl, &cxx, &cyy);
1008 ok(ret, "ImageList_GetIconSize failed\n");
1009 ok(cxx == cx, "%s: wrong cx %d (expected %d)\n", comment, cxx, cx);
1010 ok(cyy == cy, "%s: wrong cy %d (expected %d)\n", comment, cyy, cy);
1012 init_memstream(&stream);
1013 b = pImageList_Write(himl, &stream.IStream_iface);
1014 ok(b, "%s: ImageList_Write failed\n", comment);
1016 hr = GetHGlobalFromStream(stream.stream, &hglobal);
1017 ok(hr == S_OK, "%s: Failed to get hglobal, %#lx\n", comment, hr);
1019 hr = IStream_Stat(stream.stream, &stat, STATFLAG_NONAME);
1020 ok(hr == S_OK, "Stat() failed, hr %#lx.\n", hr);
1022 data = GlobalLock(hglobal);
1024 ok(data != 0, "%s: ImageList_Write didn't write any data\n", comment);
1025 ok(stat.cbSize.LowPart > sizeof(ILHEAD), "%s: ImageList_Write wrote not enough data\n", comment);
1027 header = (const ILHEAD *)data;
1028 check_ilhead_data(header, cx, cy, cur, max, grow, flags);
1029 imagelist_get_bitmap_size(header, &bmpsize);
1030 size = check_bitmap_data(header, data + sizeof(ILHEAD), stat.cbSize.LowPart - sizeof(ILHEAD),
1031 &bmpsize, flags & 0xfe, comment);
1032 if (!is_v6_header(header) && size < stat.cbSize.LowPart - sizeof(ILHEAD)) /* mask is present */
1034 ok( flags & ILC_MASK, "%s: extra data %lu/%u but mask not expected\n", comment, stat.cbSize.LowPart, size );
1035 check_bitmap_data(header, data + sizeof(ILHEAD) + size, stat.cbSize.LowPart - sizeof(ILHEAD) - size,
1036 &bmpsize, 1, comment);
1039 /* rewind and reconstruct from stream */
1040 mv.QuadPart = 0;
1041 IStream_Seek(stream.stream, mv, STREAM_SEEK_SET, NULL);
1042 himl2 = pImageList_Read(&stream.IStream_iface);
1043 ok(himl2 != NULL, "%s: Failed to deserialize imagelist\n", comment);
1044 pImageList_Destroy(himl2);
1046 GlobalUnlock(hglobal);
1047 cleanup_memstream(&stream);
1050 static void image_list_add_bitmap(HIMAGELIST himl, BYTE grey, int i)
1052 char comment[16];
1053 HBITMAP hbm;
1054 int ret;
1056 sprintf(comment, "%d", i);
1057 hbm = create_bitmap(BMP_CX, BMP_CX, RGB(grey, grey, grey), comment);
1058 ret = pImageList_Add(himl, hbm, NULL);
1059 ok(ret != -1, "Failed to add image to imagelist.\n");
1060 DeleteObject(hbm);
1063 static void image_list_init(HIMAGELIST himl, INT grow)
1065 unsigned int i;
1066 static const struct test_data
1068 BYTE grey;
1069 INT cx, cy, cur, max, bpp;
1070 const char *comment;
1071 } td[] =
1073 { 255, BMP_CX, BMP_CX, 1, 2, 24, "total 1" },
1074 { 170, BMP_CX, BMP_CX, 2, 7, 24, "total 2" },
1075 { 85, BMP_CX, BMP_CX, 3, 7, 24, "total 3" },
1076 { 0, BMP_CX, BMP_CX, 4, 7, 24, "total 4" },
1077 { 0, BMP_CX, BMP_CX, 5, 7, 24, "total 5" },
1078 { 85, BMP_CX, BMP_CX, 6, 7, 24, "total 6" },
1079 { 170, BMP_CX, BMP_CX, 7, 12, 24, "total 7" },
1080 { 255, BMP_CX, BMP_CX, 8, 12, 24, "total 8" },
1081 { 255, BMP_CX, BMP_CX, 9, 12, 24, "total 9" },
1082 { 170, BMP_CX, BMP_CX, 10, 12, 24, "total 10" },
1083 { 85, BMP_CX, BMP_CX, 11, 12, 24, "total 11" },
1084 { 0, BMP_CX, BMP_CX, 12, 17, 24, "total 12" },
1085 { 0, BMP_CX, BMP_CX, 13, 17, 24, "total 13" },
1086 { 85, BMP_CX, BMP_CX, 14, 17, 24, "total 14" },
1087 { 170, BMP_CX, BMP_CX, 15, 17, 24, "total 15" },
1088 { 255, BMP_CX, BMP_CX, 16, 17, 24, "total 16" },
1089 { 255, BMP_CX, BMP_CX, 17, 22, 24, "total 17" },
1090 { 170, BMP_CX, BMP_CX, 18, 22, 24, "total 18" },
1091 { 85, BMP_CX, BMP_CX, 19, 22, 24, "total 19" },
1092 { 0, BMP_CX, BMP_CX, 20, 22, 24, "total 20" },
1093 { 0, BMP_CX, BMP_CX, 21, 22, 24, "total 21" },
1094 { 85, BMP_CX, BMP_CX, 22, 27, 24, "total 22" },
1095 { 170, BMP_CX, BMP_CX, 23, 27, 24, "total 23" },
1096 { 255, BMP_CX, BMP_CX, 24, 27, 24, "total 24" }
1099 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, grow, ILC_COLOR24, "total 0");
1101 for (i = 0; i < ARRAY_SIZE(td); i++)
1103 image_list_add_bitmap(himl, td[i].grey, i + 1);
1104 check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, grow, td[i].bpp, td[i].comment);
1108 static void test_imagelist_storage(void)
1110 HIMAGELIST himl;
1111 INT ret, grow;
1112 HBITMAP hbm;
1113 HICON icon;
1115 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
1116 ok(himl != 0, "ImageList_Create failed\n");
1118 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 1, ILC_COLOR24, "empty");
1120 image_list_init(himl, 1);
1121 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, 1, ILC_COLOR24, "orig");
1123 ret = pImageList_Remove(himl, 4);
1124 ok(ret, "ImageList_Remove failed\n");
1125 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, 1, ILC_COLOR24, "1");
1127 ret = pImageList_Remove(himl, 5);
1128 ok(ret, "ImageList_Remove failed\n");
1129 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, 1, ILC_COLOR24, "2");
1131 ret = pImageList_Remove(himl, 6);
1132 ok(ret, "ImageList_Remove failed\n");
1133 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, 1, ILC_COLOR24, "3");
1135 ret = pImageList_Remove(himl, 7);
1136 ok(ret, "ImageList_Remove failed\n");
1137 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 1, ILC_COLOR24, "4");
1139 ret = pImageList_Remove(himl, -2);
1140 ok(!ret, "ImageList_Remove(-2) should fail\n");
1141 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 1, ILC_COLOR24, "5");
1143 ret = pImageList_Remove(himl, 20);
1144 ok(!ret, "ImageList_Remove(20) should fail\n");
1145 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 1, ILC_COLOR24, "6");
1147 ret = pImageList_Remove(himl, -1);
1148 ok(ret, "ImageList_Remove(-1) failed\n");
1149 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, 1, ILC_COLOR24, "7");
1151 ret = pImageList_Destroy(himl);
1152 ok(ret, "ImageList_Destroy failed\n");
1154 /* test ImageList_Create storage allocation */
1156 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 0, 32);
1157 ok(himl != 0, "ImageList_Create failed\n");
1158 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 32, ILC_COLOR24, "init 0 grow 32");
1159 hbm = create_bitmap(BMP_CX, BMP_CX * 9, 0, "9");
1160 ret = pImageList_Add(himl, hbm, NULL);
1161 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1162 check_iml_data(himl, BMP_CX, BMP_CX, 1, 34, 32, ILC_COLOR24, "add 1 x 9");
1163 DeleteObject(hbm);
1164 ret = pImageList_Destroy(himl);
1165 ok(ret, "ImageList_Destroy failed\n");
1167 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 4);
1168 ok(himl != 0, "ImageList_Create failed\n");
1169 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, ILC_COLOR24, "init 4 grow 4");
1170 hbm = create_bitmap(BMP_CX * 9, BMP_CX, 0, "9");
1171 ret = pImageList_Add(himl, hbm, NULL);
1172 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1173 check_iml_data(himl, BMP_CX, BMP_CX, 9, 15, 4, ILC_COLOR24, "add 9 x 1");
1174 ret = pImageList_Add(himl, hbm, NULL);
1175 ok(ret == 9, "ImageList_Add returned %d, expected 9\n", ret);
1176 check_iml_data(himl, BMP_CX, BMP_CX, 18, 25, 4, ILC_COLOR24, "add 9 x 1");
1177 DeleteObject(hbm);
1178 ret = pImageList_Destroy(himl);
1179 ok(ret, "ImageList_Destroy failed\n");
1181 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 207, 209);
1182 ok(himl != 0, "ImageList_Create failed\n");
1183 check_iml_data(himl, BMP_CX, BMP_CX, 0, 208, 209, ILC_COLOR24, "init 207 grow 209");
1184 ret = pImageList_Destroy(himl);
1185 ok(ret, "ImageList_Destroy failed\n");
1187 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 209, 207);
1188 ok(himl != 0, "ImageList_Create failed\n");
1189 check_iml_data(himl, BMP_CX, BMP_CX, 0, 210, 207, ILC_COLOR24, "init 209 grow 207");
1190 ret = pImageList_Destroy(himl);
1191 ok(ret, "ImageList_Destroy failed\n");
1193 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 14, 4);
1194 ok(himl != 0, "ImageList_Create failed\n");
1195 check_iml_data(himl, BMP_CX, BMP_CX, 0, 15, 4, ILC_COLOR24, "init 14 grow 4");
1196 ret = pImageList_Destroy(himl);
1197 ok(ret, "ImageList_Destroy failed\n");
1199 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 5, 9);
1200 ok(himl != 0, "ImageList_Create failed\n");
1201 check_iml_data(himl, BMP_CX, BMP_CX, 0, 6, 9, ILC_COLOR24, "init 5 grow 9");
1202 ret = pImageList_Destroy(himl);
1203 ok(ret, "ImageList_Destroy failed\n");
1205 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 9, 5);
1206 ok(himl != 0, "ImageList_Create failed\n");
1207 check_iml_data(himl, BMP_CX, BMP_CX, 0, 10, 5, ILC_COLOR24, "init 9 grow 5");
1208 ret = pImageList_Destroy(himl);
1209 ok(ret, "ImageList_Destroy failed\n");
1211 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 2, 4);
1212 ok(himl != 0, "ImageList_Create failed\n");
1213 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, ILC_COLOR24, "init 2 grow 4");
1214 ret = pImageList_Destroy(himl);
1215 ok(ret, "ImageList_Destroy failed\n");
1217 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 2);
1218 ok(himl != 0, "ImageList_Create failed\n");
1219 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR24, "init 4 grow 2");
1220 ret = pImageList_Destroy(himl);
1221 ok(ret, "ImageList_Destroy failed\n");
1223 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR8, 4, 2);
1224 ok(himl != 0, "ImageList_Create failed\n");
1225 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR8, "bpp 8");
1226 ret = pImageList_Destroy(himl);
1227 ok(ret, "ImageList_Destroy failed\n");
1229 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4, 4, 2);
1230 ok(himl != 0, "ImageList_Create failed\n");
1231 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR4, "bpp 4");
1232 ret = pImageList_Destroy(himl);
1233 ok(ret, "ImageList_Destroy failed\n");
1235 himl = pImageList_Create(BMP_CX, BMP_CX, 0, 4, 2);
1236 ok(himl != 0, "ImageList_Create failed\n");
1237 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR4, "bpp default");
1238 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1239 ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1240 ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1241 DestroyIcon( icon );
1242 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 2, ILC_COLOR4, "bpp default");
1243 ret = pImageList_Destroy(himl);
1244 ok(ret, "ImageList_Destroy failed\n");
1246 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24|ILC_MASK, 4, 2);
1247 ok(himl != 0, "ImageList_Create failed\n");
1248 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR24|ILC_MASK, "bpp 24 + mask");
1249 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1250 ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1251 ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1252 DestroyIcon( icon );
1253 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 2, ILC_COLOR24|ILC_MASK, "bpp 24 + mask");
1254 ret = pImageList_Destroy(himl);
1255 ok(ret, "ImageList_Destroy failed\n");
1257 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 4, 2);
1258 ok(himl != 0, "ImageList_Create failed\n");
1259 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR4|ILC_MASK, "bpp 4 + mask");
1260 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1261 ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1262 ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1263 DestroyIcon( icon );
1264 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 2, ILC_COLOR4|ILC_MASK, "bpp 4 + mask");
1265 ret = pImageList_Destroy(himl);
1266 ok(ret, "ImageList_Destroy failed\n");
1268 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 99);
1269 ok(himl != 0, "ImageList_Create failed\n");
1270 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99");
1271 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1272 ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1273 ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1274 check_iml_data(himl, BMP_CX, BMP_CX, 2, 3, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 2 icons");
1275 ok( pImageList_ReplaceIcon(himl, -1, icon) == 2, "Failed to add icon\n");
1276 DestroyIcon( icon );
1277 check_iml_data(himl, BMP_CX, BMP_CX, 3, 104, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 3 icons");
1278 ok( pImageList_Remove(himl, -1) == TRUE, "Failed to remove icon.\n");
1279 check_iml_data(himl, BMP_CX, BMP_CX, 0, 100, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 empty");
1280 ok( pImageList_SetImageCount(himl, 22) == TRUE, "Failed to set image count.\n");
1281 check_iml_data(himl, BMP_CX, BMP_CX, 22, 23, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 set count 22");
1282 ok( pImageList_SetImageCount(himl, 0) == TRUE, "Failed to set image count.\n");
1283 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 set count 0");
1284 ok( pImageList_SetImageCount(himl, 42) == TRUE, "Failed to set image count.\n");
1285 check_iml_data(himl, BMP_CX, BMP_CX, 42, 43, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 set count 42");
1286 ret = pImageList_Destroy(himl);
1287 ok(ret, "ImageList_Destroy failed\n");
1289 for (grow = 1; grow <= 16; grow++)
1291 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, grow);
1292 ok(himl != 0, "ImageList_Create failed\n");
1293 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, grow, ILC_COLOR4|ILC_MASK, "grow test");
1294 ret = pImageList_Destroy(himl);
1295 ok(ret, "ImageList_Destroy failed\n");
1298 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, -20);
1299 ok(himl != 0, "ImageList_Create failed\n");
1300 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, -20, ILC_COLOR4|ILC_MASK, "init 2 grow -20");
1301 ret = pImageList_Destroy(himl);
1302 ok(ret, "ImageList_Destroy failed\n");
1304 /* Version 6 implementation hangs on large grow values. */
1305 if (!is_v6_test())
1307 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65536+12);
1308 ok(himl != 0, "ImageList_Create failed\n");
1309 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 65536+12, ILC_COLOR4|ILC_MASK, "init 2 grow 65536+12");
1310 ret = pImageList_Destroy(himl);
1311 ok(ret, "ImageList_Destroy failed\n");
1313 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65535);
1314 ok(himl != 0, "ImageList_Create failed\n");
1315 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 65535, ILC_COLOR4|ILC_MASK, "init 2 grow 65535");
1316 ret = pImageList_Destroy(himl);
1317 ok(ret, "ImageList_Destroy failed\n");
1321 static void test_shell_imagelist(void)
1323 HRESULT (WINAPI *pSHGetImageList)(INT, REFIID, void**);
1324 IImageList *iml = NULL;
1325 HMODULE hShell32;
1326 HRESULT hr;
1327 int out = 0;
1328 RECT rect;
1329 int cx, cy;
1331 /* Try to load function from shell32 */
1332 hShell32 = LoadLibraryA("shell32.dll");
1333 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1335 if (!pSHGetImageList)
1337 win_skip("SHGetImageList not available, skipping test\n");
1338 FreeLibrary(hShell32);
1339 return;
1342 /* Get system image list */
1343 hr = pSHGetImageList(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1344 ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%lx\n", hr);
1346 if (hr != S_OK) {
1347 FreeLibrary(hShell32);
1348 return;
1351 IImageList_GetImageCount(iml, &out);
1352 ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1354 /* Fetch the small icon size */
1355 cx = GetSystemMetrics(SM_CXSMICON);
1356 cy = GetSystemMetrics(SM_CYSMICON);
1358 /* Check icon size matches */
1359 IImageList_GetImageRect(iml, 0, &rect);
1360 ok(((rect.right == cx) && (rect.bottom == cy)),
1361 "IImageList_GetImageRect returned r:%ld,b:%ld\n",
1362 rect.right, rect.bottom);
1364 IImageList_Release(iml);
1365 FreeLibrary(hShell32);
1368 static HBITMAP create_test_bitmap(HDC hdc, UINT width, UINT height, WORD bpp, const UINT32 *bits)
1370 HBITMAP hBitmap;
1371 UINT32 *buffer = NULL;
1372 UINT stride = ((width * bpp + 31) >> 3) & ~3;
1373 BITMAPINFO bitmapInfo = { { sizeof(BITMAPINFOHEADER), width, - height, 1, bpp, BI_RGB, 0, 0, 0, 0, 0 } };
1375 hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1376 ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1378 if(!hBitmap || !buffer)
1380 DeleteObject(hBitmap);
1381 return NULL;
1384 memcpy(buffer, bits, stride * height);
1386 return hBitmap;
1389 static BOOL colour_match(UINT32 x, UINT32 y)
1391 const INT32 tolerance = 8;
1393 const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1394 const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1395 const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1396 const INT32 da = abs((INT32)((x & 0xFF000000) >> 24) - (INT32)((y & 0xFF000000) >> 24));
1398 return (dr <= tolerance && dg <= tolerance && db <= tolerance && da <= tolerance);
1401 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1402 UINT32 expected, int line)
1404 bits[0] = 0xFFFFFFFF;
1405 pImageList_DrawIndirect(ildp);
1406 ok(colour_match(bits[0], expected),
1407 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1408 bits[0], expected, line);
1412 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1413 UINT fStyle, UINT32 expected, int line)
1415 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1416 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1417 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1420 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1421 DWORD dwRop, UINT32 expected, int line)
1423 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1424 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1425 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1428 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1429 UINT fState, DWORD Frame, UINT32 expected, int line)
1431 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1432 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1433 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1436 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1437 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1438 UINT32 broken_expected, int line)
1440 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1441 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1442 bits[0] = 0xFFFFFFFF;
1443 pImageList_DrawIndirect(&ildp);
1444 ok(colour_match(bits[0], expected) ||
1445 broken(colour_match(bits[0], broken_expected)),
1446 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1447 bits[0], expected, line);
1450 static void check_ImageList_DrawIndirect_grayscale(HDC hdc, HIMAGELIST himl, UINT32 *dst_bits, const UINT32 *bitmap_bits,
1451 int index, UINT width, UINT height, int line)
1453 int i;
1454 BOOL has_alpha = FALSE;
1455 IMAGELISTDRAWPARAMS ildp = { sizeof(IMAGELISTDRAWPARAMS), himl, index, hdc,
1456 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_NORMAL, 0, ILS_SATURATE, 0, 0x00000000 };
1457 memset(dst_bits, 0, width * height * sizeof(*dst_bits));
1458 pImageList_DrawIndirect(&ildp);
1460 for (i = 0; i < width * height; i++)
1461 if ((has_alpha = ((bitmap_bits[i] & 0xFF000000) != 0))) break;
1463 for (i = 0; i < width * height; i++)
1465 UINT32 expected, expected_winxp;
1466 UINT32 red = (bitmap_bits[i] & 0x00FF0000) >> 16;
1467 UINT32 green = (bitmap_bits[i] & 0x0000FF00) >> 8;
1468 UINT32 blue = (bitmap_bits[i] & 0x000000FF) >> 0;
1469 UINT32 gray = (red * 299 + green * 587 + blue * 114 + 500) / 1000;
1470 UINT32 gray_winxp = (red + green + blue) / 3;
1471 if (has_alpha)
1473 UINT32 alpha = (bitmap_bits[i] & 0xFF000000) >> 24;
1474 gray = gray * alpha / 0xff * alpha / 0xff;
1475 gray_winxp = gray_winxp * alpha / 0xff * 0x96 / 0xff;
1476 expected = (alpha << 24) | (gray << 16) | (gray << 8) | gray;
1477 expected_winxp = ((alpha * 0x96 / 0xff) << 24) | (gray_winxp << 16) | (gray_winxp << 8) | gray_winxp;
1479 else
1481 expected = ((UINT32)0xFF << 24) | (gray << 16) | (gray << 8) | gray;
1482 expected_winxp = (gray_winxp << 16) | (gray_winxp << 8) | gray_winxp;
1485 ok(colour_match(dst_bits[i], expected) || broken(colour_match(dst_bits[i], expected_winxp)),
1486 "ImageList_DrawIndirect: got Pixel(%d,%d) %08X, Expected a close match to %08X from line %d\n",
1487 i % width, i / width, dst_bits[i], expected, line);
1491 static void test_ImageList_DrawIndirect(void)
1493 const UINT32 bits_image[] = { 0x00ABCDEF, 0x00ABCDEF };
1494 const UINT32 bits_alpha[] = { 0x89ABCDEF, 0x89ABCDEF };
1495 const UINT32 bits_transparent[] = { 0x00ABCDEF, 0x89ABCDEF };
1497 const UINT32 bits_4x4[] = { 0x00ABCDEF, 0x89ABCDEF, 0xFFABCDEF, 0xFEDCBA98,
1498 0x00345678, 0x12345678, 0xFF345678, 0x87654321,
1499 0x00987654, 0xBA987654, 0xFF987654, 0x456789AB,
1500 0x00000000, 0xFF000000, 0xFFFFFFFF, 0x00FFFFFF };
1502 HIMAGELIST himl = NULL;
1503 int ret;
1504 HDC hdcDst = NULL;
1505 HBITMAP hbmOld = NULL, hbmDst = NULL;
1506 HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1507 HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL, hbm4x4 = NULL;
1508 int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1509 UINT32 *bits = 0;
1510 UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1511 IImageList *imgl;
1512 DWORD flags;
1513 HRESULT hr;
1515 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1516 0, 0, 0, 0, 0}};
1518 hdcDst = CreateCompatibleDC(0);
1519 ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1520 if (!hdcDst)
1521 return;
1523 hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1524 ok(hbmMask != 0, "CreateBitmap failed\n");
1526 hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1527 ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1529 himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1530 ok(himl != 0, "ImageList_Create failed\n");
1532 hr = pHIMAGELIST_QueryInterface(himl, &IID_IImageList, (void **) &imgl);
1533 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
1535 /* Add a no-alpha image */
1536 hbmImage = create_test_bitmap(hdcDst, 2, 1, 32, bits_image);
1537 ok(hbmImage != NULL, "Failed to create test bitmap.\n");
1539 iImage = pImageList_Add(himl, hbmImage, hbmMask);
1540 ok(iImage != -1, "ImageList_Add failed\n");
1542 hr = IImageList_GetItemFlags(imgl, 1000, &flags);
1543 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1545 hr = IImageList_GetItemFlags(imgl, 1000, NULL);
1546 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1548 hr = IImageList_GetItemFlags(imgl, iImage, &flags);
1549 ok(hr == S_OK, "Failed to get item flags, hr %#lx.\n", hr);
1550 ok(!flags, "Unexpected flags %#lx.\n", flags);
1552 /* Add an alpha image */
1553 hbmAlphaImage = create_test_bitmap(hdcDst, 2, 1, 32, bits_alpha);
1554 ok(hbmAlphaImage != NULL, "Failed to create test bitmap.\n");
1556 iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1557 ok(iAlphaImage != -1, "ImageList_Add failed\n");
1559 hr = IImageList_GetItemFlags(imgl, iAlphaImage, &flags);
1560 ok(hr == S_OK, "Failed to get item flags, hr %#lx.\n", hr);
1561 ok(flags & ILIF_ALPHA, "Unexpected flags %#lx.\n", flags);
1563 /* Add a transparent alpha image */
1564 hbmTransparentImage = create_test_bitmap(hdcDst, 2, 1, 32, bits_transparent);
1565 ok(hbmTransparentImage != NULL, "Failed to create test bitmap.\n");
1567 iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1568 ok(iTransparentImage != -1, "ImageList_Add failed\n");
1570 hr = IImageList_GetItemFlags(imgl, iTransparentImage, &flags);
1571 ok(hr == S_OK, "Failed to get item flags, hr %#lx.\n", hr);
1572 ok(flags & ILIF_ALPHA, "Unexpected flags %#lx.\n", flags);
1574 /* 32-bit Tests */
1575 bitmapInfo.bmiHeader.biBitCount = 32;
1576 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1577 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1578 hbmOld = SelectObject(hdcDst, hbmDst);
1580 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1581 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1582 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1583 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1584 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1586 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0xFFD3E5F7, __LINE__);
1587 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0xFFD3E5F7, __LINE__);
1589 /* broken on winxp */
1590 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0xFFE8F1FA, 0xFFD4D9DD, __LINE__);
1591 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0xFFE8F1FA, 0xFFB4BDC4, __LINE__);
1593 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0xFFD3E5F7, __LINE__);
1594 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0xFFD3E5F7, __LINE__);
1596 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x895D6F81, __LINE__);
1597 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, ILS_ALPHA, 127, 0xFFE9F2FB, 0xFFAEB7C0, __LINE__);
1598 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, ILS_SATURATE, 0, 0xFFAFAFAF, 0xFFF0F0F0, __LINE__);
1600 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0xFFFFFFFF, __LINE__);
1602 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1603 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0xFF543210, __LINE__);
1605 /* ILD_ROP is ignored when the image has an alpha channel */
1606 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0xFFD3E5F7, __LINE__);
1607 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0xFFD3E5F7, __LINE__);
1609 check_ImageList_DrawIndirect_grayscale(hdcDst, himl, bits, bits_image, iImage, 2, 1, __LINE__);
1610 check_ImageList_DrawIndirect_grayscale(hdcDst, himl, bits, bits_alpha, iAlphaImage, 2, 1, __LINE__);
1611 check_ImageList_DrawIndirect_grayscale(hdcDst, himl, bits, bits_transparent, iTransparentImage, 2, 1, __LINE__);
1613 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, 0xFFABCDEF, __LINE__);
1614 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, 0xFFABCDEF, __LINE__);
1616 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0xFFD5E6F7, __LINE__);
1617 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0xFFE9F2FB, 0xFFAEB7C0, __LINE__);
1618 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0xFFD3E5F7, __LINE__);
1620 /* 4x4 bitmap tests */
1621 SelectObject(hdcDst, hbmOld);
1622 DeleteObject(hbmDst);
1623 bitmapInfo.bmiHeader.biWidth = 4;
1624 bitmapInfo.bmiHeader.biHeight = -4;
1625 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1626 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1627 SelectObject(hdcDst, hbmDst);
1629 hbm4x4 = create_test_bitmap(hdcDst, 4, 4, 32, bits_4x4);
1630 ok(hbm4x4 != NULL, "Failed to create a test bitmap.\n");
1632 ret = pImageList_SetIconSize(himl, 4, 4);
1633 ok(ret, "ImageList_SetIconSize failed\n");
1635 ret = pImageList_Add(himl, hbm4x4, NULL);
1636 ok(ret != -1, "ImageList_Add failed\n");
1638 check_ImageList_DrawIndirect_grayscale(hdcDst, himl, bits, bits_4x4, 0, 4, 4, __LINE__);
1640 if(hbmOld)
1641 SelectObject(hdcDst, hbmOld);
1642 if(hbmDst)
1643 DeleteObject(hbmDst);
1645 DeleteDC(hdcDst);
1647 if(hbmMask)
1648 DeleteObject(hbmMask);
1649 if(hbmInverseMask)
1650 DeleteObject(hbmInverseMask);
1652 if(hbmImage)
1653 DeleteObject(hbmImage);
1654 if(hbmAlphaImage)
1655 DeleteObject(hbmAlphaImage);
1656 if(hbmTransparentImage)
1657 DeleteObject(hbmTransparentImage);
1658 if(hbm4x4)
1659 DeleteObject(hbm4x4);
1661 if(himl)
1663 ret = pImageList_Destroy(himl);
1664 ok(ret, "ImageList_Destroy failed\n");
1668 static void test_iimagelist(void)
1670 IImageList *imgl, *imgl2;
1671 IImageList2 *imagelist;
1672 HIMAGELIST himl;
1673 HRESULT hr;
1674 ULONG ret;
1675 HBITMAP hbm;
1676 int ret2;
1678 if (!pHIMAGELIST_QueryInterface)
1680 win_skip("XP imagelist functions not available\n");
1681 return;
1684 /* test reference counting on destruction */
1685 imgl = (IImageList*)createImageList(32, 32);
1686 ret = IImageList_AddRef(imgl);
1687 ok(ret == 2, "Expected 2, got %ld\n", ret);
1688 ret = pImageList_Destroy((HIMAGELIST)imgl);
1689 ok(ret == TRUE, "Expected TRUE, got %ld\n", ret);
1690 ret = pImageList_Destroy((HIMAGELIST)imgl);
1691 ok(ret == TRUE, "Expected TRUE, got %ld\n", ret);
1692 ret = pImageList_Destroy((HIMAGELIST)imgl);
1693 ok(ret == FALSE, "Expected FALSE, got %ld\n", ret);
1695 imgl = (IImageList*)createImageList(32, 32);
1696 ret = IImageList_AddRef(imgl);
1697 ok(ret == 2, "Expected 2, got %ld\n", ret);
1698 ret = pImageList_Destroy((HIMAGELIST)imgl);
1699 ok(ret == TRUE, "Expected TRUE, got %ld\n", ret);
1700 ret = IImageList_Release(imgl);
1701 ok(ret == 0, "Expected 0, got %ld\n", ret);
1702 ret = pImageList_Destroy((HIMAGELIST)imgl);
1703 ok(ret == FALSE, "Expected FALSE, got %ld\n", ret);
1705 /* ref counting, HIMAGELIST_QueryInterface adds a reference */
1706 imgl = (IImageList*)createImageList(32, 32);
1707 hr = pHIMAGELIST_QueryInterface((HIMAGELIST)imgl, &IID_IImageList, (void**)&imgl2);
1708 ok(hr == S_OK, "got 0x%08lx\n", hr);
1709 ok(imgl2 == imgl, "got different pointer\n");
1710 ret = IImageList_Release(imgl);
1711 ok(ret == 1, "got %lu\n", ret);
1712 IImageList_Release(imgl);
1714 if (!pImageList_CoCreateInstance)
1716 win_skip("Vista imagelist functions not available\n");
1717 return;
1720 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1721 ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%lx\n", hr);
1723 if (hr == S_OK)
1724 IImageList_Release(imgl);
1726 himl = createImageList(32, 32);
1728 if (!himl)
1729 return;
1731 hr = pHIMAGELIST_QueryInterface(himl, &IID_IImageList, (void **) &imgl);
1732 ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%lx\n", hr);
1734 if (hr == S_OK)
1735 IImageList_Release(imgl);
1737 pImageList_Destroy(himl);
1739 /* IImageList2 */
1740 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList2, (void**)&imagelist);
1741 if (hr != S_OK)
1743 win_skip("IImageList2 is not supported.\n");
1744 return;
1747 hr = IImageList2_Initialize(imagelist, BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
1748 ok(hr == S_OK, "got %#lx\n", hr);
1750 check_iml_data((HIMAGELIST)imagelist, BMP_CX, BMP_CX, 0, 2, 1, ILC_COLOR24, "IImageList2 0");
1752 hr = IImageList2_Remove(imagelist, 0);
1753 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
1754 hr = IImageList2_Remove(imagelist, -1);
1755 ok(hr == S_OK, "got %#lx\n", hr);
1757 hbm = CreateBitmap(BMP_CX, BMP_CX, 1, 1, NULL);
1759 ret2 = -1;
1760 hr = IImageList2_Add(imagelist, hbm, 0, &ret2);
1761 ok(hr == S_OK, "got %#lx\n", hr);
1762 ok(ret2 == 0, "got %d\n", ret2);
1764 check_iml_data((HIMAGELIST)imagelist, BMP_CX, BMP_CX, 1, 2, 4, ILC_COLOR24, "IImageList2 1");
1766 ret2 = -1;
1767 hr = IImageList2_Add(imagelist, hbm, 0, &ret2);
1768 ok(hr == S_OK, "got %#lx\n", hr);
1769 ok(ret2 == 1, "got %d\n", ret2);
1771 check_iml_data((HIMAGELIST)imagelist, BMP_CX, BMP_CX, 2, 7, 4, ILC_COLOR24, "IImageList2 2");
1773 hr = IImageList2_Remove(imagelist, 0);
1774 ok(hr == S_OK, "got %#lx\n", hr);
1776 check_iml_data((HIMAGELIST)imagelist, BMP_CX, BMP_CX, 1, 7, 4, ILC_COLOR24, "IImageList2 1");
1778 hr = IImageList2_Remove(imagelist, -1);
1779 ok(hr == S_OK, "got %#lx\n", hr);
1781 check_iml_data((HIMAGELIST)imagelist, BMP_CX, BMP_CX, 0, 4, 1, ILC_COLOR24, "IImageList2 0");
1783 hr = IImageList2_Remove(imagelist, 0);
1784 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
1786 DeleteObject(hbm);
1788 IImageList2_Release(imagelist);
1791 static void test_IImageList_Add_Remove(void)
1793 IImageList *imgl;
1794 HIMAGELIST himl;
1795 HRESULT hr;
1797 HICON hicon1;
1798 HICON hicon2;
1799 HICON hicon3;
1801 int ret;
1803 /* create an imagelist to play with */
1804 himl = pImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1805 ok(himl != 0,"failed to create imagelist\n");
1807 imgl = (IImageList *) himl;
1809 /* load the icons to add to the image list */
1810 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1811 ok(hicon1 != 0, "no hicon1\n");
1812 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1813 ok(hicon2 != 0, "no hicon2\n");
1814 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1815 ok(hicon3 != 0, "no hicon3\n");
1817 /* remove when nothing exists */
1818 hr = IImageList_Remove(imgl, 0);
1819 ok(hr == E_INVALIDARG, "got 0x%08lx\n", hr);
1821 /* removing everything from an empty imagelist should succeed */
1822 hr = IImageList_Remove(imgl, -1);
1823 ok(hr == S_OK, "removed nonexistent icon\n");
1825 /* add three */
1826 ret = -1;
1827 ok( IImageList_ReplaceIcon(imgl, -1, hicon1, &ret) == S_OK && (ret == 0),"failed to add icon1\n");
1828 ret = -1;
1829 ok( IImageList_ReplaceIcon(imgl, -1, hicon2, &ret) == S_OK && (ret == 1),"failed to add icon2\n");
1830 ret = -1;
1831 ok( IImageList_ReplaceIcon(imgl, -1, hicon3, &ret) == S_OK && (ret == 2),"failed to add icon3\n");
1833 /* remove an index out of range */
1834 ok( IImageList_Remove(imgl, 4711) == E_INVALIDARG, "got 0x%08lx\n", hr);
1836 /* remove three */
1837 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1838 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1839 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1841 /* remove one extra */
1842 ok( IImageList_Remove(imgl, 0) == E_INVALIDARG, "got 0x%08lx\n", hr);
1844 IImageList_Release(imgl);
1845 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1846 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1847 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1850 static void test_IImageList_Get_SetImageCount(void)
1852 IImageList *imgl;
1853 HIMAGELIST himl;
1854 HRESULT hr;
1855 INT ret;
1857 /* create an imagelist to play with */
1858 himl = pImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1859 ok(himl != 0,"failed to create imagelist\n");
1861 imgl = (IImageList *) himl;
1863 /* check SetImageCount/GetImageCount */
1864 hr = IImageList_SetImageCount(imgl, 3);
1865 ok(hr == S_OK, "got 0x%08lx\n", hr);
1866 ret = 0;
1867 hr = IImageList_GetImageCount(imgl, &ret);
1868 ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
1869 hr = IImageList_SetImageCount(imgl, 1);
1870 ok(hr == S_OK, "got 0x%08lx\n", hr);
1871 ret = 0;
1872 hr = IImageList_GetImageCount(imgl, &ret);
1873 ok(hr == S_OK && ret == 1, "invalid image count after decrease to 1\n");
1874 hr = IImageList_SetImageCount(imgl, 0);
1875 ok(hr == S_OK, "got 0x%08lx\n", hr);
1876 ret = -1;
1877 hr = IImageList_GetImageCount(imgl, &ret);
1878 ok(hr == S_OK && ret == 0, "invalid image count after decrease to 0\n");
1880 IImageList_Release(imgl);
1883 static void test_IImageList_Draw(void)
1885 IImageList *imgl;
1886 HIMAGELIST himl;
1888 HBITMAP hbm1;
1889 HBITMAP hbm2;
1890 HBITMAP hbm3;
1892 IMAGELISTDRAWPARAMS imldp;
1893 HWND hwndfortest;
1894 HRESULT hr;
1895 HDC hdc;
1896 int ret;
1898 hwndfortest = create_window();
1899 hdc = GetDC(hwndfortest);
1900 ok(hdc!=NULL, "couldn't get DC\n");
1902 /* create an imagelist to play with */
1903 himl = pImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1904 ok(himl!=0,"failed to create imagelist\n");
1906 imgl = (IImageList *) himl;
1908 /* load the icons to add to the image list */
1909 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1910 ok(hbm1 != 0, "no bitmap 1\n");
1911 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1912 ok(hbm2 != 0, "no bitmap 2\n");
1913 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1914 ok(hbm3 != 0, "no bitmap 3\n");
1916 /* add three */
1917 ret = -1;
1918 ok( IImageList_Add(imgl, hbm1, 0, &ret) == S_OK && (ret == 0), "failed to add bitmap 1\n");
1919 ret = -1;
1920 ok( IImageList_Add(imgl, hbm2, 0, &ret) == S_OK && (ret == 1), "failed to add bitmap 2\n");
1922 ok( IImageList_SetImageCount(imgl, 3) == S_OK, "Setimage count failed\n");
1923 ok( IImageList_Replace(imgl, 2, hbm3, 0) == S_OK, "failed to replace bitmap 3\n");
1925 if (0)
1927 /* crashes on native */
1928 IImageList_Draw(imgl, NULL);
1931 memset(&imldp, 0, sizeof (imldp));
1932 hr = IImageList_Draw(imgl, &imldp);
1933 ok( hr == E_INVALIDARG, "got 0x%08lx\n", hr);
1935 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
1936 imldp.hdcDst = hdc;
1937 imldp.himl = himl;
1939 force_redraw(hwndfortest);
1941 imldp.fStyle = SRCCOPY;
1942 imldp.rgbBk = CLR_DEFAULT;
1943 imldp.rgbFg = CLR_DEFAULT;
1944 imldp.y = 100;
1945 imldp.x = 100;
1946 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1947 imldp.i ++;
1948 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1949 imldp.i ++;
1950 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1951 imldp.i ++;
1952 ok( IImageList_Draw(imgl, &imldp) == E_INVALIDARG, "should fail\n");
1954 /* remove three */
1955 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 1st bitmap\n");
1956 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 2nd bitmap\n");
1957 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 3rd bitmap\n");
1959 /* destroy it */
1960 IImageList_Release(imgl);
1962 /* bitmaps should not be deleted by the imagelist */
1963 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1964 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1965 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1967 ReleaseDC(hwndfortest, hdc);
1968 DestroyWindow(hwndfortest);
1971 static void test_IImageList_Merge(void)
1973 HIMAGELIST himl1, himl2;
1974 IImageList *imgl1, *imgl2, *merge;
1975 HICON hicon1;
1976 HWND hwnd = create_window();
1977 HRESULT hr;
1978 int ret;
1980 himl1 = pImageList_Create(32,32,0,0,3);
1981 ok(himl1 != NULL,"failed to create himl1\n");
1983 himl2 = pImageList_Create(32,32,0,0,3);
1984 ok(himl2 != NULL,"failed to create himl2\n");
1986 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1987 ok(hicon1 != NULL, "failed to create hicon1\n");
1989 if (!himl1 || !himl2 || !hicon1)
1990 return;
1992 /* cast to IImageList */
1993 imgl1 = (IImageList *) himl1;
1994 imgl2 = (IImageList *) himl2;
1996 ret = -1;
1997 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl2 failed\n");
1999 if (0)
2001 /* null cases that crash on native */
2002 IImageList_Merge(imgl1, -1, NULL, 0, 0, 0, &IID_IImageList, (void**)&merge);
2003 IImageList_Merge(imgl1, -1, (IUnknown*) imgl2, 0, 0, 0, &IID_IImageList, NULL);
2006 /* If himl1 has no images, merge still succeeds */
2007 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
2008 ok(hr == S_OK, "merge himl1,-1 failed\n");
2009 if (hr == S_OK) IImageList_Release(merge);
2011 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
2012 ok(hr == S_OK, "merge himl1,0 failed\n");
2013 if (hr == S_OK) IImageList_Release(merge);
2015 /* Same happens if himl2 is empty */
2016 IImageList_Release(imgl2);
2017 himl2 = pImageList_Create(32,32,0,0,3);
2018 ok(himl2 != NULL,"failed to recreate himl2\n");
2020 imgl2 = (IImageList *) himl2;
2022 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
2023 ok(hr == S_OK, "merge himl2,-1 failed\n");
2024 if (hr == S_OK) IImageList_Release(merge);
2026 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
2027 ok(hr == S_OK, "merge himl2,0 failed\n");
2028 if (hr == S_OK) IImageList_Release(merge);
2030 /* Now try merging an image with itself */
2031 ret = -1;
2032 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"re-add icon1 to himl2 failed\n");
2034 hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
2035 ok(hr == S_OK, "merge himl2 with itself failed\n");
2036 if (hr == S_OK) IImageList_Release(merge);
2038 /* Try merging 2 different image lists */
2039 ret = -1;
2040 ok( IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl1 failed\n");
2042 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
2043 ok(hr == S_OK, "merge himl1 with himl2 failed\n");
2044 if (hr == S_OK) IImageList_Release(merge);
2046 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
2047 ok(hr == S_OK, "merge himl1 with himl2 8,16 failed\n");
2048 if (hr == S_OK) IImageList_Release(merge);
2050 IImageList_Release(imgl1);
2051 IImageList_Release(imgl2);
2053 DestroyIcon(hicon1);
2054 DestroyWindow(hwnd);
2057 static void test_iconsize(void)
2059 HIMAGELIST himl;
2060 INT cx, cy;
2061 BOOL ret;
2063 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2064 /* null pointers, not zero imagelist dimensions */
2065 ret = pImageList_GetIconSize(himl, NULL, NULL);
2066 ok(!ret, "got %d\n", ret);
2068 /* doesn't touch return pointers */
2069 cx = 0x1abe11ed;
2070 ret = pImageList_GetIconSize(himl, &cx, NULL);
2071 ok(!ret, "got %d\n", ret);
2072 ok(cx == 0x1abe11ed, "got %d\n", cx);
2074 cy = 0x1abe11ed;
2075 ret = pImageList_GetIconSize(himl, NULL, &cy);
2076 ok(!ret, "got %d\n", ret);
2077 ok(cy == 0x1abe11ed, "got %d\n", cy);
2079 pImageList_Destroy(himl);
2081 ret = pImageList_GetIconSize((HIMAGELIST)0xdeadbeef, &cx, &cy);
2082 ok(!ret, "got %d\n", ret);
2085 static void test_create_destroy(void)
2087 HIMAGELIST himl;
2088 INT cx, cy;
2089 BOOL rc;
2090 INT ret;
2092 /* list with zero or negative image dimensions */
2093 himl = pImageList_Create(0, 0, ILC_COLOR16, 0, 3);
2094 ok(himl == NULL, "got %p\n", himl);
2096 himl = pImageList_Create(0, 16, ILC_COLOR16, 0, 3);
2097 ok(himl == NULL, "got %p\n", himl);
2099 himl = pImageList_Create(16, 0, ILC_COLOR16, 0, 3);
2100 ok(himl == NULL, "got %p\n", himl);
2102 himl = pImageList_Create(16, -1, ILC_COLOR16, 0, 3);
2103 ok(himl == NULL, "got %p\n", himl);
2105 himl = pImageList_Create(-1, 16, ILC_COLOR16, 0, 3);
2106 ok(himl == NULL, "got %p\n", himl);
2108 rc = pImageList_Destroy((HIMAGELIST)0xdeadbeef);
2109 ok(rc == FALSE, "ImageList_Destroy(0xdeadbeef) should fail and not crash\n");
2111 /* DDB image lists */
2112 himl = pImageList_Create(0, 14, ILC_COLORDDB, 4, 4);
2113 ok(himl != NULL, "got %p\n", himl);
2115 pImageList_GetIconSize(himl, &cx, &cy);
2116 ok (cx == 0, "Wrong cx (%i)\n", cx);
2117 ok (cy == 14, "Wrong cy (%i)\n", cy);
2118 pImageList_Destroy(himl);
2120 himl = pImageList_Create(0, 0, ILC_COLORDDB, 4, 4);
2121 ok(himl != NULL, "got %p\n", himl);
2122 pImageList_GetIconSize(himl, &cx, &cy);
2123 ok (cx == 0, "Wrong cx (%i)\n", cx);
2124 ok (cy == 0, "Wrong cy (%i)\n", cy);
2125 pImageList_Destroy(himl);
2127 himl = pImageList_Create(0, 0, ILC_COLORDDB, 0, 4);
2128 ok(himl != NULL, "got %p\n", himl);
2129 pImageList_GetIconSize(himl, &cx, &cy);
2130 ok (cx == 0, "Wrong cx (%i)\n", cx);
2131 ok (cy == 0, "Wrong cy (%i)\n", cy);
2133 pImageList_SetImageCount(himl, 3);
2134 ret = pImageList_GetImageCount(himl);
2135 ok(ret == 3, "Unexpected image count after increase\n");
2137 /* Trying to actually add an image causes a crash on Windows */
2138 pImageList_Destroy(himl);
2140 /* Negative values fail */
2141 himl = pImageList_Create(-1, -1, ILC_COLORDDB, 4, 4);
2142 ok(himl == NULL, "got %p\n", himl);
2143 himl = pImageList_Create(-1, 1, ILC_COLORDDB, 4, 4);
2144 ok(himl == NULL, "got %p\n", himl);
2145 himl = pImageList_Create(1, -1, ILC_COLORDDB, 4, 4);
2146 ok(himl == NULL, "got %p\n", himl);
2149 static void check_color_table(const char *name, HDC hdc, HIMAGELIST himl, UINT ilc,
2150 RGBQUAD *expect, RGBQUAD *broken_expect)
2152 IMAGEINFO info;
2153 INT ret;
2154 char bmi_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
2155 BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
2156 int i, depth = ilc & 0xfe;
2158 ret = pImageList_GetImageInfo(himl, 0, &info);
2159 ok(ret, "got %d\n", ret);
2160 ok(info.hbmImage != NULL, "got %p\n", info.hbmImage);
2162 memset(bmi_buffer, 0, sizeof(bmi_buffer));
2163 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
2164 ret = GetDIBits(hdc, info.hbmImage, 0, 0, NULL, bmi, DIB_RGB_COLORS);
2165 ok(ret, "got %d\n", ret);
2166 ok(bmi->bmiHeader.biBitCount == depth, "got %d\n", bmi->bmiHeader.biBitCount);
2168 ret = GetDIBits(hdc, info.hbmImage, 0, 0, NULL, bmi, DIB_RGB_COLORS);
2169 ok(ret, "got %d\n", ret);
2170 ok(bmi->bmiHeader.biBitCount == depth, "got %d\n", bmi->bmiHeader.biBitCount);
2172 for (i = 0; i < (1 << depth); i++)
2173 ok((bmi->bmiColors[i].rgbRed == expect[i].rgbRed &&
2174 bmi->bmiColors[i].rgbGreen == expect[i].rgbGreen &&
2175 bmi->bmiColors[i].rgbBlue == expect[i].rgbBlue) ||
2176 (broken_expect && broken(bmi->bmiColors[i].rgbRed == broken_expect[i].rgbRed &&
2177 bmi->bmiColors[i].rgbGreen == broken_expect[i].rgbGreen &&
2178 bmi->bmiColors[i].rgbBlue == broken_expect[i].rgbBlue)),
2179 "%d: %s: got color[%d] %02x %02x %02x expect %02x %02x %02x\n", depth, name, i,
2180 bmi->bmiColors[i].rgbRed, bmi->bmiColors[i].rgbGreen, bmi->bmiColors[i].rgbBlue,
2181 expect[i].rgbRed, expect[i].rgbGreen, expect[i].rgbBlue);
2184 static void get_default_color_table(HDC hdc, int bpp, RGBQUAD *table)
2186 char bmi_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
2187 BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
2188 HBITMAP tmp;
2189 int i;
2190 HPALETTE pal;
2191 PALETTEENTRY entries[256];
2193 switch (bpp)
2195 case 4:
2196 tmp = CreateBitmap( 1, 1, 1, 1, NULL );
2197 memset(bmi_buffer, 0, sizeof(bmi_buffer));
2198 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
2199 bmi->bmiHeader.biHeight = 1;
2200 bmi->bmiHeader.biWidth = 1;
2201 bmi->bmiHeader.biBitCount = bpp;
2202 bmi->bmiHeader.biPlanes = 1;
2203 bmi->bmiHeader.biCompression = BI_RGB;
2204 GetDIBits( hdc, tmp, 0, 0, NULL, bmi, DIB_RGB_COLORS );
2206 memcpy(table, bmi->bmiColors, (1 << bpp) * sizeof(RGBQUAD));
2207 table[7] = bmi->bmiColors[8];
2208 table[8] = bmi->bmiColors[7];
2209 DeleteObject( tmp );
2210 break;
2212 case 8:
2213 pal = CreateHalftonePalette(hdc);
2214 GetPaletteEntries(pal, 0, 256, entries);
2215 for (i = 0; i < 256; i++)
2217 table[i].rgbRed = entries[i].peRed;
2218 table[i].rgbGreen = entries[i].peGreen;
2219 table[i].rgbBlue = entries[i].peBlue;
2220 table[i].rgbReserved = 0;
2222 DeleteObject(pal);
2223 break;
2225 default:
2226 ok(0, "unhandled depth %d\n", bpp);
2230 static void test_color_table(UINT ilc)
2232 HIMAGELIST himl;
2233 INT ret;
2234 char bmi_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
2235 BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
2236 HDC hdc = CreateCompatibleDC(0);
2237 HBITMAP dib4, dib8, dib32;
2238 RGBQUAD rgb[256], default_table[256];
2240 get_default_color_table(hdc, ilc & 0xfe, default_table);
2242 himl = pImageList_Create(16, 16, ilc, 0, 3);
2243 ok(himl != NULL, "got %p\n", himl);
2245 memset(bmi_buffer, 0, sizeof(bmi_buffer));
2246 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
2247 bmi->bmiHeader.biHeight = 16;
2248 bmi->bmiHeader.biWidth = 16;
2249 bmi->bmiHeader.biBitCount = 8;
2250 bmi->bmiHeader.biPlanes = 1;
2251 bmi->bmiHeader.biCompression = BI_RGB;
2252 bmi->bmiColors[0].rgbRed = 0xff;
2253 bmi->bmiColors[1].rgbGreen = 0xff;
2254 bmi->bmiColors[2].rgbBlue = 0xff;
2256 dib8 = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
2258 bmi->bmiHeader.biBitCount = 4;
2259 bmi->bmiColors[0].rgbRed = 0xff;
2260 bmi->bmiColors[0].rgbGreen = 0x00;
2261 bmi->bmiColors[0].rgbBlue = 0xff;
2262 bmi->bmiColors[1].rgbRed = 0xff;
2263 bmi->bmiColors[1].rgbGreen = 0xff;
2264 bmi->bmiColors[1].rgbBlue = 0x00;
2265 bmi->bmiColors[2].rgbRed = 0x00;
2266 bmi->bmiColors[2].rgbGreen = 0xff;
2267 bmi->bmiColors[2].rgbBlue = 0xff;
2269 dib4 = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
2271 bmi->bmiHeader.biBitCount = 32;
2273 dib32 = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
2275 /* add 32 first then 8. This won't set the color table */
2276 ret = pImageList_Add(himl, dib32, NULL);
2277 ok(ret == 0, "got %d\n", ret);
2278 ret = pImageList_Add(himl, dib8, NULL);
2279 ok(ret == 1, "got %d\n", ret);
2281 check_color_table("add 32, 8", hdc, himl, ilc, default_table, NULL);
2283 /* since the previous _Adds didn't set the color table, this one will */
2284 ret = pImageList_Remove(himl, -1);
2285 ok(ret, "got %d\n", ret);
2286 ret = pImageList_Add(himl, dib8, NULL);
2287 ok(ret == 0, "got %d\n", ret);
2289 memset(rgb, 0, sizeof(rgb));
2290 rgb[0].rgbRed = 0xff;
2291 rgb[1].rgbGreen = 0xff;
2292 rgb[2].rgbBlue = 0xff;
2293 check_color_table("remove all, add 8", hdc, himl, ilc, rgb, default_table);
2295 /* remove all, add 4. Color table remains the same since it's implicitly
2296 been set by the previous _Add */
2297 ret = pImageList_Remove(himl, -1);
2298 ok(ret, "got %d\n", ret);
2299 ret = pImageList_Add(himl, dib4, NULL);
2300 ok(ret == 0, "got %d\n", ret);
2301 check_color_table("remove all, add 4", hdc, himl, ilc, rgb, default_table);
2303 pImageList_Destroy(himl);
2304 himl = pImageList_Create(16, 16, ilc, 0, 3);
2305 ok(himl != NULL, "got %p\n", himl);
2307 /* add 4 */
2308 ret = pImageList_Add(himl, dib4, NULL);
2309 ok(ret == 0, "got %d\n", ret);
2311 memset(rgb, 0, 16 * sizeof(rgb[0]));
2312 rgb[0].rgbRed = 0xff;
2313 rgb[0].rgbBlue = 0xff;
2314 rgb[1].rgbRed = 0xff;
2315 rgb[1].rgbGreen = 0xff;
2316 rgb[2].rgbGreen = 0xff;
2317 rgb[2].rgbBlue = 0xff;
2318 memcpy(rgb + 16, default_table + 16, 240 * sizeof(rgb[0]));
2320 check_color_table("add 4", hdc, himl, ilc, rgb, default_table);
2322 pImageList_Destroy(himl);
2323 himl = pImageList_Create(16, 16, ilc, 0, 3);
2324 ok(himl != NULL, "got %p\n", himl);
2326 /* set color table, add 8 */
2327 ret = pImageList_Remove(himl, -1);
2328 ok(ret, "got %d\n", ret);
2329 memset(rgb, 0, sizeof(rgb));
2330 rgb[0].rgbRed = 0xcc;
2331 rgb[1].rgbBlue = 0xcc;
2332 ret = pImageList_SetColorTable(himl, 0, 2, rgb);
2333 ok(ret == 2, "got %d\n", ret);
2334 /* the table is set, so this doesn't change it */
2335 ret = pImageList_Add(himl, dib8, NULL);
2336 ok(ret == 0, "got %d\n", ret);
2338 memcpy(rgb + 2, default_table + 2, 254 * sizeof(rgb[0]));
2339 check_color_table("SetColorTable", hdc, himl, ilc, rgb, NULL);
2341 DeleteObject(dib32);
2342 DeleteObject(dib8);
2343 DeleteObject(dib4);
2344 DeleteDC(hdc);
2345 pImageList_Destroy(himl);
2348 static void test_copy(void)
2350 HIMAGELIST dst, src;
2351 BOOL ret;
2352 int count;
2354 dst = pImageList_Create(5, 11, ILC_COLOR, 1, 1);
2355 count = pImageList_GetImageCount(dst);
2356 ok(!count, "ImageList not empty.\n");
2357 src = createImageList(7, 13);
2358 count = pImageList_GetImageCount(src);
2359 ok(count > 2, "Tests need an ImageList with more than 2 images\n");
2361 /* ImageList_Copy() cannot copy between two ImageLists */
2362 ret = pImageList_Copy(dst, 0, src, 2, ILCF_MOVE);
2363 ok(!ret, "ImageList_Copy() should have returned FALSE\n");
2364 count = pImageList_GetImageCount(dst);
2365 ok(count == 0, "Expected no image in dst ImageList, got %d\n", count);
2367 pImageList_Destroy(dst);
2368 pImageList_Destroy(src);
2371 static void test_loadimage(void)
2373 HIMAGELIST list;
2374 DWORD flags;
2376 list = pImageList_LoadImageW( hinst, MAKEINTRESOURCEW(IDB_BITMAP_128x15), 16, 1, CLR_DEFAULT,
2377 IMAGE_BITMAP, LR_CREATEDIBSECTION );
2378 ok( list != NULL, "got %p\n", list );
2379 flags = pImageList_GetFlags( list );
2380 ok( flags == (ILC_COLOR4 | ILC_MASK), "got %08lx\n", flags );
2381 pImageList_Destroy( list );
2383 list = pImageList_LoadImageW( hinst, MAKEINTRESOURCEW(IDB_BITMAP_128x15), 16, 1, CLR_NONE,
2384 IMAGE_BITMAP, LR_CREATEDIBSECTION );
2385 ok( list != NULL, "got %p\n", list );
2386 flags = pImageList_GetFlags( list );
2387 ok( flags == ILC_COLOR4, "got %08lx\n", flags );
2388 pImageList_Destroy( list );
2391 #define GetAValue(argb) ((BYTE) ((argb) >> 24))
2393 static void get_image_bits(HIMAGELIST himl, int index, int width, int height, UINT32 *bits)
2395 HBITMAP hbm_dst;
2396 void *bitmap_bits;
2397 BITMAPINFO bitmap_info = {{sizeof(BITMAPINFOHEADER), width, height, 1, 32, BI_RGB, 0, 0, 0, 0, 0}};
2399 HDC hdc_dst = CreateCompatibleDC(0);
2400 hbm_dst = CreateDIBSection(hdc_dst, &bitmap_info, DIB_RGB_COLORS, &bitmap_bits, NULL, 0);
2401 SelectObject(hdc_dst, hbm_dst);
2403 pImageList_Draw(himl, index, hdc_dst, 0, 0, ILD_TRANSPARENT);
2404 memcpy(bits, bitmap_bits, (size_t)(width * height * 32 / 8));
2406 DeleteObject(hbm_dst);
2407 DeleteDC(hdc_dst);
2410 static void test_alpha(void)
2412 /* each line is a 2*1 bitmap */
2413 const static UINT32 test_bitmaps[] =
2415 0x00654321, 0x00ABCDEF,
2416 0x00654321, 0x00654321,
2417 0x00ABCDEF, 0x00654321,
2418 0x00ABCDEF, 0x00ABCDEF,
2419 0x00654321, 0x01ABCDEF,
2420 0x01654321, 0x00ABCDEF,
2421 0x00654321, 0xFFABCDEF,
2422 0x00654321, 0x89ABCDEF,
2423 0xFF654321, 0x00ABCDEF,
2424 0xFF654321, 0xFFABCDEF,
2425 0xFF654321, 0x89ABCDEF,
2426 0x87654321, 0x00ABCDEF,
2427 0x87654321, 0xFFABCDEF,
2428 0x87654321, 0x89ABCDEF
2430 const static BYTE mask_bits = 0xAA;
2432 int i, ret;
2433 HDC hdc;
2434 HBITMAP hbm_test, hbm_mask;
2435 HIMAGELIST himl;
2436 UINT32 bits[2];
2438 hdc = CreateCompatibleDC(0);
2439 himl = pImageList_Create(2, 1, ILC_COLOR32 | ILC_MASK, 0, 15);
2441 for (i = 0; i < ARRAY_SIZE(test_bitmaps); i += 2)
2443 hbm_test = create_test_bitmap(hdc, 2, 1, 32, test_bitmaps + i);
2444 ret = pImageList_AddMasked(himl, hbm_test, RGB(0x65,0x43,0x21));
2445 ok(ret == i / 2, "ImageList_AddMasked returned %d, expected %d\n", ret, i / 2);
2446 DeleteObject(hbm_test);
2448 get_image_bits(himl, i / 2, 2, 1, bits);
2449 ok(GetAValue(bits[0]) == GetAValue(test_bitmaps[i]) && GetAValue(bits[1]) == GetAValue(test_bitmaps[i + 1]),
2450 "Bitmap [%08X, %08X] returned alpha value [%02X, %02X], expected [%02X, %02X]\n",
2451 test_bitmaps[i], test_bitmaps[i + 1], GetAValue(bits[0]), GetAValue(bits[1]),
2452 GetAValue(test_bitmaps[i]), GetAValue(test_bitmaps[i + 1]));
2454 /* If all alpha values are zero, the image is considered to have no alpha and gets masked */
2455 if (!GetAValue(bits[0]) && !GetAValue(bits[1]))
2456 ok(bits[0] == (test_bitmaps[i] == 0x654321 ? 0 : test_bitmaps[i]) &&
2457 bits[1] == (test_bitmaps[i + 1] == 0x654321 ? 0 : test_bitmaps[i + 1]),
2458 "Bitmap [%08X, %08X] returned [%08X, %08X], expected [%08X, %08X]\n",
2459 test_bitmaps[i], test_bitmaps[i + 1], bits[0], bits[1],
2460 test_bitmaps[i] == 0x654321 ? 0 : test_bitmaps[i],
2461 test_bitmaps[i + 1] == 0x654321 ? 0 : test_bitmaps[i + 1]);
2464 pImageList_Destroy(himl);
2465 hbm_mask = CreateBitmap(2, 1, 1, 1, &mask_bits);
2466 himl = pImageList_Create(2, 1, ILC_COLOR32 | ILC_MASK, 0, 15);
2468 for (i = 0; i < ARRAY_SIZE(test_bitmaps); i += 2)
2470 hbm_test = create_test_bitmap(hdc, 2, 1, 32, test_bitmaps + i);
2471 ret = pImageList_Add(himl, hbm_test, hbm_mask);
2472 ok(ret == i / 2, "ImageList_Add returned %d, expected %d\n", ret, i / 2);
2473 DeleteObject(hbm_test);
2475 get_image_bits(himl, i / 2, 2, 1, bits);
2476 ok(GetAValue(bits[0]) == GetAValue(test_bitmaps[i]) && GetAValue(bits[1]) == GetAValue(test_bitmaps[i + 1]),
2477 "Bitmap [%08X, %08X] returned alpha value [%02X, %02X], expected [%02X, %02X]\n",
2478 test_bitmaps[i], test_bitmaps[i + 1], GetAValue(bits[0]), GetAValue(bits[1]),
2479 GetAValue(test_bitmaps[i]), GetAValue(test_bitmaps[i + 1]));
2481 /* If all alpha values are zero, the image is considered to have no alpha and gets masked */
2482 if (!GetAValue(bits[0]) && !GetAValue(bits[1]))
2483 ok(!bits[0] && bits[1] == test_bitmaps[i + 1],
2484 "Bitmap [%08X, %08X] returned [%08X, %08X], expected [%08X, %08X]\n",
2485 test_bitmaps[i], test_bitmaps[i + 1], bits[0], bits[1], 0, test_bitmaps[i + 1]);
2486 else
2488 if (GetAValue(bits[0]) >= 0x80)
2489 ok(bits[0] & 0x00FFFFFF, "Bitmap [%08X, %08X] has alpha and masked first pixel [%08X]\n",
2490 test_bitmaps[i], test_bitmaps[i + 1], bits[0]);
2494 pImageList_Destroy(himl);
2495 DeleteObject(hbm_mask);
2496 DeleteDC(hdc);
2499 static void test_IImageList_Clone(void)
2501 IImageList *imgl, *imgl2;
2502 HIMAGELIST himl;
2503 HRESULT hr;
2504 ULONG ref;
2506 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2507 imgl = (IImageList*)himl;
2509 if (0)
2511 /* crashes on native */
2512 IImageList_Clone(imgl, &IID_IImageList, NULL);
2515 hr = IImageList_Clone(imgl, &IID_IImageList, (void**)&imgl2);
2516 ok(hr == S_OK, "got 0x%08lx\n", hr);
2517 ref = IImageList_Release(imgl2);
2518 ok(ref == 0, "got %lu\n", ref);
2520 IImageList_Release(imgl);
2523 static void test_IImageList_GetBkColor(void)
2525 IImageList *imgl;
2526 HIMAGELIST himl;
2527 COLORREF color;
2528 HRESULT hr;
2530 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2531 imgl = (IImageList*)himl;
2533 if (0)
2535 /* crashes on native */
2536 IImageList_GetBkColor(imgl, NULL);
2539 hr = IImageList_GetBkColor(imgl, &color);
2540 ok(hr == S_OK, "got 0x%08lx\n", hr);
2542 IImageList_Release(imgl);
2545 static void test_IImageList_SetBkColor(void)
2547 IImageList *imgl;
2548 HIMAGELIST himl;
2549 COLORREF color;
2550 HRESULT hr;
2552 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2553 imgl = (IImageList*)himl;
2555 if (0)
2557 /* crashes on native */
2558 IImageList_SetBkColor(imgl, RGB(0, 0, 0), NULL);
2561 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
2562 ok(hr == S_OK, "got 0x%08lx\n", hr);
2564 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
2565 ok(hr == S_OK, "got 0x%08lx\n", hr);
2567 color = 0xdeadbeef;
2568 hr = IImageList_GetBkColor(imgl, &color);
2569 ok(hr == S_OK, "got 0x%08lx\n", hr);
2570 ok(color == CLR_NONE, "got %lx\n", color);
2572 IImageList_Release(imgl);
2575 static void test_IImageList_GetImageCount(void)
2577 IImageList *imgl;
2578 HIMAGELIST himl;
2579 int count;
2580 HRESULT hr;
2582 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2583 imgl = (IImageList*)himl;
2585 if (0)
2587 /* crashes on native */
2588 IImageList_GetImageCount(imgl, NULL);
2591 count = -1;
2592 hr = IImageList_GetImageCount(imgl, &count);
2593 ok(hr == S_OK, "got 0x%08lx\n", hr);
2594 ok(count == 0, "got %d\n", count);
2596 IImageList_Release(imgl);
2599 static void test_IImageList_GetIconSize(void)
2601 IImageList *imgl;
2602 HIMAGELIST himl;
2603 int cx, cy;
2604 HRESULT hr;
2606 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2607 imgl = (IImageList*)himl;
2609 hr = IImageList_GetIconSize(imgl, NULL, NULL);
2610 ok(hr == E_INVALIDARG, "got 0x%08lx\n", hr);
2612 hr = IImageList_GetIconSize(imgl, &cx, NULL);
2613 ok(hr == E_INVALIDARG, "got 0x%08lx\n", hr);
2615 hr = IImageList_GetIconSize(imgl, NULL, &cy);
2616 ok(hr == E_INVALIDARG, "got 0x%08lx\n", hr);
2618 IImageList_Release(imgl);
2621 static void test_ImageList_WriteEx(void)
2623 HIMAGELIST himl;
2624 IStream *stream;
2625 HRESULT hr;
2627 himl = pImageList_Create(24, 24, ILC_COLOR24, 1, 1);
2628 ok(himl != 0, "Failed to create an imagelist.\n");
2630 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2631 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2633 hr = pImageList_WriteEx(himl, ILP_NORMAL, stream);
2634 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2636 hr = pImageList_WriteEx(himl, ILP_DOWNLEVEL, stream);
2637 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2639 IStream_Release(stream);
2640 pImageList_Destroy(himl);
2643 static void init_functions(void)
2645 HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
2647 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
2648 #define X2(f, ord) p##f = (void*)GetProcAddress(hComCtl32, (const char *)ord);
2649 X(ImageList_Create);
2650 X(ImageList_Destroy);
2651 X(ImageList_Add);
2652 X(ImageList_AddMasked);
2653 X(ImageList_DrawIndirect);
2654 X(ImageList_SetImageCount);
2655 X2(ImageList_SetColorTable, 390);
2656 X(ImageList_GetFlags);
2657 X(ImageList_BeginDrag);
2658 X(ImageList_GetDragImage);
2659 X(ImageList_EndDrag);
2660 X(ImageList_GetImageCount);
2661 X(ImageList_SetDragCursorImage);
2662 X(ImageList_GetIconSize);
2663 X(ImageList_SetIconSize);
2664 X(ImageList_Remove);
2665 X(ImageList_ReplaceIcon);
2666 X(ImageList_Replace);
2667 X(ImageList_Merge);
2668 X(ImageList_GetImageInfo);
2669 X(ImageList_Write);
2670 X(ImageList_WriteEx);
2671 X(ImageList_Read);
2672 X(ImageList_Copy);
2673 X(ImageList_LoadImageW);
2674 X(ImageList_CoCreateInstance);
2675 X(HIMAGELIST_QueryInterface);
2676 X(ImageList_Draw);
2677 #undef X
2678 #undef X2
2681 START_TEST(imagelist)
2683 ULONG_PTR ctx_cookie;
2684 HANDLE hCtx;
2686 init_functions();
2688 hinst = GetModuleHandleA(NULL);
2690 test_create_destroy();
2691 test_begindrag();
2692 test_hotspot();
2693 test_add_remove();
2694 test_imagecount();
2695 test_DrawIndirect();
2696 test_merge();
2697 test_merge_colors();
2698 test_imagelist_storage();
2699 test_iconsize();
2700 test_color_table(ILC_COLOR4);
2701 test_color_table(ILC_COLOR8);
2702 test_copy();
2703 test_loadimage();
2705 /* Now perform v6 tests */
2706 if (!load_v6_module(&ctx_cookie, &hCtx))
2707 return;
2709 init_functions();
2711 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2713 /* Do v6.0 tests */
2714 test_add_remove();
2715 test_imagecount();
2716 test_DrawIndirect();
2717 test_merge();
2718 test_imagelist_storage();
2719 test_iconsize();
2720 test_color_table(ILC_COLOR4);
2721 test_color_table(ILC_COLOR8);
2722 test_copy();
2723 test_loadimage();
2724 test_alpha();
2726 test_ImageList_DrawIndirect();
2727 test_shell_imagelist();
2728 test_iimagelist();
2730 test_IImageList_Add_Remove();
2731 test_IImageList_Get_SetImageCount();
2732 test_IImageList_Draw();
2733 test_IImageList_Merge();
2734 test_IImageList_Clone();
2735 test_IImageList_GetBkColor();
2736 test_IImageList_SetBkColor();
2737 test_IImageList_GetImageCount();
2738 test_IImageList_GetIconSize();
2739 test_ImageList_WriteEx();
2741 CoUninitialize();
2743 unload_v6_module(ctx_cookie, hCtx);