comctl32/tests: Make sure v6 module is used when running tests, run more tests with...
[wine.git] / dlls / comctl32 / tests / imagelist.c
blob566b3b5a8352402a7c4fcfd949e5e69b18737a27
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 BOOL (WINAPI *pImageList_DrawIndirect)(IMAGELISTDRAWPARAMS*);
67 static BOOL (WINAPI *pImageList_SetImageCount)(HIMAGELIST,UINT);
68 static HRESULT (WINAPI *pImageList_CoCreateInstance)(REFCLSID,const IUnknown *,
69 REFIID,void **);
70 static HRESULT (WINAPI *pHIMAGELIST_QueryInterface)(HIMAGELIST,REFIID,void **);
71 static int (WINAPI *pImageList_SetColorTable)(HIMAGELIST,int,int,RGBQUAD*);
72 static DWORD (WINAPI *pImageList_GetFlags)(HIMAGELIST);
73 static BOOL (WINAPI *pImageList_BeginDrag)(HIMAGELIST, int, int, int);
74 static HIMAGELIST (WINAPI *pImageList_GetDragImage)(POINT *, POINT *);
75 static void (WINAPI *pImageList_EndDrag)(void);
76 static INT (WINAPI *pImageList_GetImageCount)(HIMAGELIST);
77 static BOOL (WINAPI *pImageList_SetDragCursorImage)(HIMAGELIST, int, int, int);
78 static BOOL (WINAPI *pImageList_GetIconSize)(HIMAGELIST, int *, int *);
79 static BOOL (WINAPI *pImageList_Remove)(HIMAGELIST, int);
80 static INT (WINAPI *pImageList_ReplaceIcon)(HIMAGELIST, int, HICON);
81 static BOOL (WINAPI *pImageList_Replace)(HIMAGELIST, int, HBITMAP, HBITMAP);
82 static HIMAGELIST (WINAPI *pImageList_Merge)(HIMAGELIST, int, HIMAGELIST, int, int, int);
83 static BOOL (WINAPI *pImageList_GetImageInfo)(HIMAGELIST, int, IMAGEINFO *);
84 static BOOL (WINAPI *pImageList_Write)(HIMAGELIST, IStream *);
85 static HIMAGELIST (WINAPI *pImageList_Read)(IStream *);
86 static BOOL (WINAPI *pImageList_Copy)(HIMAGELIST, int, HIMAGELIST, int, UINT);
87 static HIMAGELIST (WINAPI *pImageList_LoadImageW)(HINSTANCE, LPCWSTR, int, int, COLORREF, UINT, UINT);
89 static HINSTANCE hinst;
91 /* only used in interactive mode */
92 static void force_redraw(HWND hwnd)
94 if (!winetest_interactive)
95 return;
97 RedrawWindow(hwnd, NULL, 0, RDW_UPDATENOW);
98 Sleep(1000);
101 /* These macros build cursor/bitmap data in 4x4 pixel blocks */
102 #define B(x,y) ((x?0xf0:0)|(y?0xf:0))
103 #define ROW1(a,b,c,d,e,f,g,h) B(a,b),B(c,d),B(e,f),B(g,h)
104 #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), \
105 ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h)
106 #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)
107 #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), \
108 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), \
109 ROW2(a,b,c,d,e,f,g,h,i,j,k,l)
111 static const BYTE empty_bits[48*48/8];
113 static const BYTE icon_bits[32*32/8] =
115 ROW32(0,0,0,0,0,0,0,0),
116 ROW32(0,0,1,1,1,1,0,0),
117 ROW32(0,1,1,1,1,1,1,0),
118 ROW32(0,1,1,0,0,1,1,0),
119 ROW32(0,1,1,0,0,1,1,0),
120 ROW32(0,1,1,1,1,1,1,0),
121 ROW32(0,0,1,1,1,1,0,0),
122 ROW32(0,0,0,0,0,0,0,0)
125 static const BYTE bitmap_bits[48*48/8] =
127 ROW48(0,0,0,0,0,0,0,0,0,0,0,0),
128 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
129 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
130 ROW48(0,1,0,0,0,0,0,0,1,0,1,0),
131 ROW48(0,1,0,0,0,0,0,1,0,0,1,0),
132 ROW48(0,1,0,0,0,0,1,0,0,0,1,0),
133 ROW48(0,1,0,0,0,1,0,0,0,0,1,0),
134 ROW48(0,1,0,0,1,0,0,0,0,0,1,0),
135 ROW48(0,1,0,1,0,0,0,0,0,0,1,0),
136 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
137 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
138 ROW48(0,0,0,0,0,0,0,0,0,0,0,0)
141 static HIMAGELIST createImageList(int cx, int cy)
143 /* Create an ImageList and put an image into it */
144 HIMAGELIST himl = pImageList_Create(cx, cy, ILC_COLOR, 1, 1);
145 HBITMAP hbm = CreateBitmap(48, 48, 1, 1, bitmap_bits);
147 ok(himl != NULL, "Failed to create image list, %d x %d.\n", cx, cy);
148 pImageList_Add(himl, hbm, NULL);
149 DeleteObject(hbm);
150 return himl;
153 static HWND create_window(void)
155 char className[] = "bmwnd";
156 char winName[] = "Test Bitmap";
157 HWND hWnd;
158 static BOOL registered = FALSE;
160 if (!registered)
162 WNDCLASSA cls;
164 cls.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
165 cls.lpfnWndProc = DefWindowProcA;
166 cls.cbClsExtra = 0;
167 cls.cbWndExtra = 0;
168 cls.hInstance = 0;
169 cls.hIcon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
170 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
171 cls.hbrBackground = GetStockObject (WHITE_BRUSH);
172 cls.lpszMenuName = 0;
173 cls.lpszClassName = className;
175 RegisterClassA (&cls);
176 registered = TRUE;
179 /* Setup window */
180 hWnd = CreateWindowA (className, winName,
181 WS_OVERLAPPEDWINDOW ,
182 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
183 0, hinst, 0);
185 if (winetest_interactive)
187 ShowWindow (hWnd, SW_SHOW);
188 force_redraw (hWnd);
191 return hWnd;
194 static HDC show_image(HWND hwnd, HIMAGELIST himl, int idx, int size,
195 LPCSTR loc, BOOL clear)
197 HDC hdc;
199 if (!winetest_interactive || !himl) return NULL;
201 SetWindowTextA(hwnd, loc);
202 hdc = GetDC(hwnd);
203 ImageList_Draw(himl, idx, hdc, 0, 0, ILD_TRANSPARENT);
205 force_redraw(hwnd);
207 if (clear)
209 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
210 ReleaseDC(hwnd, hdc);
211 hdc = NULL;
214 return hdc;
217 /* Useful for checking differences */
218 static void dump_bits(const BYTE *p, const BYTE *q, int size)
220 int i, j;
222 size /= 8;
224 for (i = 0; i < size * 2; i++)
226 printf("|");
227 for (j = 0; j < size; j++)
228 printf("%c%c", p[j] & 0xf0 ? 'X' : ' ', p[j] & 0xf ? 'X' : ' ');
229 printf(" -- ");
230 for (j = 0; j < size; j++)
231 printf("%c%c", q[j] & 0xf0 ? 'X' : ' ', q[j] & 0xf ? 'X' : ' ');
232 printf("|\n");
233 p += size * 4;
234 q += size * 4;
236 printf("\n");
239 static void check_bits(HWND hwnd, HIMAGELIST himl, int idx, int size,
240 const BYTE *checkbits, LPCSTR loc)
242 BYTE bits[100*100/8];
243 COLORREF c;
244 HDC hdc;
245 int x, y, i = -1;
247 if (!winetest_interactive || !himl) return;
249 memset(bits, 0, sizeof(bits));
250 hdc = show_image(hwnd, himl, idx, size, loc, FALSE);
252 c = GetPixel(hdc, 0, 0);
254 for (y = 0; y < size; y ++)
256 for (x = 0; x < size; x++)
258 if (!(x & 0x7)) i++;
259 if (GetPixel(hdc, x, y) != c) bits[i] |= (0x80 >> (x & 0x7));
263 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
264 ReleaseDC(hwnd, hdc);
266 ok (memcmp(bits, checkbits, (size * size)/8) == 0,
267 "%s: bits different\n", loc);
268 if (memcmp(bits, checkbits, (size * size)/8))
269 dump_bits(bits, checkbits, size);
272 static void test_begindrag(void)
274 HIMAGELIST himl = createImageList(7,13);
275 HIMAGELIST drag;
276 BOOL ret;
277 int count;
278 POINT hotspot;
280 count = pImageList_GetImageCount(himl);
281 ok(count > 2, "Tests need an ImageList with more than 2 images\n");
283 /* Two BeginDrag() without EndDrag() in between */
284 ret = pImageList_BeginDrag(himl, 1, 0, 0);
285 drag = pImageList_GetDragImage(NULL, NULL);
286 ok(ret && drag, "ImageList_BeginDrag() failed\n");
287 ret = pImageList_BeginDrag(himl, 0, 3, 5);
288 ok(!ret, "ImageList_BeginDrag() returned TRUE\n");
289 drag = pImageList_GetDragImage(NULL, &hotspot);
290 ok(!!drag, "No active ImageList drag left\n");
291 ok(hotspot.x == 0 && hotspot.y == 0, "New ImageList drag was created\n");
292 pImageList_EndDrag();
293 drag = pImageList_GetDragImage(NULL, NULL);
294 ok(!drag, "ImageList drag was not destroyed\n");
296 /* Invalid image index */
297 pImageList_BeginDrag(himl, 0, 0, 0);
298 ret = pImageList_BeginDrag(himl, count, 3, 5);
299 ok(!ret, "ImageList_BeginDrag() returned TRUE\n");
300 drag = pImageList_GetDragImage(NULL, &hotspot);
301 ok(drag && hotspot.x == 0 && hotspot.y == 0, "Active drag should not have been canceled\n");
302 pImageList_EndDrag();
303 drag = pImageList_GetDragImage(NULL, NULL);
304 ok(!drag, "ImageList drag was not destroyed\n");
305 /* Invalid negative image indexes succeed */
306 ret = pImageList_BeginDrag(himl, -17, 0, 0);
307 drag = pImageList_GetDragImage(NULL, NULL);
308 ok(ret && drag, "ImageList drag was created\n");
309 pImageList_EndDrag();
310 ret = pImageList_BeginDrag(himl, -1, 0, 0);
311 drag = pImageList_GetDragImage(NULL, NULL);
312 ok(ret && drag, "ImageList drag was created\n");
313 pImageList_EndDrag();
314 pImageList_Destroy(himl);
317 static void test_hotspot(void)
319 struct hotspot {
320 int dx;
321 int dy;
324 #define SIZEX1 47
325 #define SIZEY1 31
326 #define SIZEX2 11
327 #define SIZEY2 17
328 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
329 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
330 { 10, 7 },
331 { SIZEX1, SIZEY1 },
332 { -9, -8 },
333 { -7, 35 }
335 int i, j, ret;
336 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
337 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
338 HWND hwnd = create_window();
341 for (i = 0; i < HOTSPOTS_MAX; i++) {
342 for (j = 0; j < HOTSPOTS_MAX; j++) {
343 int dx1 = hotspots[i].dx;
344 int dy1 = hotspots[i].dy;
345 int dx2 = hotspots[j].dx;
346 int dy2 = hotspots[j].dy;
347 int correctx, correcty, newx, newy;
348 char loc[256];
349 HIMAGELIST himlNew;
350 POINT ppt;
352 ret = pImageList_BeginDrag(himl1, 0, dx1, dy1);
353 ok(ret != 0, "BeginDrag failed for { %d, %d }\n", dx1, dy1);
354 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
355 show_image(hwnd, himl1, 0, max(SIZEX1, SIZEY1), loc, TRUE);
357 /* check merging the dragged image with a second image */
358 ret = pImageList_SetDragCursorImage(himl2, 0, dx2, dy2);
359 ok(ret != 0, "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
360 dx1, dy1, dx2, dy2);
361 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
362 show_image(hwnd, himl2, 0, max(SIZEX2, SIZEY2), loc, TRUE);
364 /* check new hotspot, it should be the same like the old one */
365 himlNew = pImageList_GetDragImage(NULL, &ppt);
366 ok(ppt.x == dx1 && ppt.y == dy1,
367 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
368 dx1, dy1, ppt.x, ppt.y);
369 /* check size of new dragged image */
370 pImageList_GetIconSize(himlNew, &newx, &newy);
371 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
372 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
373 ok(newx == correctx && newy == correcty,
374 "Expected drag image size [%d,%d] got [%d,%d]\n",
375 correctx, correcty, newx, newy);
376 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
377 show_image(hwnd, himlNew, 0, max(correctx, correcty), loc, TRUE);
378 pImageList_EndDrag();
381 #undef SIZEX1
382 #undef SIZEY1
383 #undef SIZEX2
384 #undef SIZEY2
385 #undef HOTSPOTS_MAX
386 pImageList_Destroy(himl2);
387 pImageList_Destroy(himl1);
388 DestroyWindow(hwnd);
391 static void test_add_remove(void)
393 HIMAGELIST himl ;
395 HICON hicon1 ;
396 HICON hicon2 ;
397 HICON hicon3 ;
399 /* create an imagelist to play with */
400 himl = pImageList_Create(84, 84, ILC_COLOR16, 0, 3);
401 ok(himl!=0,"failed to create imagelist\n");
403 /* load the icons to add to the image list */
404 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
405 ok(hicon1 != 0, "no hicon1\n");
406 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
407 ok(hicon2 != 0, "no hicon2\n");
408 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
409 ok(hicon3 != 0, "no hicon3\n");
411 /* remove when nothing exists */
412 ok(!pImageList_Remove(himl, 0), "Removed nonexistent icon.\n");
413 /* removing everything from an empty imagelist should succeed */
414 ok(pImageList_Remove(himl, -1), "Removed nonexistent icon\n");
416 /* add three */
417 ok(0 == pImageList_ReplaceIcon(himl, -1, hicon1), "Failed to add icon1.\n");
418 ok(1 == pImageList_ReplaceIcon(himl, -1, hicon2), "Failed to add icon2.\n");
419 ok(2 == pImageList_ReplaceIcon(himl, -1, hicon3), "Failed to add icon3.\n");
421 /* remove an index out of range */
422 ok(!pImageList_Remove(himl, 4711), "removed nonexistent icon\n");
424 /* remove three */
425 ok(pImageList_Remove(himl, 0), "Can't remove 0\n");
426 ok(pImageList_Remove(himl, 0), "Can't remove 0\n");
427 ok(pImageList_Remove(himl, 0), "Can't remove 0\n");
429 /* remove one extra */
430 ok(!pImageList_Remove(himl, 0), "Removed nonexistent icon.\n");
432 /* destroy it */
433 ok(pImageList_Destroy(himl), "Failed to destroy imagelist.\n");
435 ok(-1 == pImageList_ReplaceIcon((HIMAGELIST)0xdeadbeef, -1, hicon1), "Don't crash on bad handle\n");
437 ok(DestroyIcon(hicon1), "Failed to destroy icon 1.\n");
438 ok(DestroyIcon(hicon2), "Failed to destroy icon 2.\n");
439 ok(DestroyIcon(hicon3), "Failed to destroy icon 3.\n");
442 static void test_imagecount(void)
444 HIMAGELIST himl;
446 ok(0 == pImageList_GetImageCount((HIMAGELIST)0xdeadbeef), "don't crash on bad handle\n");
448 if (!pImageList_SetImageCount)
450 win_skip("ImageList_SetImageCount not available\n");
451 return;
454 himl = pImageList_Create(84, 84, ILC_COLOR16, 0, 3);
455 ok(himl != 0, "Failed to create imagelist.\n");
457 ok(pImageList_SetImageCount(himl, 3), "couldn't increase image count\n");
458 ok(pImageList_GetImageCount(himl) == 3, "invalid image count after increase\n");
459 ok(pImageList_SetImageCount(himl, 1), "couldn't decrease image count\n");
460 ok(pImageList_GetImageCount(himl) == 1, "invalid image count after decrease to 1\n");
461 ok(pImageList_SetImageCount(himl, 0), "couldn't decrease image count\n");
462 ok(pImageList_GetImageCount(himl) == 0, "invalid image count after decrease to 0\n");
464 ok(pImageList_Destroy(himl), "Failed to destroy imagelist.\n");
467 static void test_DrawIndirect(void)
469 HIMAGELIST himl;
471 HBITMAP hbm1;
472 HBITMAP hbm2;
473 HBITMAP hbm3;
475 IMAGELISTDRAWPARAMS imldp;
476 HDC hdc;
477 HWND hwndfortest;
479 if (!pImageList_DrawIndirect)
481 win_skip("ImageList_DrawIndirect not available, skipping test\n");
482 return;
485 hwndfortest = create_window();
486 hdc = GetDC(hwndfortest);
487 ok(hdc!=NULL, "couldn't get DC\n");
489 /* create an imagelist to play with */
490 himl = pImageList_Create(48, 48, ILC_COLOR16, 0, 3);
491 ok(himl != 0, "Failed to create imagelist.\n");
493 /* load the icons to add to the image list */
494 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
495 ok(hbm1 != 0, "no bitmap 1\n");
496 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
497 ok(hbm2 != 0, "no bitmap 2\n");
498 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
499 ok(hbm3 != 0, "no bitmap 3\n");
501 /* add three */
502 ok(0 == ImageList_Add(himl, hbm1, 0),"failed to add bitmap 1\n");
503 ok(1 == ImageList_Add(himl, hbm2, 0),"failed to add bitmap 2\n");
505 if (pImageList_SetImageCount)
507 ok(pImageList_SetImageCount(himl,3),"Setimage count failed\n");
508 /*ok(2==ImageList_Add(himl, hbm3, NULL),"failed to add bitmap 3\n"); */
509 ok(pImageList_Replace(himl, 2, hbm3, 0),"failed to replace bitmap 3\n");
512 memset(&imldp, 0, sizeof (imldp));
513 ok(!pImageList_DrawIndirect(&imldp), "zero data succeeded!\n");
514 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
515 ok(!pImageList_DrawIndirect(&imldp), "zero hdc succeeded!\n");
516 imldp.hdcDst = hdc;
517 ok(!pImageList_DrawIndirect(&imldp),"zero himl succeeded!\n");
518 imldp.himl = (HIMAGELIST)0xdeadbeef;
519 ok(!pImageList_DrawIndirect(&imldp),"bad himl succeeded!\n");
520 imldp.himl = himl;
522 force_redraw(hwndfortest);
524 imldp.fStyle = SRCCOPY;
525 imldp.rgbBk = CLR_DEFAULT;
526 imldp.rgbFg = CLR_DEFAULT;
527 imldp.y = 100;
528 imldp.x = 100;
529 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
530 imldp.i ++;
531 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
532 imldp.i ++;
533 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
534 imldp.i ++;
535 ok(!pImageList_DrawIndirect(&imldp),"should fail\n");
537 /* remove three */
538 ok(pImageList_Remove(himl, 0), "removing 1st bitmap\n");
539 ok(pImageList_Remove(himl, 0), "removing 2nd bitmap\n");
540 ok(pImageList_Remove(himl, 0), "removing 3rd bitmap\n");
542 /* destroy it */
543 ok(pImageList_Destroy(himl), "Failed to destroy imagelist.\n");
545 /* bitmaps should not be deleted by the imagelist */
546 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
547 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
548 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
550 ReleaseDC(hwndfortest, hdc);
551 DestroyWindow(hwndfortest);
554 static int get_color_format(HBITMAP bmp)
556 BITMAPINFO bmi;
557 HDC hdc = CreateCompatibleDC(0);
558 HBITMAP hOldBmp = SelectObject(hdc, bmp);
559 int ret;
561 memset(&bmi, 0, sizeof(bmi));
562 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
563 ret = GetDIBits(hdc, bmp, 0, 0, 0, &bmi, DIB_RGB_COLORS);
564 ok(ret, "GetDIBits failed\n");
566 SelectObject(hdc, hOldBmp);
567 DeleteDC(hdc);
568 return bmi.bmiHeader.biBitCount;
571 static void test_merge_colors(void)
573 HIMAGELIST himl[8], hmerge;
574 int sizes[] = { ILC_COLOR, ILC_COLOR | ILC_MASK, ILC_COLOR4, ILC_COLOR8, ILC_COLOR16, ILC_COLOR24, ILC_COLOR32, ILC_COLORDDB };
575 HICON hicon1;
576 IMAGEINFO info;
577 int bpp, i, j;
579 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
580 ok(hicon1 != NULL, "failed to create hicon1\n");
582 for (i = 0; i < 8; i++)
584 himl[i] = pImageList_Create(32, 32, sizes[i], 0, 3);
585 ok(himl[i] != NULL, "failed to create himl[%d]\n", i);
586 ok(0 == pImageList_ReplaceIcon(himl[i], -1, hicon1), "Failed to add icon1 to himl[%d].\n", i);
587 if (i == 0 || i == 1 || i == 7)
589 pImageList_GetImageInfo(himl[i], 0, &info);
590 sizes[i] = get_color_format(info.hbmImage);
593 DestroyIcon(hicon1);
594 for (i = 0; i < 8; i++)
595 for (j = 0; j < 8; j++)
597 hmerge = pImageList_Merge(himl[i], 0, himl[j], 0, 0, 0);
598 ok(hmerge != NULL, "merge himl[%d], himl[%d] failed\n", i, j);
600 pImageList_GetImageInfo(hmerge, 0, &info);
601 bpp = get_color_format(info.hbmImage);
602 /* ILC_COLOR[X] is defined as [X] */
603 if (i == 4 && j == 7)
604 ok(bpp == 16, /* merging ILC_COLOR16 with ILC_COLORDDB seems to be a special case */
605 "wrong biBitCount %d when merging lists %d (%d) and %d (%d)\n", bpp, i, sizes[i], j, sizes[j]);
606 else
607 ok(bpp == (i > j ? sizes[i] : sizes[j]),
608 "wrong biBitCount %d when merging lists %d (%d) and %d (%d)\n", bpp, i, sizes[i], j, sizes[j]);
609 ok(info.hbmMask != 0, "Imagelist merged from %d and %d had no mask\n", i, j);
611 pImageList_Destroy(hmerge);
614 for (i = 0; i < 8; i++)
615 pImageList_Destroy(himl[i]);
618 static void test_merge(void)
620 HIMAGELIST himl1, himl2, hmerge;
621 HICON hicon1;
622 HWND hwnd = create_window();
624 himl1 = pImageList_Create(32, 32, 0, 0, 3);
625 ok(himl1 != NULL,"failed to create himl1\n");
627 himl2 = pImageList_Create(32, 32, 0, 0, 3);
628 ok(himl2 != NULL,"failed to create himl2\n");
630 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
631 ok(hicon1 != NULL, "failed to create hicon1\n");
633 if (!himl1 || !himl2 || !hicon1)
634 return;
636 ok(0 == pImageList_ReplaceIcon(himl2, -1, hicon1), "Failed to add icon1 to himl2.\n");
637 check_bits(hwnd, himl2, 0, 32, icon_bits, "add icon1 to himl2");
639 /* If himl1 has no images, merge still succeeds */
640 hmerge = pImageList_Merge(himl1, -1, himl2, 0, 0, 0);
641 ok(hmerge != NULL, "merge himl1,-1 failed\n");
642 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,-1");
643 pImageList_Destroy(hmerge);
645 hmerge = pImageList_Merge(himl1, 0, himl2, 0, 0, 0);
646 ok(hmerge != NULL,"merge himl1,0 failed\n");
647 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,0");
648 pImageList_Destroy(hmerge);
650 /* Same happens if himl2 is empty */
651 pImageList_Destroy(himl2);
652 himl2 = pImageList_Create(32, 32, 0, 0, 3);
653 ok(himl2 != NULL,"failed to recreate himl2\n");
654 if (!himl2)
655 return;
657 hmerge = pImageList_Merge(himl1, -1, himl2, -1, 0, 0);
658 ok(hmerge != NULL, "merge himl2,-1 failed\n");
659 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,-1");
660 pImageList_Destroy(hmerge);
662 hmerge = pImageList_Merge(himl1, -1, himl2, 0, 0, 0);
663 ok(hmerge != NULL, "merge himl2,0 failed\n");
664 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,0");
665 pImageList_Destroy(hmerge);
667 /* Now try merging an image with itself */
668 ok(0 == pImageList_ReplaceIcon(himl2, -1, hicon1), "Failed to re-add icon1 to himl2.\n");
670 hmerge = pImageList_Merge(himl2, 0, himl2, 0, 0, 0);
671 ok(hmerge != NULL, "merge himl2 with itself failed\n");
672 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2 with itself");
673 pImageList_Destroy(hmerge);
675 /* Try merging 2 different image lists */
676 ok(0 == pImageList_ReplaceIcon(himl1, -1, hicon1), "Failed to add icon1 to himl1.\n");
678 hmerge = pImageList_Merge(himl1, 0, himl2, 0, 0, 0);
679 ok(hmerge != NULL, "merge himl1 with himl2 failed\n");
680 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2");
681 pImageList_Destroy(hmerge);
683 hmerge = pImageList_Merge(himl1, 0, himl2, 0, 8, 16);
684 ok(hmerge != NULL, "merge himl1 with himl2 8,16 failed\n");
685 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2, 8,16");
686 pImageList_Destroy(hmerge);
688 pImageList_Destroy(himl1);
689 pImageList_Destroy(himl2);
690 DestroyIcon(hicon1);
691 DestroyWindow(hwnd);
694 /*********************** imagelist storage test ***************************/
696 #define BMP_CX 48
698 struct memstream
700 IStream IStream_iface;
701 IStream *stream;
704 static struct memstream *impl_from_IStream(IStream *iface)
706 return CONTAINING_RECORD(iface, struct memstream, IStream_iface);
709 static HRESULT STDMETHODCALLTYPE Test_Stream_QueryInterface(IStream *iface, REFIID riid,
710 void **ppvObject)
712 ok(0, "unexpected call\n");
713 return E_NOTIMPL;
716 static ULONG STDMETHODCALLTYPE Test_Stream_AddRef(IStream *iface)
718 ok(0, "unexpected call\n");
719 return 2;
722 static ULONG STDMETHODCALLTYPE Test_Stream_Release(IStream *iface)
724 ok(0, "unexpected call\n");
725 return 1;
728 static HRESULT STDMETHODCALLTYPE Test_Stream_Read(IStream *iface, void *pv, ULONG cb,
729 ULONG *pcbRead)
731 struct memstream *stream = impl_from_IStream(iface);
732 return IStream_Read(stream->stream, pv, cb, pcbRead);
735 static HRESULT STDMETHODCALLTYPE Test_Stream_Write(IStream *iface, const void *pv, ULONG cb,
736 ULONG *pcbWritten)
738 struct memstream *stream = impl_from_IStream(iface);
739 return IStream_Write(stream->stream, pv, cb, pcbWritten);
742 static HRESULT STDMETHODCALLTYPE Test_Stream_Seek(IStream *iface, LARGE_INTEGER dlibMove,
743 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
745 ok(0, "unexpected call\n");
746 return E_NOTIMPL;
749 static HRESULT STDMETHODCALLTYPE Test_Stream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
751 ok(0, "unexpected call\n");
752 return E_NOTIMPL;
755 static HRESULT STDMETHODCALLTYPE Test_Stream_CopyTo(IStream *iface, IStream *pstm,
756 ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead,
757 ULARGE_INTEGER *pcbWritten)
759 ok(0, "unexpected call\n");
760 return E_NOTIMPL;
763 static HRESULT STDMETHODCALLTYPE Test_Stream_Commit(IStream *iface, DWORD grfCommitFlags)
765 ok(0, "unexpected call\n");
766 return E_NOTIMPL;
769 static HRESULT STDMETHODCALLTYPE Test_Stream_Revert(IStream *iface)
771 ok(0, "unexpected call\n");
772 return E_NOTIMPL;
775 static HRESULT STDMETHODCALLTYPE Test_Stream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset,
776 ULARGE_INTEGER cb, DWORD dwLockType)
778 ok(0, "unexpected call\n");
779 return E_NOTIMPL;
782 static HRESULT STDMETHODCALLTYPE Test_Stream_UnlockRegion(IStream *iface, ULARGE_INTEGER libOffset,
783 ULARGE_INTEGER cb, DWORD dwLockType)
785 ok(0, "unexpected call\n");
786 return E_NOTIMPL;
789 static HRESULT STDMETHODCALLTYPE Test_Stream_Stat(IStream *iface, STATSTG *pstatstg,
790 DWORD grfStatFlag)
792 ok(0, "unexpected call\n");
793 return E_NOTIMPL;
796 static HRESULT STDMETHODCALLTYPE Test_Stream_Clone(IStream *iface, IStream **ppstm)
798 ok(0, "unexpected call\n");
799 return E_NOTIMPL;
802 static const IStreamVtbl Test_Stream_Vtbl =
804 Test_Stream_QueryInterface,
805 Test_Stream_AddRef,
806 Test_Stream_Release,
807 Test_Stream_Read,
808 Test_Stream_Write,
809 Test_Stream_Seek,
810 Test_Stream_SetSize,
811 Test_Stream_CopyTo,
812 Test_Stream_Commit,
813 Test_Stream_Revert,
814 Test_Stream_LockRegion,
815 Test_Stream_UnlockRegion,
816 Test_Stream_Stat,
817 Test_Stream_Clone
820 static void init_memstream(struct memstream *stream)
822 stream->IStream_iface.lpVtbl = &Test_Stream_Vtbl;
823 CreateStreamOnHGlobal(NULL, TRUE, &stream->stream);
826 static void cleanup_memstream(struct memstream *stream)
828 IStream_Release(stream->stream);
832 static INT DIB_GetWidthBytes( int width, int bpp )
834 return ((width * bpp + 31) / 8) & ~3;
837 static ULONG check_bitmap_data(const char *bm_data, ULONG bm_data_size,
838 INT width, INT height, INT bpp,
839 const char *comment)
841 const BITMAPFILEHEADER *bmfh = (const BITMAPFILEHEADER *)bm_data;
842 const BITMAPINFOHEADER *bmih = (const BITMAPINFOHEADER *)(bm_data + sizeof(*bmfh));
843 ULONG hdr_size, image_size;
845 hdr_size = sizeof(*bmfh) + sizeof(*bmih);
846 if (bmih->biBitCount <= 8) hdr_size += (1 << bpp) * sizeof(RGBQUAD);
848 ok(bmfh->bfType == (('M' << 8) | 'B'), "wrong bfType 0x%02x\n", bmfh->bfType);
849 ok(bmfh->bfSize == hdr_size, "wrong bfSize 0x%02x\n", bmfh->bfSize);
850 ok(bmfh->bfReserved1 == 0, "wrong bfReserved1 0x%02x\n", bmfh->bfReserved1);
851 ok(bmfh->bfReserved2 == 0, "wrong bfReserved2 0x%02x\n", bmfh->bfReserved2);
852 ok(bmfh->bfOffBits == hdr_size, "wrong bfOffBits 0x%02x\n", bmfh->bfOffBits);
854 ok(bmih->biSize == sizeof(*bmih), "wrong biSize %d\n", bmih->biSize);
855 ok(bmih->biWidth == width, "wrong biWidth %d (expected %d)\n", bmih->biWidth, width);
856 ok(bmih->biHeight == height, "wrong biHeight %d (expected %d)\n", bmih->biHeight, height);
857 ok(bmih->biPlanes == 1, "wrong biPlanes %d\n", bmih->biPlanes);
858 ok(bmih->biBitCount == bpp, "wrong biBitCount %d\n", bmih->biBitCount);
860 image_size = DIB_GetWidthBytes(bmih->biWidth, bmih->biBitCount) * bmih->biHeight;
861 ok(bmih->biSizeImage == image_size, "wrong biSizeImage %u\n", bmih->biSizeImage);
863 if (0)
865 char fname[256];
866 FILE *f;
867 sprintf(fname, "bmp_%s.bmp", comment);
868 f = fopen(fname, "wb");
869 fwrite(bm_data, 1, bm_data_size, f);
870 fclose(f);
873 return hdr_size + image_size;
876 static void check_ilhead_data(const char *ilh_data, INT cx, INT cy, INT cur, INT max, INT grow, INT flags)
878 const ILHEAD *ilh = (const ILHEAD *)ilh_data;
880 ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
881 ok(ilh->usVersion == 0x101, "wrong usVersion %x (expected 0x101)\n", ilh->usVersion);
882 ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
883 ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
884 ok(ilh->cGrow == grow, "wrong cGrow %d (expected %d)\n", ilh->cGrow, grow);
885 ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
886 ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
887 ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
888 ok(ilh->flags == flags || broken(!(ilh->flags & 0xfe) && (flags & 0xfe) == ILC_COLOR4), /* <= w2k */
889 "wrong flags %04x\n", ilh->flags);
890 ok(ilh->ovls[0] == -1, "wrong ovls[0] %04x\n", ilh->ovls[0]);
891 ok(ilh->ovls[1] == -1, "wrong ovls[1] %04x\n", ilh->ovls[1]);
892 ok(ilh->ovls[2] == -1, "wrong ovls[2] %04x\n", ilh->ovls[2]);
893 ok(ilh->ovls[3] == -1, "wrong ovls[3] %04x\n", ilh->ovls[3]);
896 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
898 HDC hdc;
899 BITMAPINFO bmi;
900 HBITMAP hbmp, hbmp_old;
901 HBRUSH hbrush;
902 RECT rc = { 0, 0, cx, cy };
904 hdc = CreateCompatibleDC(0);
906 memset(&bmi, 0, sizeof(bmi));
907 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
908 bmi.bmiHeader.biHeight = cx;
909 bmi.bmiHeader.biWidth = cy;
910 bmi.bmiHeader.biBitCount = 24;
911 bmi.bmiHeader.biPlanes = 1;
912 bmi.bmiHeader.biCompression = BI_RGB;
913 hbmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
915 hbmp_old = SelectObject(hdc, hbmp);
917 hbrush = CreateSolidBrush(color);
918 FillRect(hdc, &rc, hbrush);
919 DeleteObject(hbrush);
921 DrawTextA(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
923 SelectObject(hdc, hbmp_old);
924 DeleteDC(hdc);
926 return hbmp;
929 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, INT grow,
930 INT width, INT height, INT flags, const char *comment)
932 INT ret, cxx, cyy, size;
933 struct memstream stream;
934 LARGE_INTEGER mv;
935 HIMAGELIST himl2;
936 HGLOBAL hglobal;
937 STATSTG stat;
938 char *data;
939 HRESULT hr;
941 ret = pImageList_GetImageCount(himl);
942 ok(ret == cur, "%s: expected image count %d got %d\n", comment, cur, ret);
944 ret = pImageList_GetIconSize(himl, &cxx, &cyy);
945 ok(ret, "ImageList_GetIconSize failed\n");
946 ok(cxx == cx, "%s: wrong cx %d (expected %d)\n", comment, cxx, cx);
947 ok(cyy == cy, "%s: wrong cy %d (expected %d)\n", comment, cyy, cy);
949 init_memstream(&stream);
950 ret = pImageList_Write(himl, &stream.IStream_iface);
951 ok(ret, "%s: ImageList_Write failed\n", comment);
953 hr = GetHGlobalFromStream(stream.stream, &hglobal);
954 ok(hr == S_OK, "%s: Failed to get hglobal, %#x\n", comment, hr);
956 IStream_Stat(stream.stream, &stat, STATFLAG_NONAME);
958 data = GlobalLock(hglobal);
960 ok(data != 0, "%s: ImageList_Write didn't write any data\n", comment);
961 ok(stat.cbSize.LowPart > sizeof(ILHEAD), "%s: ImageList_Write wrote not enough data\n", comment);
963 check_ilhead_data(data, cx, cy, cur, max, grow, flags);
964 size = check_bitmap_data(data + sizeof(ILHEAD), stat.cbSize.LowPart - sizeof(ILHEAD),
965 width, height, flags & 0xfe, comment);
966 if (size < stat.cbSize.LowPart - sizeof(ILHEAD)) /* mask is present */
968 ok( flags & ILC_MASK, "%s: extra data %u/%u but mask not expected\n", comment, stat.cbSize.LowPart, size );
969 check_bitmap_data(data + sizeof(ILHEAD) + size, stat.cbSize.LowPart - sizeof(ILHEAD) - size,
970 width, height, 1, comment);
973 /* rewind and reconstruct from stream */
974 mv.QuadPart = 0;
975 IStream_Seek(stream.stream, mv, STREAM_SEEK_SET, NULL);
976 himl2 = pImageList_Read(&stream.IStream_iface);
977 ok(himl2 != NULL, "%s: Failed to deserialize imagelist\n", comment);
978 pImageList_Destroy(himl2);
980 GlobalUnlock(hglobal);
981 cleanup_memstream(&stream);
984 static void image_list_init(HIMAGELIST himl)
986 HBITMAP hbm;
987 char comment[16];
988 INT n = 1;
989 DWORD i;
990 static const struct test_data
992 BYTE grey;
993 INT cx, cy, cur, max, grow, width, height, bpp;
994 const char *comment;
995 } td[] =
997 { 255, BMP_CX, BMP_CX, 1, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 1" },
998 { 170, BMP_CX, BMP_CX, 2, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 2" },
999 { 85, BMP_CX, BMP_CX, 3, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 3" },
1000 { 0, BMP_CX, BMP_CX, 4, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 4" },
1001 { 0, BMP_CX, BMP_CX, 5, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 5" },
1002 { 85, BMP_CX, BMP_CX, 6, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 6" },
1003 { 170, BMP_CX, BMP_CX, 7, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 7" },
1004 { 255, BMP_CX, BMP_CX, 8, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 8" },
1005 { 255, BMP_CX, BMP_CX, 9, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 9" },
1006 { 170, BMP_CX, BMP_CX, 10, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 10" },
1007 { 85, BMP_CX, BMP_CX, 11, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 11" },
1008 { 0, BMP_CX, BMP_CX, 12, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 12" },
1009 { 0, BMP_CX, BMP_CX, 13, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 13" },
1010 { 85, BMP_CX, BMP_CX, 14, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 14" },
1011 { 170, BMP_CX, BMP_CX, 15, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 15" },
1012 { 255, BMP_CX, BMP_CX, 16, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 16" },
1013 { 255, BMP_CX, BMP_CX, 17, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 17" },
1014 { 170, BMP_CX, BMP_CX, 18, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 18" },
1015 { 85, BMP_CX, BMP_CX, 19, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 19" },
1016 { 0, BMP_CX, BMP_CX, 20, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 20" },
1017 { 0, BMP_CX, BMP_CX, 21, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 21" },
1018 { 85, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 22" },
1019 { 170, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 23" },
1020 { 255, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 24" }
1023 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "total 0");
1025 #define add_bitmap(grey) \
1026 sprintf(comment, "%d", n++); \
1027 hbm = create_bitmap(BMP_CX, BMP_CX, RGB((grey),(grey),(grey)), comment); \
1028 ImageList_Add(himl, hbm, NULL); \
1029 DeleteObject(hbm);
1031 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
1033 add_bitmap(td[i].grey);
1034 check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, td[i].grow,
1035 td[i].width, td[i].height, td[i].bpp, td[i].comment);
1037 #undef add_bitmap
1040 static void test_imagelist_storage(void)
1042 HIMAGELIST himl;
1043 HBITMAP hbm;
1044 HICON icon;
1045 INT ret;
1047 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
1048 ok(himl != 0, "ImageList_Create failed\n");
1050 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "empty");
1052 image_list_init(himl);
1053 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "orig");
1055 ret = pImageList_Remove(himl, 4);
1056 ok(ret, "ImageList_Remove failed\n");
1057 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "1");
1059 ret = pImageList_Remove(himl, 5);
1060 ok(ret, "ImageList_Remove failed\n");
1061 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "2");
1063 ret = pImageList_Remove(himl, 6);
1064 ok(ret, "ImageList_Remove failed\n");
1065 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "3");
1067 ret = pImageList_Remove(himl, 7);
1068 ok(ret, "ImageList_Remove failed\n");
1069 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "4");
1071 ret = pImageList_Remove(himl, -2);
1072 ok(!ret, "ImageList_Remove(-2) should fail\n");
1073 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "5");
1075 ret = pImageList_Remove(himl, 20);
1076 ok(!ret, "ImageList_Remove(20) should fail\n");
1077 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "6");
1079 ret = pImageList_Remove(himl, -1);
1080 ok(ret, "ImageList_Remove(-1) failed\n");
1081 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "7");
1083 ret = pImageList_Destroy(himl);
1084 ok(ret, "ImageList_Destroy failed\n");
1086 /* test ImageList_Create storage allocation */
1088 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 0, 32);
1089 ok(himl != 0, "ImageList_Create failed\n");
1090 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 32, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "init 0 grow 32");
1091 hbm = create_bitmap(BMP_CX * 9, BMP_CX, 0, "9");
1092 ret = pImageList_Add(himl, hbm, NULL);
1093 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1094 check_iml_data(himl, BMP_CX, BMP_CX, 1, 34, 32, BMP_CX * 4, BMP_CX * 9, ILC_COLOR24, "add 1 x 9");
1095 DeleteObject(hbm);
1096 ret = pImageList_Destroy(himl);
1097 ok(ret, "ImageList_Destroy failed\n");
1099 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 4);
1100 ok(himl != 0, "ImageList_Create failed\n");
1101 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 4 grow 4");
1102 hbm = create_bitmap(BMP_CX, BMP_CX * 9, 0, "9");
1103 ret = pImageList_Add(himl, hbm, NULL);
1104 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1105 check_iml_data(himl, BMP_CX, BMP_CX, 9, 15, 4, BMP_CX * 4, BMP_CX * 4, ILC_COLOR24, "add 9 x 1");
1106 ret = pImageList_Add(himl, hbm, NULL);
1107 ok(ret == 9, "ImageList_Add returned %d, expected 9\n", ret);
1108 check_iml_data(himl, BMP_CX, BMP_CX, 18, 25, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "add 9 x 1");
1109 DeleteObject(hbm);
1110 ret = pImageList_Destroy(himl);
1111 ok(ret, "ImageList_Destroy failed\n");
1113 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 207, 209);
1114 ok(himl != 0, "ImageList_Create failed\n");
1115 check_iml_data(himl, BMP_CX, BMP_CX, 0, 208, 212, BMP_CX * 4, BMP_CX * 52, ILC_COLOR24, "init 207 grow 209");
1116 ret = pImageList_Destroy(himl);
1117 ok(ret, "ImageList_Destroy failed\n");
1119 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 209, 207);
1120 ok(himl != 0, "ImageList_Create failed\n");
1121 check_iml_data(himl, BMP_CX, BMP_CX, 0, 210, 208, BMP_CX * 4, BMP_CX * 53, ILC_COLOR24, "init 209 grow 207");
1122 ret = pImageList_Destroy(himl);
1123 ok(ret, "ImageList_Destroy failed\n");
1125 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 14, 4);
1126 ok(himl != 0, "ImageList_Create failed\n");
1127 check_iml_data(himl, BMP_CX, BMP_CX, 0, 15, 4, BMP_CX * 4, BMP_CX * 4, ILC_COLOR24, "init 14 grow 4");
1128 ret = pImageList_Destroy(himl);
1129 ok(ret, "ImageList_Destroy failed\n");
1131 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 5, 9);
1132 ok(himl != 0, "ImageList_Create failed\n");
1133 check_iml_data(himl, BMP_CX, BMP_CX, 0, 6, 12, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 5 grow 9");
1134 ret = pImageList_Destroy(himl);
1135 ok(ret, "ImageList_Destroy failed\n");
1137 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 9, 5);
1138 ok(himl != 0, "ImageList_Create failed\n");
1139 check_iml_data(himl, BMP_CX, BMP_CX, 0, 10, 8, BMP_CX * 4, BMP_CX * 3, ILC_COLOR24, "init 9 grow 5");
1140 ret = pImageList_Destroy(himl);
1141 ok(ret, "ImageList_Destroy failed\n");
1143 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 2, 4);
1144 ok(himl != 0, "ImageList_Create failed\n");
1145 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "init 2 grow 4");
1146 ret = pImageList_Destroy(himl);
1147 ok(ret, "ImageList_Destroy failed\n");
1149 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 2);
1150 ok(himl != 0, "ImageList_Create failed\n");
1151 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 4 grow 2");
1152 ret = pImageList_Destroy(himl);
1153 ok(ret, "ImageList_Destroy failed\n");
1155 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR8, 4, 2);
1156 ok(himl != 0, "ImageList_Create failed\n");
1157 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR8, "bpp 8");
1158 ret = pImageList_Destroy(himl);
1159 ok(ret, "ImageList_Destroy failed\n");
1161 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4, 4, 2);
1162 ok(himl != 0, "ImageList_Create failed\n");
1163 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp 4");
1164 ret = pImageList_Destroy(himl);
1165 ok(ret, "ImageList_Destroy failed\n");
1167 himl = pImageList_Create(BMP_CX, BMP_CX, 0, 4, 2);
1168 ok(himl != 0, "ImageList_Create failed\n");
1169 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp default");
1170 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1171 ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1172 ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1173 DestroyIcon( icon );
1174 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp default");
1175 ret = pImageList_Destroy(himl);
1176 ok(ret, "ImageList_Destroy failed\n");
1178 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24|ILC_MASK, 4, 2);
1179 ok(himl != 0, "ImageList_Create failed\n");
1180 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24|ILC_MASK,
1181 "bpp 24 + mask");
1182 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1183 ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1184 ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1185 DestroyIcon( icon );
1186 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24|ILC_MASK, "bpp 24 + mask");
1187 ret = pImageList_Destroy(himl);
1188 ok(ret, "ImageList_Destroy failed\n");
1190 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 4, 2);
1191 ok(himl != 0, "ImageList_Create failed\n");
1192 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4|ILC_MASK, "bpp 4 + mask");
1193 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1194 ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1195 ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1196 DestroyIcon( icon );
1197 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4|ILC_MASK, "bpp 4 + mask");
1198 ret = pImageList_Destroy(himl);
1199 ok(ret, "ImageList_Destroy failed\n");
1201 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 99);
1202 ok(himl != 0, "ImageList_Create failed\n");
1203 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 100, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1204 "init 2 grow 99");
1205 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1206 ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1207 ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1208 check_iml_data(himl, BMP_CX, BMP_CX, 2, 3, 100, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1209 "init 2 grow 99 2 icons");
1210 ok( pImageList_ReplaceIcon(himl, -1, icon) == 2, "Failed to add icon\n");
1211 DestroyIcon( icon );
1212 check_iml_data(himl, BMP_CX, BMP_CX, 3, 104, 100, BMP_CX * 4, BMP_CX * 104/4, ILC_COLOR4|ILC_MASK,
1213 "init 2 grow 99 3 icons");
1214 ok( pImageList_Remove(himl, -1) == TRUE, "Failed to remove icon.\n");
1215 check_iml_data(himl, BMP_CX, BMP_CX, 0, 100, 100, BMP_CX * 4, BMP_CX * 100/4, ILC_COLOR4|ILC_MASK,
1216 "init 2 grow 99 empty");
1217 ok( pImageList_SetImageCount(himl, 22) == TRUE, "Failed to set image count.\n");
1218 check_iml_data(himl, BMP_CX, BMP_CX, 22, 23, 100, BMP_CX * 4, BMP_CX * 24/4, ILC_COLOR4|ILC_MASK,
1219 "init 2 grow 99 set count 22");
1220 ok( pImageList_SetImageCount(himl, 0) == TRUE, "Failed to set image count.\n");
1221 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 100, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1222 "init 2 grow 99 set count 0");
1223 ok( pImageList_SetImageCount(himl, 42) == TRUE, "Failed to set image count.\n");
1224 check_iml_data(himl, BMP_CX, BMP_CX, 42, 43, 100, BMP_CX * 4, BMP_CX * 44/4, ILC_COLOR4|ILC_MASK,
1225 "init 2 grow 99 set count 42");
1226 ret = pImageList_Destroy(himl);
1227 ok(ret, "ImageList_Destroy failed\n");
1229 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65536+12);
1230 ok(himl != 0, "ImageList_Create failed\n");
1231 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 12, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1232 "init 2 grow 65536+12");
1233 ret = pImageList_Destroy(himl);
1234 ok(ret, "ImageList_Destroy failed\n");
1236 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65535);
1237 ok(himl != 0, "ImageList_Create failed\n");
1238 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 0, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1239 "init 2 grow 65535");
1240 ret = pImageList_Destroy(himl);
1241 ok(ret, "ImageList_Destroy failed\n");
1243 himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, -20);
1244 ok(himl != 0, "ImageList_Create failed\n");
1245 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1246 "init 2 grow -20");
1247 ret = pImageList_Destroy(himl);
1248 ok(ret, "ImageList_Destroy failed\n");
1251 static void test_shell_imagelist(void)
1253 HRESULT (WINAPI *pSHGetImageList)(INT, REFIID, void**);
1254 IImageList *iml = NULL;
1255 HMODULE hShell32;
1256 HRESULT hr;
1257 int out = 0;
1258 RECT rect;
1259 int cx, cy;
1261 /* Try to load function from shell32 */
1262 hShell32 = LoadLibraryA("shell32.dll");
1263 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1265 if (!pSHGetImageList)
1267 win_skip("SHGetImageList not available, skipping test\n");
1268 FreeLibrary(hShell32);
1269 return;
1272 /* Get system image list */
1273 hr = pSHGetImageList(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1274 ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1276 if (hr != S_OK) {
1277 FreeLibrary(hShell32);
1278 return;
1281 IImageList_GetImageCount(iml, &out);
1282 ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1284 /* Fetch the small icon size */
1285 cx = GetSystemMetrics(SM_CXSMICON);
1286 cy = GetSystemMetrics(SM_CYSMICON);
1288 /* Check icon size matches */
1289 IImageList_GetImageRect(iml, 0, &rect);
1290 ok(((rect.right == cx) && (rect.bottom == cy)),
1291 "IImageList_GetImageRect returned r:%d,b:%d\n",
1292 rect.right, rect.bottom);
1294 IImageList_Release(iml);
1295 FreeLibrary(hShell32);
1298 static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
1300 HBITMAP hBitmap;
1301 UINT32 *buffer = NULL;
1302 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
1303 0, 0, 0, 0, 0}};
1305 hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1306 ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1308 if(!hBitmap || !buffer)
1310 DeleteObject(hBitmap);
1311 return NULL;
1314 buffer[0] = pixel1;
1315 buffer[1] = pixel2;
1317 return hBitmap;
1320 static BOOL colour_match(UINT32 x, UINT32 y)
1322 const INT32 tolerance = 8;
1324 const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1325 const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1326 const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1328 return (dr <= tolerance && dg <= tolerance && db <= tolerance);
1331 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1332 UINT32 expected, int line)
1334 bits[0] = 0x00FFFFFF;
1335 pImageList_DrawIndirect(ildp);
1336 ok(colour_match(bits[0], expected),
1337 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1338 bits[0] & 0x00FFFFFF, expected, line);
1342 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1343 UINT fStyle, UINT32 expected, int line)
1345 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1346 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1347 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1350 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1351 DWORD dwRop, UINT32 expected, int line)
1353 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1354 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1355 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1358 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1359 UINT fState, DWORD Frame, UINT32 expected, int line)
1361 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1362 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1363 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1366 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1367 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1368 UINT32 broken_expected, int line)
1370 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1371 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1372 bits[0] = 0x00FFFFFF;
1373 pImageList_DrawIndirect(&ildp);
1374 ok(colour_match(bits[0], expected) ||
1375 broken(colour_match(bits[0], broken_expected)),
1376 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1377 bits[0] & 0x00FFFFFF, expected, line);
1380 static void test_ImageList_DrawIndirect(void)
1382 HIMAGELIST himl = NULL;
1383 int ret;
1384 HDC hdcDst = NULL;
1385 HBITMAP hbmOld = NULL, hbmDst = NULL;
1386 HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1387 HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
1388 int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1389 UINT32 *bits = 0;
1390 UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1391 int bpp, broken_value;
1393 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1394 0, 0, 0, 0, 0}};
1396 hdcDst = CreateCompatibleDC(0);
1397 ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1398 if (!hdcDst)
1399 return;
1400 bpp = GetDeviceCaps(hdcDst, BITSPIXEL);
1402 hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1403 ok(hbmMask != 0, "CreateBitmap failed\n");
1404 if(!hbmMask) goto cleanup;
1406 hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1407 ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1408 if(!hbmInverseMask) goto cleanup;
1410 himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1411 ok(himl != 0, "ImageList_Create failed\n");
1412 if(!himl) goto cleanup;
1414 /* Add a no-alpha image */
1415 hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
1416 if(!hbmImage) goto cleanup;
1418 iImage = pImageList_Add(himl, hbmImage, hbmMask);
1419 ok(iImage != -1, "ImageList_Add failed\n");
1420 if(iImage == -1) goto cleanup;
1422 /* Add an alpha image */
1423 hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
1424 if(!hbmAlphaImage) goto cleanup;
1426 iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1427 ok(iAlphaImage != -1, "ImageList_Add failed\n");
1428 if(iAlphaImage == -1) goto cleanup;
1430 /* Add a transparent alpha image */
1431 hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
1432 if(!hbmTransparentImage) goto cleanup;
1434 iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1435 ok(iTransparentImage != -1, "ImageList_Add failed\n");
1436 if(iTransparentImage == -1) goto cleanup;
1438 /* 32-bit Tests */
1439 bitmapInfo.bmiHeader.biBitCount = 32;
1440 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1441 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1442 if (!hbmDst || !bits)
1443 goto cleanup;
1444 hbmOld = SelectObject(hdcDst, hbmDst);
1446 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1447 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1448 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
1449 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1450 else broken_value = 0x00B4BDC4;
1451 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1452 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1453 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1454 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1456 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
1457 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
1459 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1460 else broken_value = 0x009DA8B1;
1461 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1462 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1463 else broken_value = 0x008C99A3;
1464 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1465 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
1466 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
1467 todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
1469 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
1471 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1472 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
1474 /* ILD_ROP is ignored when the image has an alpha channel */
1475 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
1476 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
1478 todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
1479 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
1481 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
1482 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
1484 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
1485 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
1486 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
1488 cleanup:
1490 if(hbmOld)
1491 SelectObject(hdcDst, hbmOld);
1492 if(hbmDst)
1493 DeleteObject(hbmDst);
1495 if(hdcDst)
1496 DeleteDC(hdcDst);
1498 if(hbmMask)
1499 DeleteObject(hbmMask);
1500 if(hbmInverseMask)
1501 DeleteObject(hbmInverseMask);
1503 if(hbmImage)
1504 DeleteObject(hbmImage);
1505 if(hbmAlphaImage)
1506 DeleteObject(hbmAlphaImage);
1507 if(hbmTransparentImage)
1508 DeleteObject(hbmTransparentImage);
1510 if(himl)
1512 ret = ImageList_Destroy(himl);
1513 ok(ret, "ImageList_Destroy failed\n");
1517 static void test_iimagelist(void)
1519 IImageList *imgl, *imgl2;
1520 IImageList2 *imagelist;
1521 HIMAGELIST himl;
1522 HRESULT hr;
1523 ULONG ret;
1525 if (!pHIMAGELIST_QueryInterface)
1527 win_skip("XP imagelist functions not available\n");
1528 return;
1531 /* test reference counting on destruction */
1532 imgl = (IImageList*)createImageList(32, 32);
1533 ret = IImageList_AddRef(imgl);
1534 ok(ret == 2, "Expected 2, got %d\n", ret);
1535 ret = ImageList_Destroy((HIMAGELIST)imgl);
1536 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1537 ret = ImageList_Destroy((HIMAGELIST)imgl);
1538 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1539 ret = ImageList_Destroy((HIMAGELIST)imgl);
1540 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1542 imgl = (IImageList*)createImageList(32, 32);
1543 ret = IImageList_AddRef(imgl);
1544 ok(ret == 2, "Expected 2, got %d\n", ret);
1545 ret = ImageList_Destroy((HIMAGELIST)imgl);
1546 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1547 ret = IImageList_Release(imgl);
1548 ok(ret == 0, "Expected 0, got %d\n", ret);
1549 ret = ImageList_Destroy((HIMAGELIST)imgl);
1550 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1552 /* ref counting, HIMAGELIST_QueryInterface adds a reference */
1553 imgl = (IImageList*)createImageList(32, 32);
1554 hr = pHIMAGELIST_QueryInterface((HIMAGELIST)imgl, &IID_IImageList, (void**)&imgl2);
1555 ok(hr == S_OK, "got 0x%08x\n", hr);
1556 ok(imgl2 == imgl, "got different pointer\n");
1557 ret = IImageList_Release(imgl);
1558 ok(ret == 1, "got %u\n", ret);
1559 IImageList_Release(imgl);
1561 if (!pImageList_CoCreateInstance)
1563 win_skip("Vista imagelist functions not available\n");
1564 return;
1567 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1568 ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
1570 if (hr == S_OK)
1571 IImageList_Release(imgl);
1573 himl = createImageList(32, 32);
1575 if (!himl)
1576 return;
1578 hr = (pHIMAGELIST_QueryInterface)(himl, &IID_IImageList, (void **) &imgl);
1579 ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
1581 if (hr == S_OK)
1582 IImageList_Release(imgl);
1584 pImageList_Destroy(himl);
1586 /* IImageList2 */
1587 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList2, (void**)&imagelist);
1588 if (hr != S_OK)
1590 win_skip("IImageList2 is not supported.\n");
1591 return;
1593 ok(hr == S_OK, "got 0x%08x\n", hr);
1594 IImageList2_Release(imagelist);
1597 static void test_IImageList_Add_Remove(void)
1599 IImageList *imgl;
1600 HIMAGELIST himl;
1601 HRESULT hr;
1603 HICON hicon1;
1604 HICON hicon2;
1605 HICON hicon3;
1607 int ret;
1609 /* create an imagelist to play with */
1610 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1611 ok(himl != 0,"failed to create imagelist\n");
1613 imgl = (IImageList *) himl;
1615 /* load the icons to add to the image list */
1616 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1617 ok(hicon1 != 0, "no hicon1\n");
1618 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1619 ok(hicon2 != 0, "no hicon2\n");
1620 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1621 ok(hicon3 != 0, "no hicon3\n");
1623 /* remove when nothing exists */
1624 hr = IImageList_Remove(imgl, 0);
1625 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1627 /* removing everything from an empty imagelist should succeed */
1628 hr = IImageList_Remove(imgl, -1);
1629 ok(hr == S_OK, "removed nonexistent icon\n");
1631 /* add three */
1632 ret = -1;
1633 ok( IImageList_ReplaceIcon(imgl, -1, hicon1, &ret) == S_OK && (ret == 0),"failed to add icon1\n");
1634 ret = -1;
1635 ok( IImageList_ReplaceIcon(imgl, -1, hicon2, &ret) == S_OK && (ret == 1),"failed to add icon2\n");
1636 ret = -1;
1637 ok( IImageList_ReplaceIcon(imgl, -1, hicon3, &ret) == S_OK && (ret == 2),"failed to add icon3\n");
1639 /* remove an index out of range */
1640 ok( IImageList_Remove(imgl, 4711) == E_INVALIDARG, "got 0x%08x\n", hr);
1642 /* remove three */
1643 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1644 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1645 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1647 /* remove one extra */
1648 ok( IImageList_Remove(imgl, 0) == E_INVALIDARG, "got 0x%08x\n", hr);
1650 IImageList_Release(imgl);
1651 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1652 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1653 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1656 static void test_IImageList_Get_SetImageCount(void)
1658 IImageList *imgl;
1659 HIMAGELIST himl;
1660 HRESULT hr;
1661 INT ret;
1663 /* create an imagelist to play with */
1664 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1665 ok(himl != 0,"failed to create imagelist\n");
1667 imgl = (IImageList *) himl;
1669 /* check SetImageCount/GetImageCount */
1670 hr = IImageList_SetImageCount(imgl, 3);
1671 ok(hr == S_OK, "got 0x%08x\n", hr);
1672 ret = 0;
1673 hr = IImageList_GetImageCount(imgl, &ret);
1674 ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
1675 hr = IImageList_SetImageCount(imgl, 1);
1676 ok(hr == S_OK, "got 0x%08x\n", hr);
1677 ret = 0;
1678 hr = IImageList_GetImageCount(imgl, &ret);
1679 ok(hr == S_OK && ret == 1, "invalid image count after decrease to 1\n");
1680 hr = IImageList_SetImageCount(imgl, 0);
1681 ok(hr == S_OK, "got 0x%08x\n", hr);
1682 ret = -1;
1683 hr = IImageList_GetImageCount(imgl, &ret);
1684 ok(hr == S_OK && ret == 0, "invalid image count after decrease to 0\n");
1686 IImageList_Release(imgl);
1689 static void test_IImageList_Draw(void)
1691 IImageList *imgl;
1692 HIMAGELIST himl;
1694 HBITMAP hbm1;
1695 HBITMAP hbm2;
1696 HBITMAP hbm3;
1698 IMAGELISTDRAWPARAMS imldp;
1699 HWND hwndfortest;
1700 HRESULT hr;
1701 HDC hdc;
1702 int ret;
1704 hwndfortest = create_window();
1705 hdc = GetDC(hwndfortest);
1706 ok(hdc!=NULL, "couldn't get DC\n");
1708 /* create an imagelist to play with */
1709 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1710 ok(himl!=0,"failed to create imagelist\n");
1712 imgl = (IImageList *) himl;
1714 /* load the icons to add to the image list */
1715 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1716 ok(hbm1 != 0, "no bitmap 1\n");
1717 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1718 ok(hbm2 != 0, "no bitmap 2\n");
1719 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1720 ok(hbm3 != 0, "no bitmap 3\n");
1722 /* add three */
1723 ret = -1;
1724 ok( IImageList_Add(imgl, hbm1, 0, &ret) == S_OK && (ret == 0), "failed to add bitmap 1\n");
1725 ret = -1;
1726 ok( IImageList_Add(imgl, hbm2, 0, &ret) == S_OK && (ret == 1), "failed to add bitmap 2\n");
1728 ok( IImageList_SetImageCount(imgl, 3) == S_OK, "Setimage count failed\n");
1729 ok( IImageList_Replace(imgl, 2, hbm3, 0) == S_OK, "failed to replace bitmap 3\n");
1731 if (0)
1733 /* crashes on native */
1734 IImageList_Draw(imgl, NULL);
1737 memset(&imldp, 0, sizeof (imldp));
1738 hr = IImageList_Draw(imgl, &imldp);
1739 ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
1741 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
1742 imldp.hdcDst = hdc;
1743 imldp.himl = himl;
1745 force_redraw(hwndfortest);
1747 imldp.fStyle = SRCCOPY;
1748 imldp.rgbBk = CLR_DEFAULT;
1749 imldp.rgbFg = CLR_DEFAULT;
1750 imldp.y = 100;
1751 imldp.x = 100;
1752 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1753 imldp.i ++;
1754 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1755 imldp.i ++;
1756 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1757 imldp.i ++;
1758 ok( IImageList_Draw(imgl, &imldp) == E_INVALIDARG, "should fail\n");
1760 /* remove three */
1761 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 1st bitmap\n");
1762 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 2nd bitmap\n");
1763 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 3rd bitmap\n");
1765 /* destroy it */
1766 IImageList_Release(imgl);
1768 /* bitmaps should not be deleted by the imagelist */
1769 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1770 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1771 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1773 ReleaseDC(hwndfortest, hdc);
1774 DestroyWindow(hwndfortest);
1777 static void test_IImageList_Merge(void)
1779 HIMAGELIST himl1, himl2;
1780 IImageList *imgl1, *imgl2, *merge;
1781 HICON hicon1;
1782 HWND hwnd = create_window();
1783 HRESULT hr;
1784 int ret;
1786 himl1 = ImageList_Create(32,32,0,0,3);
1787 ok(himl1 != NULL,"failed to create himl1\n");
1789 himl2 = ImageList_Create(32,32,0,0,3);
1790 ok(himl2 != NULL,"failed to create himl2\n");
1792 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1793 ok(hicon1 != NULL, "failed to create hicon1\n");
1795 if (!himl1 || !himl2 || !hicon1)
1796 return;
1798 /* cast to IImageList */
1799 imgl1 = (IImageList *) himl1;
1800 imgl2 = (IImageList *) himl2;
1802 ret = -1;
1803 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl2 failed\n");
1805 if (0)
1807 /* null cases that crash on native */
1808 IImageList_Merge(imgl1, -1, NULL, 0, 0, 0, &IID_IImageList, (void**)&merge);
1809 IImageList_Merge(imgl1, -1, (IUnknown*) imgl2, 0, 0, 0, &IID_IImageList, NULL);
1812 /* If himl1 has no images, merge still succeeds */
1813 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1814 ok(hr == S_OK, "merge himl1,-1 failed\n");
1815 if (hr == S_OK) IImageList_Release(merge);
1817 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1818 ok(hr == S_OK, "merge himl1,0 failed\n");
1819 if (hr == S_OK) IImageList_Release(merge);
1821 /* Same happens if himl2 is empty */
1822 IImageList_Release(imgl2);
1823 himl2 = ImageList_Create(32,32,0,0,3);
1824 ok(himl2 != NULL,"failed to recreate himl2\n");
1826 imgl2 = (IImageList *) himl2;
1828 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
1829 ok(hr == S_OK, "merge himl2,-1 failed\n");
1830 if (hr == S_OK) IImageList_Release(merge);
1832 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1833 ok(hr == S_OK, "merge himl2,0 failed\n");
1834 if (hr == S_OK) IImageList_Release(merge);
1836 /* Now try merging an image with itself */
1837 ret = -1;
1838 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"re-add icon1 to himl2 failed\n");
1840 hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1841 ok(hr == S_OK, "merge himl2 with itself failed\n");
1842 if (hr == S_OK) IImageList_Release(merge);
1844 /* Try merging 2 different image lists */
1845 ret = -1;
1846 ok( IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl1 failed\n");
1848 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1849 ok(hr == S_OK, "merge himl1 with himl2 failed\n");
1850 if (hr == S_OK) IImageList_Release(merge);
1852 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
1853 ok(hr == S_OK, "merge himl1 with himl2 8,16 failed\n");
1854 if (hr == S_OK) IImageList_Release(merge);
1856 IImageList_Release(imgl1);
1857 IImageList_Release(imgl2);
1859 DestroyIcon(hicon1);
1860 DestroyWindow(hwnd);
1863 static void test_iconsize(void)
1865 HIMAGELIST himl;
1866 INT cx, cy;
1867 BOOL ret;
1869 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1870 /* null pointers, not zero imagelist dimensions */
1871 ret = pImageList_GetIconSize(himl, NULL, NULL);
1872 ok(!ret, "got %d\n", ret);
1874 /* doesn't touch return pointers */
1875 cx = 0x1abe11ed;
1876 ret = pImageList_GetIconSize(himl, &cx, NULL);
1877 ok(!ret, "got %d\n", ret);
1878 ok(cx == 0x1abe11ed, "got %d\n", cx);
1880 cy = 0x1abe11ed;
1881 ret = pImageList_GetIconSize(himl, NULL, &cy);
1882 ok(!ret, "got %d\n", ret);
1883 ok(cy == 0x1abe11ed, "got %d\n", cy);
1885 pImageList_Destroy(himl);
1887 ret = pImageList_GetIconSize((HIMAGELIST)0xdeadbeef, &cx, &cy);
1888 ok(!ret, "got %d\n", ret);
1891 static void test_create_destroy(void)
1893 HIMAGELIST himl;
1894 INT cx, cy;
1895 BOOL rc;
1896 INT ret;
1898 /* list with zero or negative image dimensions */
1899 himl = pImageList_Create(0, 0, ILC_COLOR16, 0, 3);
1900 ok(himl == NULL, "got %p\n", himl);
1902 himl = pImageList_Create(0, 16, ILC_COLOR16, 0, 3);
1903 ok(himl == NULL, "got %p\n", himl);
1905 himl = pImageList_Create(16, 0, ILC_COLOR16, 0, 3);
1906 ok(himl == NULL, "got %p\n", himl);
1908 himl = pImageList_Create(16, -1, ILC_COLOR16, 0, 3);
1909 ok(himl == NULL, "got %p\n", himl);
1911 himl = pImageList_Create(-1, 16, ILC_COLOR16, 0, 3);
1912 ok(himl == NULL, "got %p\n", himl);
1914 rc = pImageList_Destroy((HIMAGELIST)0xdeadbeef);
1915 ok(rc == FALSE, "ImageList_Destroy(0xdeadbeef) should fail and not crash\n");
1917 /* DDB image lists */
1918 himl = pImageList_Create(0, 14, ILC_COLORDDB, 4, 4);
1919 ok(himl != NULL, "got %p\n", himl);
1921 pImageList_GetIconSize(himl, &cx, &cy);
1922 ok (cx == 0, "Wrong cx (%i)\n", cx);
1923 ok (cy == 14, "Wrong cy (%i)\n", cy);
1924 pImageList_Destroy(himl);
1926 himl = pImageList_Create(0, 0, ILC_COLORDDB, 4, 4);
1927 ok(himl != NULL, "got %p\n", himl);
1928 pImageList_GetIconSize(himl, &cx, &cy);
1929 ok (cx == 0, "Wrong cx (%i)\n", cx);
1930 ok (cy == 0, "Wrong cy (%i)\n", cy);
1931 pImageList_Destroy(himl);
1933 himl = pImageList_Create(0, 0, ILC_COLORDDB, 0, 4);
1934 ok(himl != NULL, "got %p\n", himl);
1935 pImageList_GetIconSize(himl, &cx, &cy);
1936 ok (cx == 0, "Wrong cx (%i)\n", cx);
1937 ok (cy == 0, "Wrong cy (%i)\n", cy);
1939 pImageList_SetImageCount(himl, 3);
1940 ret = pImageList_GetImageCount(himl);
1941 ok(ret == 3, "Unexpected image count after increase\n");
1943 /* Trying to actually add an image causes a crash on Windows */
1944 pImageList_Destroy(himl);
1946 /* Negative values fail */
1947 himl = pImageList_Create(-1, -1, ILC_COLORDDB, 4, 4);
1948 ok(himl == NULL, "got %p\n", himl);
1949 himl = pImageList_Create(-1, 1, ILC_COLORDDB, 4, 4);
1950 ok(himl == NULL, "got %p\n", himl);
1951 himl = pImageList_Create(1, -1, ILC_COLORDDB, 4, 4);
1952 ok(himl == NULL, "got %p\n", himl);
1955 static void check_color_table(const char *name, HDC hdc, HIMAGELIST himl, UINT ilc,
1956 RGBQUAD *expect, RGBQUAD *broken_expect)
1958 IMAGEINFO info;
1959 INT ret;
1960 char bmi_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1961 BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
1962 int i, depth = ilc & 0xfe;
1964 ret = pImageList_GetImageInfo(himl, 0, &info);
1965 ok(ret, "got %d\n", ret);
1966 ok(info.hbmImage != NULL, "got %p\n", info.hbmImage);
1968 memset(bmi_buffer, 0, sizeof(bmi_buffer));
1969 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
1970 ret = GetDIBits(hdc, info.hbmImage, 0, 0, NULL, bmi, DIB_RGB_COLORS);
1971 ok(ret, "got %d\n", ret);
1972 ok(bmi->bmiHeader.biBitCount == depth, "got %d\n", bmi->bmiHeader.biBitCount);
1974 ret = GetDIBits(hdc, info.hbmImage, 0, 0, NULL, bmi, DIB_RGB_COLORS);
1975 ok(ret, "got %d\n", ret);
1976 ok(bmi->bmiHeader.biBitCount == depth, "got %d\n", bmi->bmiHeader.biBitCount);
1978 for (i = 0; i < (1 << depth); i++)
1979 ok((bmi->bmiColors[i].rgbRed == expect[i].rgbRed &&
1980 bmi->bmiColors[i].rgbGreen == expect[i].rgbGreen &&
1981 bmi->bmiColors[i].rgbBlue == expect[i].rgbBlue) ||
1982 broken(bmi->bmiColors[i].rgbRed == broken_expect[i].rgbRed &&
1983 bmi->bmiColors[i].rgbGreen == broken_expect[i].rgbGreen &&
1984 bmi->bmiColors[i].rgbBlue == broken_expect[i].rgbBlue),
1985 "%d: %s: got color[%d] %02x %02x %02x expect %02x %02x %02x\n", depth, name, i,
1986 bmi->bmiColors[i].rgbRed, bmi->bmiColors[i].rgbGreen, bmi->bmiColors[i].rgbBlue,
1987 expect[i].rgbRed, expect[i].rgbGreen, expect[i].rgbBlue);
1990 static void get_default_color_table(HDC hdc, int bpp, RGBQUAD *table)
1992 char bmi_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1993 BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
1994 HBITMAP tmp;
1995 int i;
1996 HPALETTE pal;
1997 PALETTEENTRY entries[256];
1999 switch (bpp)
2001 case 4:
2002 tmp = CreateBitmap( 1, 1, 1, 1, NULL );
2003 memset(bmi_buffer, 0, sizeof(bmi_buffer));
2004 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
2005 bmi->bmiHeader.biHeight = 1;
2006 bmi->bmiHeader.biWidth = 1;
2007 bmi->bmiHeader.biBitCount = bpp;
2008 bmi->bmiHeader.biPlanes = 1;
2009 bmi->bmiHeader.biCompression = BI_RGB;
2010 GetDIBits( hdc, tmp, 0, 0, NULL, bmi, DIB_RGB_COLORS );
2012 memcpy(table, bmi->bmiColors, (1 << bpp) * sizeof(RGBQUAD));
2013 table[7] = bmi->bmiColors[8];
2014 table[8] = bmi->bmiColors[7];
2015 DeleteObject( tmp );
2016 break;
2018 case 8:
2019 pal = CreateHalftonePalette(hdc);
2020 GetPaletteEntries(pal, 0, 256, entries);
2021 for (i = 0; i < 256; i++)
2023 table[i].rgbRed = entries[i].peRed;
2024 table[i].rgbGreen = entries[i].peGreen;
2025 table[i].rgbBlue = entries[i].peBlue;
2026 table[i].rgbReserved = 0;
2028 DeleteObject(pal);
2029 break;
2031 default:
2032 ok(0, "unhandled depth %d\n", bpp);
2036 static void test_color_table(UINT ilc)
2038 HIMAGELIST himl;
2039 INT ret;
2040 char bmi_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
2041 BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
2042 HDC hdc = CreateCompatibleDC(0);
2043 HBITMAP dib4, dib8, dib32;
2044 RGBQUAD rgb[256], default_table[256];
2046 get_default_color_table(hdc, ilc & 0xfe, default_table);
2048 himl = pImageList_Create(16, 16, ilc, 0, 3);
2049 ok(himl != NULL, "got %p\n", himl);
2051 memset(bmi_buffer, 0, sizeof(bmi_buffer));
2052 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
2053 bmi->bmiHeader.biHeight = 16;
2054 bmi->bmiHeader.biWidth = 16;
2055 bmi->bmiHeader.biBitCount = 8;
2056 bmi->bmiHeader.biPlanes = 1;
2057 bmi->bmiHeader.biCompression = BI_RGB;
2058 bmi->bmiColors[0].rgbRed = 0xff;
2059 bmi->bmiColors[1].rgbGreen = 0xff;
2060 bmi->bmiColors[2].rgbBlue = 0xff;
2062 dib8 = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
2064 bmi->bmiHeader.biBitCount = 4;
2065 bmi->bmiColors[0].rgbRed = 0xff;
2066 bmi->bmiColors[0].rgbGreen = 0x00;
2067 bmi->bmiColors[0].rgbBlue = 0xff;
2068 bmi->bmiColors[1].rgbRed = 0xff;
2069 bmi->bmiColors[1].rgbGreen = 0xff;
2070 bmi->bmiColors[1].rgbBlue = 0x00;
2071 bmi->bmiColors[2].rgbRed = 0x00;
2072 bmi->bmiColors[2].rgbGreen = 0xff;
2073 bmi->bmiColors[2].rgbBlue = 0xff;
2075 dib4 = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
2077 bmi->bmiHeader.biBitCount = 32;
2079 dib32 = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
2081 /* add 32 first then 8. This won't set the color table */
2082 ret = pImageList_Add(himl, dib32, NULL);
2083 ok(ret == 0, "got %d\n", ret);
2084 ret = pImageList_Add(himl, dib8, NULL);
2085 ok(ret == 1, "got %d\n", ret);
2087 check_color_table("add 32, 8", hdc, himl, ilc, default_table, NULL);
2089 /* since the previous _Adds didn't set the color table, this one will */
2090 ret = pImageList_Remove(himl, -1);
2091 ok(ret, "got %d\n", ret);
2092 ret = pImageList_Add(himl, dib8, NULL);
2093 ok(ret == 0, "got %d\n", ret);
2095 memset(rgb, 0, sizeof(rgb));
2096 rgb[0].rgbRed = 0xff;
2097 rgb[1].rgbGreen = 0xff;
2098 rgb[2].rgbBlue = 0xff;
2099 check_color_table("remove all, add 8", hdc, himl, ilc, rgb, default_table);
2101 /* remove all, add 4. Color table remains the same since it's inplicitly
2102 been set by the previous _Add */
2103 ret = pImageList_Remove(himl, -1);
2104 ok(ret, "got %d\n", ret);
2105 ret = pImageList_Add(himl, dib4, NULL);
2106 ok(ret == 0, "got %d\n", ret);
2107 check_color_table("remove all, add 4", hdc, himl, ilc, rgb, default_table);
2109 pImageList_Destroy(himl);
2110 himl = pImageList_Create(16, 16, ilc, 0, 3);
2111 ok(himl != NULL, "got %p\n", himl);
2113 /* add 4 */
2114 ret = pImageList_Add(himl, dib4, NULL);
2115 ok(ret == 0, "got %d\n", ret);
2117 memset(rgb, 0, 16 * sizeof(rgb[0]));
2118 rgb[0].rgbRed = 0xff;
2119 rgb[0].rgbBlue = 0xff;
2120 rgb[1].rgbRed = 0xff;
2121 rgb[1].rgbGreen = 0xff;
2122 rgb[2].rgbGreen = 0xff;
2123 rgb[2].rgbBlue = 0xff;
2124 memcpy(rgb + 16, default_table + 16, 240 * sizeof(rgb[0]));
2126 check_color_table("add 4", hdc, himl, ilc, rgb, default_table);
2128 pImageList_Destroy(himl);
2129 himl = pImageList_Create(16, 16, ilc, 0, 3);
2130 ok(himl != NULL, "got %p\n", himl);
2132 /* set color table, add 8 */
2133 ret = pImageList_Remove(himl, -1);
2134 ok(ret, "got %d\n", ret);
2135 memset(rgb, 0, sizeof(rgb));
2136 rgb[0].rgbRed = 0xcc;
2137 rgb[1].rgbBlue = 0xcc;
2138 ret = pImageList_SetColorTable(himl, 0, 2, rgb);
2139 ok(ret == 2, "got %d\n", ret);
2140 /* the table is set, so this doesn't change it */
2141 ret = pImageList_Add(himl, dib8, NULL);
2142 ok(ret == 0, "got %d\n", ret);
2144 memcpy(rgb + 2, default_table + 2, 254 * sizeof(rgb[0]));
2145 check_color_table("SetColorTable", hdc, himl, ilc, rgb, NULL);
2147 DeleteObject(dib32);
2148 DeleteObject(dib8);
2149 DeleteObject(dib4);
2150 DeleteDC(hdc);
2151 pImageList_Destroy(himl);
2154 static void test_copy(void)
2156 HIMAGELIST dst, src;
2157 BOOL ret;
2158 int count;
2160 dst = pImageList_Create(5, 11, ILC_COLOR, 1, 1);
2161 count = pImageList_GetImageCount(dst);
2162 ok(!count, "ImageList not empty.\n");
2163 src = createImageList(7, 13);
2164 count = pImageList_GetImageCount(src);
2165 ok(count > 2, "Tests need an ImageList with more than 2 images\n");
2167 /* ImageList_Copy() cannot copy between two ImageLists */
2168 ret = pImageList_Copy(dst, 0, src, 2, ILCF_MOVE);
2169 ok(!ret, "ImageList_Copy() should have returned FALSE\n");
2170 count = pImageList_GetImageCount(dst);
2171 ok(count == 0, "Expected no image in dst ImageList, got %d\n", count);
2173 pImageList_Destroy(dst);
2174 pImageList_Destroy(src);
2177 static void test_loadimage(void)
2179 HIMAGELIST list;
2180 DWORD flags;
2182 list = pImageList_LoadImageW( hinst, MAKEINTRESOURCEW(IDB_BITMAP_128x15), 16, 1, CLR_DEFAULT,
2183 IMAGE_BITMAP, LR_CREATEDIBSECTION );
2184 ok( list != NULL, "got %p\n", list );
2185 flags = pImageList_GetFlags( list );
2186 ok( flags == (ILC_COLOR4 | ILC_MASK), "got %08x\n", flags );
2187 pImageList_Destroy( list );
2189 list = pImageList_LoadImageW( hinst, MAKEINTRESOURCEW(IDB_BITMAP_128x15), 16, 1, CLR_NONE,
2190 IMAGE_BITMAP, LR_CREATEDIBSECTION );
2191 ok( list != NULL, "got %p\n", list );
2192 flags = pImageList_GetFlags( list );
2193 ok( flags == ILC_COLOR4, "got %08x\n", flags );
2194 pImageList_Destroy( list );
2197 static void test_IImageList_Clone(void)
2199 IImageList *imgl, *imgl2;
2200 HIMAGELIST himl;
2201 HRESULT hr;
2202 ULONG ref;
2204 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2205 imgl = (IImageList*)himl;
2207 if (0)
2209 /* crashes on native */
2210 IImageList_Clone(imgl, &IID_IImageList, NULL);
2213 hr = IImageList_Clone(imgl, &IID_IImageList, (void**)&imgl2);
2214 ok(hr == S_OK, "got 0x%08x\n", hr);
2215 ref = IImageList_Release(imgl2);
2216 ok(ref == 0, "got %u\n", ref);
2218 IImageList_Release(imgl);
2221 static void test_IImageList_GetBkColor(void)
2223 IImageList *imgl;
2224 HIMAGELIST himl;
2225 COLORREF color;
2226 HRESULT hr;
2228 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2229 imgl = (IImageList*)himl;
2231 if (0)
2233 /* crashes on native */
2234 IImageList_GetBkColor(imgl, NULL);
2237 hr = IImageList_GetBkColor(imgl, &color);
2238 ok(hr == S_OK, "got 0x%08x\n", hr);
2240 IImageList_Release(imgl);
2243 static void test_IImageList_SetBkColor(void)
2245 IImageList *imgl;
2246 HIMAGELIST himl;
2247 COLORREF color;
2248 HRESULT hr;
2250 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2251 imgl = (IImageList*)himl;
2253 if (0)
2255 /* crashes on native */
2256 IImageList_SetBkColor(imgl, RGB(0, 0, 0), NULL);
2259 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
2260 ok(hr == S_OK, "got 0x%08x\n", hr);
2262 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
2263 ok(hr == S_OK, "got 0x%08x\n", hr);
2265 color = 0xdeadbeef;
2266 hr = IImageList_GetBkColor(imgl, &color);
2267 ok(hr == S_OK, "got 0x%08x\n", hr);
2268 ok(color == CLR_NONE, "got %x\n", color);
2270 IImageList_Release(imgl);
2273 static void test_IImageList_GetImageCount(void)
2275 IImageList *imgl;
2276 HIMAGELIST himl;
2277 int count;
2278 HRESULT hr;
2280 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2281 imgl = (IImageList*)himl;
2283 if (0)
2285 /* crashes on native */
2286 IImageList_GetImageCount(imgl, NULL);
2289 count = -1;
2290 hr = IImageList_GetImageCount(imgl, &count);
2291 ok(hr == S_OK, "got 0x%08x\n", hr);
2292 ok(count == 0, "got %d\n", count);
2294 IImageList_Release(imgl);
2297 static void test_IImageList_GetIconSize(void)
2299 IImageList *imgl;
2300 HIMAGELIST himl;
2301 int cx, cy;
2302 HRESULT hr;
2304 himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2305 imgl = (IImageList*)himl;
2307 hr = IImageList_GetIconSize(imgl, NULL, NULL);
2308 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2310 hr = IImageList_GetIconSize(imgl, &cx, NULL);
2311 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2313 hr = IImageList_GetIconSize(imgl, NULL, &cy);
2314 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2316 IImageList_Release(imgl);
2319 static void init_functions(void)
2321 HMODULE hComCtl32 = GetModuleHandleA("comctl32.dll");
2323 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
2324 #define X2(f, ord) p##f = (void*)GetProcAddress(hComCtl32, (const char *)ord);
2325 X(ImageList_Create);
2326 X(ImageList_Destroy);
2327 X(ImageList_Add);
2328 X(ImageList_DrawIndirect);
2329 X(ImageList_SetImageCount);
2330 X(ImageList_SetImageCount);
2331 X2(ImageList_SetColorTable, 390);
2332 X(ImageList_GetFlags);
2333 X(ImageList_BeginDrag);
2334 X(ImageList_GetDragImage);
2335 X(ImageList_EndDrag);
2336 X(ImageList_GetImageCount);
2337 X(ImageList_SetDragCursorImage);
2338 X(ImageList_GetIconSize);
2339 X(ImageList_Remove);
2340 X(ImageList_ReplaceIcon);
2341 X(ImageList_Replace);
2342 X(ImageList_Merge);
2343 X(ImageList_GetImageInfo);
2344 X(ImageList_Write);
2345 X(ImageList_Read);
2346 X(ImageList_Copy);
2347 X(ImageList_LoadImageW);
2348 X(ImageList_CoCreateInstance);
2349 X(HIMAGELIST_QueryInterface);
2350 #undef X
2351 #undef X2
2354 START_TEST(imagelist)
2356 ULONG_PTR ctx_cookie;
2357 HANDLE hCtx;
2359 init_functions();
2361 hinst = GetModuleHandleA(NULL);
2363 InitCommonControls();
2365 test_create_destroy();
2366 test_begindrag();
2367 test_hotspot();
2368 test_add_remove();
2369 test_imagecount();
2370 test_DrawIndirect();
2371 test_merge();
2372 test_merge_colors();
2373 test_imagelist_storage();
2374 test_iconsize();
2375 test_color_table(ILC_COLOR4);
2376 test_color_table(ILC_COLOR8);
2377 test_copy();
2378 test_loadimage();
2380 /* Now perform v6 tests */
2381 if (!load_v6_module(&ctx_cookie, &hCtx))
2382 return;
2384 init_functions();
2386 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2388 /* Do v6.0 tests */
2389 test_add_remove();
2390 test_imagecount();
2391 test_DrawIndirect();
2392 test_merge();
2393 test_iconsize();
2394 test_color_table(ILC_COLOR4);
2395 test_color_table(ILC_COLOR8);
2396 test_copy();
2397 test_loadimage();
2399 test_ImageList_DrawIndirect();
2400 test_shell_imagelist();
2401 test_iimagelist();
2403 test_IImageList_Add_Remove();
2404 test_IImageList_Get_SetImageCount();
2405 test_IImageList_Draw();
2406 test_IImageList_Merge();
2407 test_IImageList_Clone();
2408 test_IImageList_GetBkColor();
2409 test_IImageList_SetBkColor();
2410 test_IImageList_GetImageCount();
2411 test_IImageList_GetIconSize();
2413 CoUninitialize();
2415 unload_v6_module(ctx_cookie, hCtx);