comctl32/tests: Add some more tests for ImageList_Write.
[wine.git] / dlls / comctl32 / tests / imagelist.c
blob85eb13e0b4e53b4ce28159a9b5fac181aae128d9
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>
29 #include <assert.h>
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35 #include "objbase.h"
36 #include "commctrl.h" /* must be included after objbase.h to get ImageList_Write */
37 #include "initguid.h"
38 #include "commoncontrols.h"
39 #include "shellapi.h"
41 #include "wine/test.h"
42 #include "v6util.h"
44 #undef VISIBLE
46 #ifdef VISIBLE
47 #define WAIT Sleep (1000)
48 #define REDRAW(hwnd) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW)
49 #else
50 #define WAIT
51 #define REDRAW(hwnd)
52 #endif
54 #define IMAGELIST_MAGIC (('L' << 8) | 'I')
56 #include "pshpack2.h"
57 /* Header used by ImageList_Read() and ImageList_Write() */
58 typedef struct _ILHEAD
60 USHORT usMagic;
61 USHORT usVersion;
62 WORD cCurImage;
63 WORD cMaxImage;
64 WORD cGrow;
65 WORD cx;
66 WORD cy;
67 COLORREF bkcolor;
68 WORD flags;
69 SHORT ovls[4];
70 } ILHEAD;
71 #include "poppack.h"
73 static HIMAGELIST (WINAPI *pImageList_Create)(int, int, UINT, int, int);
74 static int (WINAPI *pImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP);
75 static BOOL (WINAPI *pImageList_DrawIndirect)(IMAGELISTDRAWPARAMS*);
76 static BOOL (WINAPI *pImageList_SetImageCount)(HIMAGELIST,UINT);
77 static HRESULT (WINAPI *pImageList_CoCreateInstance)(REFCLSID,const IUnknown *,
78 REFIID,void **);
79 static HRESULT (WINAPI *pHIMAGELIST_QueryInterface)(HIMAGELIST,REFIID,void **);
81 static HINSTANCE hinst;
83 /* These macros build cursor/bitmap data in 4x4 pixel blocks */
84 #define B(x,y) ((x?0xf0:0)|(y?0xf:0))
85 #define ROW1(a,b,c,d,e,f,g,h) B(a,b),B(c,d),B(e,f),B(g,h)
86 #define ROW32(a,b,c,d,e,f,g,h) ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h), \
87 ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h)
88 #define ROW2(a,b,c,d,e,f,g,h,i,j,k,l) ROW1(a,b,c,d,e,f,g,h),B(i,j),B(k,l)
89 #define ROW48(a,b,c,d,e,f,g,h,i,j,k,l) ROW2(a,b,c,d,e,f,g,h,i,j,k,l), \
90 ROW2(a,b,c,d,e,f,g,h,i,j,k,l), ROW2(a,b,c,d,e,f,g,h,i,j,k,l), \
91 ROW2(a,b,c,d,e,f,g,h,i,j,k,l)
93 static const BYTE empty_bits[48*48/8];
95 static const BYTE icon_bits[32*32/8] =
97 ROW32(0,0,0,0,0,0,0,0),
98 ROW32(0,0,1,1,1,1,0,0),
99 ROW32(0,1,1,1,1,1,1,0),
100 ROW32(0,1,1,0,0,1,1,0),
101 ROW32(0,1,1,0,0,1,1,0),
102 ROW32(0,1,1,1,1,1,1,0),
103 ROW32(0,0,1,1,1,1,0,0),
104 ROW32(0,0,0,0,0,0,0,0)
107 static const BYTE bitmap_bits[48*48/8] =
109 ROW48(0,0,0,0,0,0,0,0,0,0,0,0),
110 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
111 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
112 ROW48(0,1,0,0,0,0,0,0,1,0,1,0),
113 ROW48(0,1,0,0,0,0,0,1,0,0,1,0),
114 ROW48(0,1,0,0,0,0,1,0,0,0,1,0),
115 ROW48(0,1,0,0,0,1,0,0,0,0,1,0),
116 ROW48(0,1,0,0,1,0,0,0,0,0,1,0),
117 ROW48(0,1,0,1,0,0,0,0,0,0,1,0),
118 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
119 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
120 ROW48(0,0,0,0,0,0,0,0,0,0,0,0)
123 static HIMAGELIST createImageList(int cx, int cy)
125 /* Create an ImageList and put an image into it */
126 HIMAGELIST himl = ImageList_Create(cx, cy, ILC_COLOR, 1, 1);
127 HBITMAP hbm = CreateBitmap(48, 48, 1, 1, bitmap_bits);
128 ImageList_Add(himl, hbm, NULL);
129 DeleteObject(hbm);
130 return himl;
133 static HWND create_a_window(void)
135 char className[] = "bmwnd";
136 char winName[] = "Test Bitmap";
137 HWND hWnd;
138 static int registered = 0;
140 if (!registered)
142 WNDCLASSA cls;
144 cls.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
145 cls.lpfnWndProc = DefWindowProcA;
146 cls.cbClsExtra = 0;
147 cls.cbWndExtra = 0;
148 cls.hInstance = 0;
149 cls.hIcon = LoadIconA (0, IDI_APPLICATION);
150 cls.hCursor = LoadCursorA (0, IDC_ARROW);
151 cls.hbrBackground = GetStockObject (WHITE_BRUSH);
152 cls.lpszMenuName = 0;
153 cls.lpszClassName = className;
155 RegisterClassA (&cls);
156 registered = 1;
159 /* Setup window */
160 hWnd = CreateWindowA (className, winName,
161 WS_OVERLAPPEDWINDOW ,
162 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
163 0, hinst, 0);
165 #ifdef VISIBLE
166 ShowWindow (hWnd, SW_SHOW);
167 #endif
168 REDRAW(hWnd);
169 WAIT;
171 return hWnd;
174 static HDC show_image(HWND hwnd, HIMAGELIST himl, int idx, int size,
175 LPCSTR loc, BOOL clear)
177 HDC hdc = NULL;
178 #ifdef VISIBLE
179 if (!himl) return NULL;
181 SetWindowText(hwnd, loc);
182 hdc = GetDC(hwnd);
183 ImageList_Draw(himl, idx, hdc, 0, 0, ILD_TRANSPARENT);
185 REDRAW(hwnd);
186 WAIT;
188 if (clear)
190 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
191 ReleaseDC(hwnd, hdc);
192 hdc = NULL;
194 #endif /* VISIBLE */
195 return hdc;
198 /* Useful for checking differences */
199 #if 0
200 static void dump_bits(const BYTE *p, const BYTE *q, int size)
202 int i, j;
204 size /= 8;
206 for (i = 0; i < size * 2; i++)
208 printf("|");
209 for (j = 0; j < size; j++)
210 printf("%c%c", p[j] & 0xf0 ? 'X' : ' ', p[j] & 0xf ? 'X' : ' ');
211 printf(" -- ");
212 for (j = 0; j < size; j++)
213 printf("%c%c", q[j] & 0xf0 ? 'X' : ' ', q[j] & 0xf ? 'X' : ' ');
214 printf("|\n");
215 p += size * 4;
216 q += size * 4;
218 printf("\n");
220 #endif
222 static void check_bits(HWND hwnd, HIMAGELIST himl, int idx, int size,
223 const BYTE *checkbits, LPCSTR loc)
225 #ifdef VISIBLE
226 BYTE bits[100*100/8];
227 COLORREF c;
228 HDC hdc;
229 int x, y, i = -1;
231 if (!himl) return;
233 memset(bits, 0, sizeof(bits));
234 hdc = show_image(hwnd, himl, idx, size, loc, FALSE);
236 c = GetPixel(hdc, 0, 0);
238 for (y = 0; y < size; y ++)
240 for (x = 0; x < size; x++)
242 if (!(x & 0x7)) i++;
243 if (GetPixel(hdc, x, y) != c) bits[i] |= (0x80 >> (x & 0x7));
247 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
248 ReleaseDC(hwnd, hdc);
250 ok (memcmp(bits, checkbits, (size * size)/8) == 0,
251 "%s: bits different\n", loc);
252 if (memcmp(bits, checkbits, (size * size)/8))
253 dump_bits(bits, checkbits, size);
254 #endif /* VISIBLE */
257 static void test_hotspot(void)
259 struct hotspot {
260 int dx;
261 int dy;
264 #define SIZEX1 47
265 #define SIZEY1 31
266 #define SIZEX2 11
267 #define SIZEY2 17
268 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
269 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
270 { 10, 7 },
271 { SIZEX1, SIZEY1 },
272 { -9, -8 },
273 { -7, 35 }
275 int i, j, ret;
276 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
277 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
278 HWND hwnd = create_a_window();
281 for (i = 0; i < HOTSPOTS_MAX; i++) {
282 for (j = 0; j < HOTSPOTS_MAX; j++) {
283 int dx1 = hotspots[i].dx;
284 int dy1 = hotspots[i].dy;
285 int dx2 = hotspots[j].dx;
286 int dy2 = hotspots[j].dy;
287 int correctx, correcty, newx, newy;
288 char loc[256];
289 HIMAGELIST himlNew;
290 POINT ppt;
292 ret = ImageList_BeginDrag(himl1, 0, dx1, dy1);
293 ok(ret != 0, "BeginDrag failed for { %d, %d }\n", dx1, dy1);
294 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
295 show_image(hwnd, himl1, 0, max(SIZEX1, SIZEY1), loc, TRUE);
297 /* check merging the dragged image with a second image */
298 ret = ImageList_SetDragCursorImage(himl2, 0, dx2, dy2);
299 ok(ret != 0, "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
300 dx1, dy1, dx2, dy2);
301 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
302 show_image(hwnd, himl2, 0, max(SIZEX2, SIZEY2), loc, TRUE);
304 /* check new hotspot, it should be the same like the old one */
305 himlNew = ImageList_GetDragImage(NULL, &ppt);
306 ok(ppt.x == dx1 && ppt.y == dy1,
307 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
308 dx1, dy1, ppt.x, ppt.y);
309 /* check size of new dragged image */
310 ImageList_GetIconSize(himlNew, &newx, &newy);
311 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
312 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
313 ok(newx == correctx && newy == correcty,
314 "Expected drag image size [%d,%d] got [%d,%d]\n",
315 correctx, correcty, newx, newy);
316 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
317 show_image(hwnd, himlNew, 0, max(correctx, correcty), loc, TRUE);
318 ImageList_EndDrag();
321 #undef SIZEX1
322 #undef SIZEY1
323 #undef SIZEX2
324 #undef SIZEY2
325 #undef HOTSPOTS_MAX
326 ImageList_Destroy(himl2);
327 ImageList_Destroy(himl1);
328 DestroyWindow(hwnd);
331 static void test_add_remove(void)
333 HIMAGELIST himl ;
335 HICON hicon1 ;
336 HICON hicon2 ;
337 HICON hicon3 ;
339 /* create an imagelist to play with */
340 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
341 ok(himl!=0,"failed to create imagelist\n");
343 /* load the icons to add to the image list */
344 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
345 ok(hicon1 != 0, "no hicon1\n");
346 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
347 ok(hicon2 != 0, "no hicon2\n");
348 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
349 ok(hicon3 != 0, "no hicon3\n");
351 /* remove when nothing exists */
352 ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
353 /* removing everything from an empty imagelist should succeed */
354 ok(ImageList_RemoveAll(himl),"removed nonexistent icon\n");
356 /* add three */
357 ok(0==ImageList_AddIcon(himl, hicon1),"failed to add icon1\n");
358 ok(1==ImageList_AddIcon(himl, hicon2),"failed to add icon2\n");
359 ok(2==ImageList_AddIcon(himl, hicon3),"failed to add icon3\n");
361 /* remove an index out of range */
362 ok(!ImageList_Remove(himl,4711),"removed nonexistent icon\n");
364 /* remove three */
365 ok(ImageList_Remove(himl,0),"can't remove 0\n");
366 ok(ImageList_Remove(himl,0),"can't remove 0\n");
367 ok(ImageList_Remove(himl,0),"can't remove 0\n");
369 /* remove one extra */
370 ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
372 /* destroy it */
373 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
375 ok(-1==ImageList_AddIcon((HIMAGELIST)0xdeadbeef, hicon1),"don't crash on bad handle\n");
377 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
378 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
379 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
382 static void test_imagecount(void)
384 HIMAGELIST himl;
386 ok(0==ImageList_GetImageCount((HIMAGELIST)0xdeadbeef),"don't crash on bad handle\n");
388 if (!pImageList_SetImageCount)
390 win_skip("ImageList_SetImageCount not available\n");
391 return;
394 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
395 ok(himl!=0,"failed to create imagelist\n");
397 ok(pImageList_SetImageCount(himl, 3), "couldn't increase image count\n");
398 ok(ImageList_GetImageCount(himl) == 3, "invalid image count after increase\n");
399 ok(pImageList_SetImageCount(himl, 1), "couldn't decrease image count\n");
400 ok(ImageList_GetImageCount(himl) == 1, "invalid image count after decrease to 1\n");
401 ok(pImageList_SetImageCount(himl, 0), "couldn't decrease image count\n");
402 ok(ImageList_GetImageCount(himl) == 0, "invalid image count after decrease to 0\n");
404 ok(ImageList_Destroy(himl), "destroy imagelist failed\n");
407 static void test_DrawIndirect(void)
409 HIMAGELIST himl;
411 HBITMAP hbm1;
412 HBITMAP hbm2;
413 HBITMAP hbm3;
415 IMAGELISTDRAWPARAMS imldp;
416 HDC hdc;
417 HWND hwndfortest;
419 if (!pImageList_DrawIndirect)
421 win_skip("ImageList_DrawIndirect not available, skipping test\n");
422 return;
425 hwndfortest = create_a_window();
426 hdc = GetDC(hwndfortest);
427 ok(hdc!=NULL, "couldn't get DC\n");
429 /* create an imagelist to play with */
430 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
431 ok(himl!=0,"failed to create imagelist\n");
433 /* load the icons to add to the image list */
434 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
435 ok(hbm1 != 0, "no bitmap 1\n");
436 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
437 ok(hbm2 != 0, "no bitmap 2\n");
438 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
439 ok(hbm3 != 0, "no bitmap 3\n");
441 /* add three */
442 ok(0==ImageList_Add(himl, hbm1, 0),"failed to add bitmap 1\n");
443 ok(1==ImageList_Add(himl, hbm2, 0),"failed to add bitmap 2\n");
445 if (pImageList_SetImageCount)
447 ok(pImageList_SetImageCount(himl,3),"Setimage count failed\n");
448 /*ok(2==ImageList_Add(himl, hbm3, NULL),"failed to add bitmap 3\n"); */
449 ok(ImageList_Replace(himl, 2, hbm3, 0),"failed to replace bitmap 3\n");
452 memset(&imldp, 0, sizeof (imldp));
453 ok(!pImageList_DrawIndirect(&imldp), "zero data succeeded!\n");
454 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
455 ok(!pImageList_DrawIndirect(&imldp), "zero hdc succeeded!\n");
456 imldp.hdcDst = hdc;
457 ok(!pImageList_DrawIndirect(&imldp),"zero himl succeeded!\n");
458 imldp.himl = (HIMAGELIST)0xdeadbeef;
459 ok(!pImageList_DrawIndirect(&imldp),"bad himl succeeded!\n");
460 imldp.himl = himl;
462 REDRAW(hwndfortest);
463 WAIT;
465 imldp.fStyle = SRCCOPY;
466 imldp.rgbBk = CLR_DEFAULT;
467 imldp.rgbFg = CLR_DEFAULT;
468 imldp.y = 100;
469 imldp.x = 100;
470 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
471 imldp.i ++;
472 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
473 imldp.i ++;
474 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
475 imldp.i ++;
476 ok(!pImageList_DrawIndirect(&imldp),"should fail\n");
478 /* remove three */
479 ok(ImageList_Remove(himl, 0), "removing 1st bitmap\n");
480 ok(ImageList_Remove(himl, 0), "removing 2nd bitmap\n");
481 ok(ImageList_Remove(himl, 0), "removing 3rd bitmap\n");
483 /* destroy it */
484 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
486 /* bitmaps should not be deleted by the imagelist */
487 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
488 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
489 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
491 ReleaseDC(hwndfortest, hdc);
492 DestroyWindow(hwndfortest);
495 static void test_merge(void)
497 HIMAGELIST himl1, himl2, hmerge;
498 HICON hicon1;
499 HWND hwnd = create_a_window();
501 himl1 = ImageList_Create(32,32,0,0,3);
502 ok(himl1 != NULL,"failed to create himl1\n");
504 himl2 = ImageList_Create(32,32,0,0,3);
505 ok(himl2 != NULL,"failed to create himl2\n");
507 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
508 ok(hicon1 != NULL, "failed to create hicon1\n");
510 if (!himl1 || !himl2 || !hicon1)
511 return;
513 ok(0==ImageList_AddIcon(himl2, hicon1),"add icon1 to himl2 failed\n");
514 check_bits(hwnd, himl2, 0, 32, icon_bits, "add icon1 to himl2");
516 /* If himl1 has no images, merge still succeeds */
517 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
518 ok(hmerge != NULL, "merge himl1,-1 failed\n");
519 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,-1");
520 if (hmerge) ImageList_Destroy(hmerge);
522 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
523 ok(hmerge != NULL,"merge himl1,0 failed\n");
524 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,0");
525 if (hmerge) ImageList_Destroy(hmerge);
527 /* Same happens if himl2 is empty */
528 ImageList_Destroy(himl2);
529 himl2 = ImageList_Create(32,32,0,0,3);
530 ok(himl2 != NULL,"failed to recreate himl2\n");
531 if (!himl2)
532 return;
534 hmerge = ImageList_Merge(himl1, -1, himl2, -1, 0, 0);
535 ok(hmerge != NULL, "merge himl2,-1 failed\n");
536 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,-1");
537 if (hmerge) ImageList_Destroy(hmerge);
539 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
540 ok(hmerge != NULL, "merge himl2,0 failed\n");
541 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,0");
542 if (hmerge) ImageList_Destroy(hmerge);
544 /* Now try merging an image with itself */
545 ok(0==ImageList_AddIcon(himl2, hicon1),"re-add icon1 to himl2 failed\n");
547 hmerge = ImageList_Merge(himl2, 0, himl2, 0, 0, 0);
548 ok(hmerge != NULL, "merge himl2 with itself failed\n");
549 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2 with itself");
550 if (hmerge) ImageList_Destroy(hmerge);
552 /* Try merging 2 different image lists */
553 ok(0==ImageList_AddIcon(himl1, hicon1),"add icon1 to himl1 failed\n");
555 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
556 ok(hmerge != NULL, "merge himl1 with himl2 failed\n");
557 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2");
558 if (hmerge) ImageList_Destroy(hmerge);
560 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 8, 16);
561 ok(hmerge != NULL, "merge himl1 with himl2 8,16 failed\n");
562 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2, 8,16");
563 if (hmerge) ImageList_Destroy(hmerge);
565 ImageList_Destroy(himl1);
566 ImageList_Destroy(himl2);
567 DestroyIcon(hicon1);
568 DestroyWindow(hwnd);
571 /*********************** imagelist storage test ***************************/
573 #define BMP_CX 48
575 struct my_IStream
577 IStream IStream_iface;
578 char *iml_data; /* written imagelist data */
579 ULONG iml_data_size;
582 static struct my_IStream *impl_from_IStream(IStream *iface)
584 return CONTAINING_RECORD(iface, struct my_IStream, IStream_iface);
587 static HRESULT STDMETHODCALLTYPE Test_Stream_QueryInterface(IStream *iface, REFIID riid,
588 void **ppvObject)
590 assert(0);
591 return E_NOTIMPL;
594 static ULONG STDMETHODCALLTYPE Test_Stream_AddRef(IStream *iface)
596 assert(0);
597 return 2;
600 static ULONG STDMETHODCALLTYPE Test_Stream_Release(IStream *iface)
602 assert(0);
603 return 1;
606 static HRESULT STDMETHODCALLTYPE Test_Stream_Read(IStream *iface, void *pv, ULONG cb,
607 ULONG *pcbRead)
609 assert(0);
610 return E_NOTIMPL;
613 static BOOL allocate_storage(struct my_IStream *my_is, ULONG add)
615 my_is->iml_data_size += add;
617 if (!my_is->iml_data)
618 my_is->iml_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data_size);
619 else
620 my_is->iml_data = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data, my_is->iml_data_size);
622 return my_is->iml_data ? TRUE : FALSE;
625 static HRESULT STDMETHODCALLTYPE Test_Stream_Write(IStream *iface, const void *pv, ULONG cb,
626 ULONG *pcbWritten)
628 struct my_IStream *my_is = impl_from_IStream(iface);
629 ULONG current_iml_data_size = my_is->iml_data_size;
631 if (!allocate_storage(my_is, cb)) return E_FAIL;
633 memcpy(my_is->iml_data + current_iml_data_size, pv, cb);
634 if (pcbWritten) *pcbWritten = cb;
636 return S_OK;
639 static HRESULT STDMETHODCALLTYPE Test_Stream_Seek(IStream *iface, LARGE_INTEGER dlibMove,
640 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
642 assert(0);
643 return E_NOTIMPL;
646 static HRESULT STDMETHODCALLTYPE Test_Stream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
648 assert(0);
649 return E_NOTIMPL;
652 static HRESULT STDMETHODCALLTYPE Test_Stream_CopyTo(IStream *iface, IStream *pstm,
653 ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead,
654 ULARGE_INTEGER *pcbWritten)
656 assert(0);
657 return E_NOTIMPL;
660 static HRESULT STDMETHODCALLTYPE Test_Stream_Commit(IStream *iface, DWORD grfCommitFlags)
662 assert(0);
663 return E_NOTIMPL;
666 static HRESULT STDMETHODCALLTYPE Test_Stream_Revert(IStream *iface)
668 assert(0);
669 return E_NOTIMPL;
672 static HRESULT STDMETHODCALLTYPE Test_Stream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset,
673 ULARGE_INTEGER cb, DWORD dwLockType)
675 assert(0);
676 return E_NOTIMPL;
679 static HRESULT STDMETHODCALLTYPE Test_Stream_UnlockRegion(IStream *iface, ULARGE_INTEGER libOffset,
680 ULARGE_INTEGER cb, DWORD dwLockType)
682 assert(0);
683 return E_NOTIMPL;
686 static HRESULT STDMETHODCALLTYPE Test_Stream_Stat(IStream *iface, STATSTG *pstatstg,
687 DWORD grfStatFlag)
689 assert(0);
690 return E_NOTIMPL;
693 static HRESULT STDMETHODCALLTYPE Test_Stream_Clone(IStream *iface, IStream **ppstm)
695 assert(0);
696 return E_NOTIMPL;
699 static const IStreamVtbl Test_Stream_Vtbl =
701 Test_Stream_QueryInterface,
702 Test_Stream_AddRef,
703 Test_Stream_Release,
704 Test_Stream_Read,
705 Test_Stream_Write,
706 Test_Stream_Seek,
707 Test_Stream_SetSize,
708 Test_Stream_CopyTo,
709 Test_Stream_Commit,
710 Test_Stream_Revert,
711 Test_Stream_LockRegion,
712 Test_Stream_UnlockRegion,
713 Test_Stream_Stat,
714 Test_Stream_Clone
717 static struct my_IStream Test_Stream = { { &Test_Stream_Vtbl }, 0, 0 };
719 static INT DIB_GetWidthBytes( int width, int bpp )
721 return ((width * bpp + 31) / 8) & ~3;
724 static ULONG check_bitmap_data(const char *bm_data, ULONG bm_data_size,
725 INT width, INT height, INT bpp,
726 const char *comment)
728 const BITMAPFILEHEADER *bmfh = (const BITMAPFILEHEADER *)bm_data;
729 const BITMAPINFOHEADER *bmih = (const BITMAPINFOHEADER *)(bm_data + sizeof(*bmfh));
730 ULONG hdr_size, image_size;
732 hdr_size = sizeof(*bmfh) + sizeof(*bmih);
733 if (bmih->biBitCount <= 8) hdr_size += (1 << bpp) * sizeof(RGBQUAD);
735 ok(bmfh->bfType == (('M' << 8) | 'B'), "wrong bfType 0x%02x\n", bmfh->bfType);
736 ok(bmfh->bfSize == hdr_size, "wrong bfSize 0x%02x\n", bmfh->bfSize);
737 ok(bmfh->bfReserved1 == 0, "wrong bfReserved1 0x%02x\n", bmfh->bfReserved1);
738 ok(bmfh->bfReserved2 == 0, "wrong bfReserved2 0x%02x\n", bmfh->bfReserved2);
739 ok(bmfh->bfOffBits == hdr_size, "wrong bfOffBits 0x%02x\n", bmfh->bfOffBits);
741 ok(bmih->biSize == sizeof(*bmih), "wrong biSize %d\n", bmih->biSize);
742 ok(bmih->biWidth == width, "wrong biWidth %d (expected %d)\n", bmih->biWidth, width);
743 ok(bmih->biHeight == height, "wrong biHeight %d (expected %d)\n", bmih->biHeight, height);
744 ok(bmih->biPlanes == 1, "wrong biPlanes %d\n", bmih->biPlanes);
745 ok(bmih->biBitCount == bpp, "wrong biBitCount %d\n", bmih->biBitCount);
747 image_size = DIB_GetWidthBytes(bmih->biWidth, bmih->biBitCount) * bmih->biHeight;
748 ok(bmih->biSizeImage == image_size, "wrong biSizeImage %u\n", bmih->biSizeImage);
749 #if 0
751 char fname[256];
752 FILE *f;
753 sprintf(fname, "bmp_%s.bmp", comment);
754 f = fopen(fname, "wb");
755 fwrite(bm_data, 1, bm_data_size, f);
756 fclose(f);
758 #endif
759 return hdr_size + image_size;
762 static void check_ilhead_data(const char *ilh_data, INT cx, INT cy, INT cur, INT max, INT grow, INT flags)
764 const ILHEAD *ilh = (const ILHEAD *)ilh_data;
766 ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
767 ok(ilh->usVersion == 0x101, "wrong usVersion %x (expected 0x101)\n", ilh->usVersion);
768 ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
769 ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
770 ok(ilh->cGrow == grow, "wrong cGrow %d (expected %d)\n", ilh->cGrow, grow);
771 ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
772 ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
773 ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
774 ok(ilh->flags == flags, "wrong flags %04x\n", ilh->flags);
775 ok(ilh->ovls[0] == -1, "wrong ovls[0] %04x\n", ilh->ovls[0]);
776 ok(ilh->ovls[1] == -1, "wrong ovls[1] %04x\n", ilh->ovls[1]);
777 ok(ilh->ovls[2] == -1, "wrong ovls[2] %04x\n", ilh->ovls[2]);
778 ok(ilh->ovls[3] == -1, "wrong ovls[3] %04x\n", ilh->ovls[3]);
781 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
783 HDC hdc;
784 char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
785 BITMAPINFO *bmi = (BITMAPINFO *)bmibuf;
786 HBITMAP hbmp, hbmp_old;
787 HBRUSH hbrush;
788 RECT rc = { 0, 0, cx, cy };
790 hdc = CreateCompatibleDC(0);
792 memset(bmi, 0, sizeof(*bmi));
793 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
794 bmi->bmiHeader.biHeight = cx;
795 bmi->bmiHeader.biWidth = cy;
796 bmi->bmiHeader.biBitCount = 24;
797 bmi->bmiHeader.biPlanes = 1;
798 bmi->bmiHeader.biCompression = BI_RGB;
799 hbmp = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
801 hbmp_old = SelectObject(hdc, hbmp);
803 hbrush = CreateSolidBrush(color);
804 FillRect(hdc, &rc, hbrush);
805 DeleteObject(hbrush);
807 DrawText(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
809 SelectObject(hdc, hbmp_old);
810 DeleteDC(hdc);
812 return hbmp;
815 #define iml_clear_stream_data() \
816 HeapFree(GetProcessHeap(), 0, Test_Stream.iml_data); \
817 Test_Stream.iml_data = NULL; \
818 Test_Stream.iml_data_size = 0;
820 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, INT grow,
821 INT width, INT height, INT flags, const char *comment)
823 INT ret, cxx, cyy, size;
825 trace("%s\n", comment);
827 ret = ImageList_GetImageCount(himl);
828 ok(ret == cur, "expected image count %d got %d\n", cur, ret);
830 ret = ImageList_GetIconSize(himl, &cxx, &cyy);
831 ok(ret, "ImageList_GetIconSize failed\n");
832 ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx);
833 ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy);
835 iml_clear_stream_data();
836 ret = ImageList_Write(himl, &Test_Stream.IStream_iface);
837 ok(ret, "ImageList_Write failed\n");
839 ok(Test_Stream.iml_data != 0, "ImageList_Write didn't write any data\n");
840 ok(Test_Stream.iml_data_size > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n");
842 check_ilhead_data(Test_Stream.iml_data, cx, cy, cur, max, grow, flags);
843 size = check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD),
844 Test_Stream.iml_data_size - sizeof(ILHEAD),
845 width, height, flags & 0xfe, comment);
846 if (size < Test_Stream.iml_data_size - sizeof(ILHEAD)) /* mask is present */
848 ok( flags & ILC_MASK, "extra data %u/%u but mask not expected\n",
849 Test_Stream.iml_data_size, size );
850 check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD) + size,
851 Test_Stream.iml_data_size - sizeof(ILHEAD) - size,
852 width, height, 1, comment);
856 static void image_list_init(HIMAGELIST himl)
858 HBITMAP hbm;
859 char comment[16];
860 INT n = 1;
861 DWORD i;
862 static const struct test_data
864 BYTE grey;
865 INT cx, cy, cur, max, grow, width, height, bpp;
866 const char *comment;
867 } td[] =
869 { 255, BMP_CX, BMP_CX, 1, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 1" },
870 { 170, BMP_CX, BMP_CX, 2, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 2" },
871 { 85, BMP_CX, BMP_CX, 3, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 3" },
872 { 0, BMP_CX, BMP_CX, 4, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 4" },
873 { 0, BMP_CX, BMP_CX, 5, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 5" },
874 { 85, BMP_CX, BMP_CX, 6, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 6" },
875 { 170, BMP_CX, BMP_CX, 7, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 7" },
876 { 255, BMP_CX, BMP_CX, 8, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 8" },
877 { 255, BMP_CX, BMP_CX, 9, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 9" },
878 { 170, BMP_CX, BMP_CX, 10, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 10" },
879 { 85, BMP_CX, BMP_CX, 11, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 11" },
880 { 0, BMP_CX, BMP_CX, 12, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 12" },
881 { 0, BMP_CX, BMP_CX, 13, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 13" },
882 { 85, BMP_CX, BMP_CX, 14, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 14" },
883 { 170, BMP_CX, BMP_CX, 15, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 15" },
884 { 255, BMP_CX, BMP_CX, 16, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 16" },
885 { 255, BMP_CX, BMP_CX, 17, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 17" },
886 { 170, BMP_CX, BMP_CX, 18, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 18" },
887 { 85, BMP_CX, BMP_CX, 19, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 19" },
888 { 0, BMP_CX, BMP_CX, 20, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 20" },
889 { 0, BMP_CX, BMP_CX, 21, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 21" },
890 { 85, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 22" },
891 { 170, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 23" },
892 { 255, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 24" }
895 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "total 0");
897 #define add_bitmap(grey) \
898 sprintf(comment, "%d", n++); \
899 hbm = create_bitmap(BMP_CX, BMP_CX, RGB((grey),(grey),(grey)), comment); \
900 ImageList_Add(himl, hbm, NULL); \
901 DeleteObject(hbm);
903 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
905 add_bitmap(td[i].grey);
906 check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, td[i].grow,
907 td[i].width, td[i].height, td[i].bpp, td[i].comment);
909 #undef add_bitmap
912 static void test_imagelist_storage(void)
914 HIMAGELIST himl;
915 HBITMAP hbm;
916 HICON icon;
917 INT ret;
919 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
920 ok(himl != 0, "ImageList_Create failed\n");
922 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "empty");
924 image_list_init(himl);
925 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "orig");
927 ret = ImageList_Remove(himl, 4);
928 ok(ret, "ImageList_Remove failed\n");
929 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "1");
931 ret = ImageList_Remove(himl, 5);
932 ok(ret, "ImageList_Remove failed\n");
933 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "2");
935 ret = ImageList_Remove(himl, 6);
936 ok(ret, "ImageList_Remove failed\n");
937 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "3");
939 ret = ImageList_Remove(himl, 7);
940 ok(ret, "ImageList_Remove failed\n");
941 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "4");
943 ret = ImageList_Remove(himl, -2);
944 ok(!ret, "ImageList_Remove(-2) should fail\n");
945 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "5");
947 ret = ImageList_Remove(himl, 20);
948 ok(!ret, "ImageList_Remove(20) should fail\n");
949 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "6");
951 ret = ImageList_Remove(himl, -1);
952 ok(ret, "ImageList_Remove(-1) failed\n");
953 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "7");
955 ret = ImageList_Destroy(himl);
956 ok(ret, "ImageList_Destroy failed\n");
958 iml_clear_stream_data();
960 /* test ImageList_Create storage allocation */
962 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 0, 32);
963 ok(himl != 0, "ImageList_Create failed\n");
964 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 32, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "init 0 grow 32");
965 hbm = create_bitmap(BMP_CX * 9, BMP_CX, 0, "9");
966 ret = ImageList_Add(himl, hbm, NULL);
967 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
968 check_iml_data(himl, BMP_CX, BMP_CX, 1, 34, 32, BMP_CX * 4, BMP_CX * 9, ILC_COLOR24, "add 1 x 9");
969 DeleteObject(hbm);
970 ret = ImageList_Destroy(himl);
971 ok(ret, "ImageList_Destroy failed\n");
972 iml_clear_stream_data();
974 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 4);
975 ok(himl != 0, "ImageList_Create failed\n");
976 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 4 grow 4");
977 hbm = create_bitmap(BMP_CX, BMP_CX * 9, 0, "9");
978 ret = ImageList_Add(himl, hbm, NULL);
979 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
980 check_iml_data(himl, BMP_CX, BMP_CX, 9, 15, 4, BMP_CX * 4, BMP_CX * 4, ILC_COLOR24, "add 9 x 1");
981 ret = ImageList_Add(himl, hbm, NULL);
982 ok(ret == 9, "ImageList_Add returned %d, expected 9\n", ret);
983 check_iml_data(himl, BMP_CX, BMP_CX, 18, 25, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "add 9 x 1");
984 DeleteObject(hbm);
985 ret = ImageList_Destroy(himl);
986 ok(ret, "ImageList_Destroy failed\n");
987 iml_clear_stream_data();
989 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 207, 209);
990 ok(himl != 0, "ImageList_Create failed\n");
991 check_iml_data(himl, BMP_CX, BMP_CX, 0, 208, 212, BMP_CX * 4, BMP_CX * 52, ILC_COLOR24, "init 207 grow 209");
992 ret = ImageList_Destroy(himl);
993 ok(ret, "ImageList_Destroy failed\n");
994 iml_clear_stream_data();
996 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 209, 207);
997 ok(himl != 0, "ImageList_Create failed\n");
998 check_iml_data(himl, BMP_CX, BMP_CX, 0, 210, 208, BMP_CX * 4, BMP_CX * 53, ILC_COLOR24, "init 209 grow 207");
999 ret = ImageList_Destroy(himl);
1000 ok(ret, "ImageList_Destroy failed\n");
1001 iml_clear_stream_data();
1003 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 14, 4);
1004 ok(himl != 0, "ImageList_Create failed\n");
1005 check_iml_data(himl, BMP_CX, BMP_CX, 0, 15, 4, BMP_CX * 4, BMP_CX * 4, ILC_COLOR24, "init 14 grow 4");
1006 ret = ImageList_Destroy(himl);
1007 ok(ret, "ImageList_Destroy failed\n");
1008 iml_clear_stream_data();
1010 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 5, 9);
1011 ok(himl != 0, "ImageList_Create failed\n");
1012 check_iml_data(himl, BMP_CX, BMP_CX, 0, 6, 12, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 5 grow 9");
1013 ret = ImageList_Destroy(himl);
1014 ok(ret, "ImageList_Destroy failed\n");
1015 iml_clear_stream_data();
1017 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 9, 5);
1018 ok(himl != 0, "ImageList_Create failed\n");
1019 check_iml_data(himl, BMP_CX, BMP_CX, 0, 10, 8, BMP_CX * 4, BMP_CX * 3, ILC_COLOR24, "init 9 grow 5");
1020 ret = ImageList_Destroy(himl);
1021 ok(ret, "ImageList_Destroy failed\n");
1022 iml_clear_stream_data();
1024 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 2, 4);
1025 ok(himl != 0, "ImageList_Create failed\n");
1026 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "init 2 grow 4");
1027 ret = ImageList_Destroy(himl);
1028 ok(ret, "ImageList_Destroy failed\n");
1029 iml_clear_stream_data();
1031 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 2);
1032 ok(himl != 0, "ImageList_Create failed\n");
1033 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 4 grow 2");
1034 ret = ImageList_Destroy(himl);
1035 ok(ret, "ImageList_Destroy failed\n");
1036 iml_clear_stream_data();
1038 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR8, 4, 2);
1039 ok(himl != 0, "ImageList_Create failed\n");
1040 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR8, "bpp 8");
1041 ret = ImageList_Destroy(himl);
1042 ok(ret, "ImageList_Destroy failed\n");
1043 iml_clear_stream_data();
1045 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4, 4, 2);
1046 ok(himl != 0, "ImageList_Create failed\n");
1047 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp 4");
1048 ret = ImageList_Destroy(himl);
1049 ok(ret, "ImageList_Destroy failed\n");
1050 iml_clear_stream_data();
1052 himl = ImageList_Create(BMP_CX, BMP_CX, 0, 4, 2);
1053 ok(himl != 0, "ImageList_Create failed\n");
1054 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp default");
1055 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1056 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1057 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1058 DestroyIcon( icon );
1059 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp default");
1060 ret = ImageList_Destroy(himl);
1061 ok(ret, "ImageList_Destroy failed\n");
1062 iml_clear_stream_data();
1064 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24|ILC_MASK, 4, 2);
1065 ok(himl != 0, "ImageList_Create failed\n");
1066 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24|ILC_MASK,
1067 "bpp 24 + mask");
1068 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1069 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1070 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1071 DestroyIcon( icon );
1072 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24|ILC_MASK,
1073 "bpp 24 + mask");
1074 ret = ImageList_Destroy(himl);
1075 ok(ret, "ImageList_Destroy failed\n");
1076 iml_clear_stream_data();
1078 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 4, 2);
1079 ok(himl != 0, "ImageList_Create failed\n");
1080 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4|ILC_MASK,
1081 "bpp 4 + mask");
1082 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1083 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1084 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1085 DestroyIcon( icon );
1086 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4|ILC_MASK,
1087 "bpp 4 + mask");
1088 ret = ImageList_Destroy(himl);
1089 ok(ret, "ImageList_Destroy failed\n");
1090 iml_clear_stream_data();
1093 static void test_shell_imagelist(void)
1095 BOOL (WINAPI *pSHGetImageList)(INT, REFIID, void**);
1096 IImageList *iml = NULL;
1097 HMODULE hShell32;
1098 HRESULT hr;
1099 int out = 0;
1100 RECT rect;
1101 int cx, cy;
1103 /* Try to load function from shell32 */
1104 hShell32 = LoadLibrary("shell32.dll");
1105 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1107 if (!pSHGetImageList)
1109 win_skip("SHGetImageList not available, skipping test\n");
1110 return;
1113 /* Get system image list */
1114 hr = (pSHGetImageList)(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1116 ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1118 if (hr != S_OK)
1119 return;
1121 IImageList_GetImageCount(iml, &out);
1122 ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1124 /* Fetch the small icon size */
1125 cx = GetSystemMetrics(SM_CXSMICON);
1126 cy = GetSystemMetrics(SM_CYSMICON);
1128 /* Check icon size matches */
1129 IImageList_GetImageRect(iml, 0, &rect);
1130 ok(((rect.right == cx) && (rect.bottom == cy)),
1131 "IImageList_GetImageRect returned r:%d,b:%d\n",
1132 rect.right, rect.bottom);
1134 IImageList_Release(iml);
1135 FreeLibrary(hShell32);
1138 static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
1140 HBITMAP hBitmap;
1141 UINT32 *buffer = NULL;
1142 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
1143 0, 0, 0, 0, 0}};
1145 hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1146 ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1148 if(!hBitmap || !buffer)
1150 DeleteObject(hBitmap);
1151 return NULL;
1154 buffer[0] = pixel1;
1155 buffer[1] = pixel2;
1157 return hBitmap;
1160 static BOOL colour_match(UINT32 x, UINT32 y)
1162 const INT32 tolerance = 8;
1164 const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1165 const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1166 const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1168 return (dr <= tolerance && dg <= tolerance && db <= tolerance);
1171 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1172 UINT32 expected, int line)
1174 bits[0] = 0x00FFFFFF;
1175 pImageList_DrawIndirect(ildp);
1176 ok(colour_match(bits[0], expected),
1177 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1178 bits[0] & 0x00FFFFFF, expected, line);
1182 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1183 UINT fStyle, UINT32 expected, int line)
1185 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1186 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1187 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1190 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1191 DWORD dwRop, UINT32 expected, int line)
1193 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1194 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1195 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1198 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1199 UINT fState, DWORD Frame, UINT32 expected, int line)
1201 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1202 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1203 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1206 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1207 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1208 UINT32 broken_expected, int line)
1210 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1211 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1212 bits[0] = 0x00FFFFFF;
1213 pImageList_DrawIndirect(&ildp);
1214 ok(colour_match(bits[0], expected) ||
1215 broken(colour_match(bits[0], broken_expected)),
1216 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1217 bits[0] & 0x00FFFFFF, expected, line);
1220 static void test_ImageList_DrawIndirect(void)
1222 HIMAGELIST himl = NULL;
1223 int ret;
1224 HDC hdcDst = NULL;
1225 HBITMAP hbmOld = NULL, hbmDst = NULL;
1226 HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1227 HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
1228 int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1229 UINT32 *bits = 0;
1230 UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1231 int bpp, broken_value;
1233 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1234 0, 0, 0, 0, 0}};
1236 hdcDst = CreateCompatibleDC(0);
1237 ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1238 if (!hdcDst)
1239 return;
1240 bpp = GetDeviceCaps(hdcDst, BITSPIXEL);
1242 hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1243 ok(hbmMask != 0, "CreateBitmap failed\n");
1244 if(!hbmMask) goto cleanup;
1246 hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1247 ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1248 if(!hbmInverseMask) goto cleanup;
1250 himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1251 ok(himl != 0, "ImageList_Create failed\n");
1252 if(!himl) goto cleanup;
1254 /* Add a no-alpha image */
1255 hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
1256 if(!hbmImage) goto cleanup;
1258 iImage = pImageList_Add(himl, hbmImage, hbmMask);
1259 ok(iImage != -1, "ImageList_Add failed\n");
1260 if(iImage == -1) goto cleanup;
1262 /* Add an alpha image */
1263 hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
1264 if(!hbmAlphaImage) goto cleanup;
1266 iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1267 ok(iAlphaImage != -1, "ImageList_Add failed\n");
1268 if(iAlphaImage == -1) goto cleanup;
1270 /* Add a transparent alpha image */
1271 hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
1272 if(!hbmTransparentImage) goto cleanup;
1274 iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1275 ok(iTransparentImage != -1, "ImageList_Add failed\n");
1276 if(iTransparentImage == -1) goto cleanup;
1278 /* 32-bit Tests */
1279 bitmapInfo.bmiHeader.biBitCount = 32;
1280 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1281 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1282 if (!hbmDst || !bits)
1283 goto cleanup;
1284 hbmOld = SelectObject(hdcDst, hbmDst);
1286 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1287 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1288 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
1289 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1290 else broken_value = 0x00B4BDC4;
1291 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1292 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1293 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1294 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1296 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
1297 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
1299 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1300 else broken_value = 0x009DA8B1;
1301 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1302 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1303 else broken_value = 0x008C99A3;
1304 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1305 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
1306 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
1307 todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
1309 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
1311 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1312 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
1314 /* ILD_ROP is ignored when the image has an alpha channel */
1315 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
1316 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
1318 todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
1319 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
1321 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
1322 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
1324 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
1325 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
1326 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
1328 cleanup:
1330 if(hbmOld)
1331 SelectObject(hdcDst, hbmOld);
1332 if(hbmDst)
1333 DeleteObject(hbmDst);
1335 if(hdcDst)
1336 DeleteDC(hdcDst);
1338 if(hbmMask)
1339 DeleteObject(hbmMask);
1340 if(hbmInverseMask)
1341 DeleteObject(hbmInverseMask);
1343 if(hbmImage)
1344 DeleteObject(hbmImage);
1345 if(hbmAlphaImage)
1346 DeleteObject(hbmAlphaImage);
1347 if(hbmTransparentImage)
1348 DeleteObject(hbmTransparentImage);
1350 if(himl)
1352 ret = ImageList_Destroy(himl);
1353 ok(ret, "ImageList_Destroy failed\n");
1357 static void test_iimagelist(void)
1359 IImageList *imgl, *imgl2;
1360 HIMAGELIST himl;
1361 HRESULT hr;
1362 ULONG ret;
1364 if (!pHIMAGELIST_QueryInterface)
1366 win_skip("XP imagelist functions not available\n");
1367 return;
1370 /* test reference counting on destruction */
1371 imgl = (IImageList*)createImageList(32, 32);
1372 ret = IUnknown_AddRef(imgl);
1373 ok(ret == 2, "Expected 2, got %d\n", ret);
1374 ret = ImageList_Destroy((HIMAGELIST)imgl);
1375 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1376 ret = ImageList_Destroy((HIMAGELIST)imgl);
1377 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1378 ret = ImageList_Destroy((HIMAGELIST)imgl);
1379 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1381 imgl = (IImageList*)createImageList(32, 32);
1382 ret = IUnknown_AddRef(imgl);
1383 ok(ret == 2, "Expected 2, got %d\n", ret);
1384 ret = ImageList_Destroy((HIMAGELIST)imgl);
1385 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1386 ret = IImageList_Release(imgl);
1387 ok(ret == 0, "Expected 0, got %d\n", ret);
1388 ret = ImageList_Destroy((HIMAGELIST)imgl);
1389 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1391 /* ref counting, HIMAGELIST_QueryInterface adds a reference */
1392 imgl = (IImageList*)createImageList(32, 32);
1393 hr = pHIMAGELIST_QueryInterface((HIMAGELIST)imgl, &IID_IImageList, (void**)&imgl2);
1394 ok(hr == S_OK, "got 0x%08x\n", hr);
1395 ok(imgl2 == imgl, "got different pointer\n");
1396 ret = IImageList_Release(imgl);
1397 ok(ret == 1, "got %u\n", ret);
1398 IImageList_Release(imgl);
1400 if (!pImageList_CoCreateInstance)
1402 win_skip("Vista imagelist functions not available\n");
1403 return;
1406 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1407 ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
1409 if (hr == S_OK)
1410 IImageList_Release(imgl);
1412 himl = createImageList(32, 32);
1414 if (!himl)
1415 return;
1417 hr = (pHIMAGELIST_QueryInterface)(himl, &IID_IImageList, (void **) &imgl);
1418 ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
1420 if (hr == S_OK)
1421 IImageList_Release(imgl);
1423 ImageList_Destroy(himl);
1426 static void test_hotspot_v6(void)
1428 struct hotspot {
1429 int dx;
1430 int dy;
1433 #define SIZEX1 47
1434 #define SIZEY1 31
1435 #define SIZEX2 11
1436 #define SIZEY2 17
1437 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
1438 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
1439 { 10, 7 },
1440 { SIZEX1, SIZEY1 },
1441 { -9, -8 },
1442 { -7, 35 }
1444 int i, j;
1445 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
1446 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
1447 IImageList *imgl1, *imgl2;
1448 HRESULT hr;
1450 /* cast to IImageList */
1451 imgl1 = (IImageList *) himl1;
1452 imgl2 = (IImageList *) himl2;
1454 for (i = 0; i < HOTSPOTS_MAX; i++) {
1455 for (j = 0; j < HOTSPOTS_MAX; j++) {
1456 int dx1 = hotspots[i].dx;
1457 int dy1 = hotspots[i].dy;
1458 int dx2 = hotspots[j].dx;
1459 int dy2 = hotspots[j].dy;
1460 int correctx, correcty, newx, newy;
1461 char loc[256];
1462 IImageList *imglNew;
1463 POINT ppt;
1465 hr = IImageList_BeginDrag(imgl1, 0, dx1, dy1);
1466 ok(SUCCEEDED(hr), "BeginDrag failed for { %d, %d }\n", dx1, dy1);
1467 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
1469 /* check merging the dragged image with a second image */
1470 hr = IImageList_SetDragCursorImage(imgl2, (IUnknown *) imgl2, 0, dx2, dy2);
1471 ok(SUCCEEDED(hr), "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
1472 dx1, dy1, dx2, dy2);
1473 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
1475 /* check new hotspot, it should be the same like the old one */
1476 hr = IImageList_GetDragImage(imgl2, NULL, &ppt, &IID_IImageList, (PVOID *) &imglNew);
1477 ok(SUCCEEDED(hr), "GetDragImage failed\n");
1478 ok(ppt.x == dx1 && ppt.y == dy1,
1479 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
1480 dx1, dy1, ppt.x, ppt.y);
1481 /* check size of new dragged image */
1482 IImageList_GetIconSize(imglNew, &newx, &newy);
1483 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
1484 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
1485 ok(newx == correctx && newy == correcty,
1486 "Expected drag image size [%d,%d] got [%d,%d]\n",
1487 correctx, correcty, newx, newy);
1488 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
1489 IImageList_EndDrag(imgl2);
1492 #undef SIZEX1
1493 #undef SIZEY1
1494 #undef SIZEX2
1495 #undef SIZEY2
1496 #undef HOTSPOTS_MAX
1497 IImageList_Release(imgl2);
1498 IImageList_Release(imgl1);
1501 static void test_IImageList_Add_Remove(void)
1503 IImageList *imgl;
1504 HIMAGELIST himl;
1505 HRESULT hr;
1507 HICON hicon1;
1508 HICON hicon2;
1509 HICON hicon3;
1511 int ret;
1513 /* create an imagelist to play with */
1514 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1515 ok(himl != 0,"failed to create imagelist\n");
1517 imgl = (IImageList *) himl;
1519 /* load the icons to add to the image list */
1520 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1521 ok(hicon1 != 0, "no hicon1\n");
1522 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1523 ok(hicon2 != 0, "no hicon2\n");
1524 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1525 ok(hicon3 != 0, "no hicon3\n");
1527 /* remove when nothing exists */
1528 hr = IImageList_Remove(imgl, 0);
1529 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1531 /* removing everything from an empty imagelist should succeed */
1532 hr = IImageList_Remove(imgl, -1);
1533 ok(hr == S_OK, "removed nonexistent icon\n");
1535 /* add three */
1536 ret = -1;
1537 ok( IImageList_ReplaceIcon(imgl, -1, hicon1, &ret) == S_OK && (ret == 0),"failed to add icon1\n");
1538 ret = -1;
1539 ok( IImageList_ReplaceIcon(imgl, -1, hicon2, &ret) == S_OK && (ret == 1),"failed to add icon2\n");
1540 ret = -1;
1541 ok( IImageList_ReplaceIcon(imgl, -1, hicon3, &ret) == S_OK && (ret == 2),"failed to add icon3\n");
1543 /* remove an index out of range */
1544 ok( IImageList_Remove(imgl, 4711) == E_INVALIDARG, "got 0x%08x\n", hr);
1546 /* remove three */
1547 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1548 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1549 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1551 /* remove one extra */
1552 ok( IImageList_Remove(imgl, 0) == E_INVALIDARG, "got 0x%08x\n", hr);
1554 IImageList_Release(imgl);
1555 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1556 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1557 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1560 static void test_IImageList_Get_SetImageCount(void)
1562 IImageList *imgl;
1563 HIMAGELIST himl;
1564 HRESULT hr;
1565 INT ret;
1567 /* create an imagelist to play with */
1568 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1569 ok(himl != 0,"failed to create imagelist\n");
1571 imgl = (IImageList *) himl;
1573 /* check SetImageCount/GetImageCount */
1574 hr = IImageList_SetImageCount(imgl, 3);
1575 ok(hr == S_OK, "got 0x%08x\n", hr);
1576 ret = 0;
1577 hr = IImageList_GetImageCount(imgl, &ret);
1578 ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
1579 hr = IImageList_SetImageCount(imgl, 1);
1580 ok(hr == S_OK, "got 0x%08x\n", hr);
1581 ret = 0;
1582 hr = IImageList_GetImageCount(imgl, &ret);
1583 ok(hr == S_OK && ret == 1, "invalid image count after decrease to 1\n");
1584 hr = IImageList_SetImageCount(imgl, 0);
1585 ok(hr == S_OK, "got 0x%08x\n", hr);
1586 ret = -1;
1587 hr = IImageList_GetImageCount(imgl, &ret);
1588 ok(hr == S_OK && ret == 0, "invalid image count after decrease to 0\n");
1590 IImageList_Release(imgl);
1593 static void test_IImageList_Draw(void)
1595 IImageList *imgl;
1596 HIMAGELIST himl;
1598 HBITMAP hbm1;
1599 HBITMAP hbm2;
1600 HBITMAP hbm3;
1602 IMAGELISTDRAWPARAMS imldp;
1603 HWND hwndfortest;
1604 HRESULT hr;
1605 HDC hdc;
1606 int ret;
1608 hwndfortest = create_a_window();
1609 hdc = GetDC(hwndfortest);
1610 ok(hdc!=NULL, "couldn't get DC\n");
1612 /* create an imagelist to play with */
1613 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1614 ok(himl!=0,"failed to create imagelist\n");
1616 imgl = (IImageList *) himl;
1618 /* load the icons to add to the image list */
1619 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1620 ok(hbm1 != 0, "no bitmap 1\n");
1621 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1622 ok(hbm2 != 0, "no bitmap 2\n");
1623 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1624 ok(hbm3 != 0, "no bitmap 3\n");
1626 /* add three */
1627 ret = -1;
1628 ok( IImageList_Add(imgl, hbm1, 0, &ret) == S_OK && (ret == 0), "failed to add bitmap 1\n");
1629 ret = -1;
1630 ok( IImageList_Add(imgl, hbm2, 0, &ret) == S_OK && (ret == 1), "failed to add bitmap 2\n");
1632 ok( IImageList_SetImageCount(imgl, 3) == S_OK, "Setimage count failed\n");
1633 ok( IImageList_Replace(imgl, 2, hbm3, 0) == S_OK, "failed to replace bitmap 3\n");
1635 if (0)
1637 /* crashes on native */
1638 IImageList_Draw(imgl, NULL);
1641 memset(&imldp, 0, sizeof (imldp));
1642 hr = IImageList_Draw(imgl, &imldp);
1643 ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
1645 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
1646 imldp.hdcDst = hdc;
1647 imldp.himl = himl;
1649 REDRAW(hwndfortest);
1650 WAIT;
1652 imldp.fStyle = SRCCOPY;
1653 imldp.rgbBk = CLR_DEFAULT;
1654 imldp.rgbFg = CLR_DEFAULT;
1655 imldp.y = 100;
1656 imldp.x = 100;
1657 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1658 imldp.i ++;
1659 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1660 imldp.i ++;
1661 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1662 imldp.i ++;
1663 ok( IImageList_Draw(imgl, &imldp) == E_INVALIDARG, "should fail\n");
1665 /* remove three */
1666 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 1st bitmap\n");
1667 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 2nd bitmap\n");
1668 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 3rd bitmap\n");
1670 /* destroy it */
1671 IImageList_Release(imgl);
1673 /* bitmaps should not be deleted by the imagelist */
1674 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1675 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1676 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1678 ReleaseDC(hwndfortest, hdc);
1679 DestroyWindow(hwndfortest);
1682 static void test_IImageList_Merge(void)
1684 HIMAGELIST himl1, himl2;
1685 IImageList *imgl1, *imgl2, *merge;
1686 HICON hicon1;
1687 HWND hwnd = create_a_window();
1688 HRESULT hr;
1689 int ret;
1691 himl1 = ImageList_Create(32,32,0,0,3);
1692 ok(himl1 != NULL,"failed to create himl1\n");
1694 himl2 = ImageList_Create(32,32,0,0,3);
1695 ok(himl2 != NULL,"failed to create himl2\n");
1697 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1698 ok(hicon1 != NULL, "failed to create hicon1\n");
1700 if (!himl1 || !himl2 || !hicon1)
1701 return;
1703 /* cast to IImageList */
1704 imgl1 = (IImageList *) himl1;
1705 imgl2 = (IImageList *) himl2;
1707 ret = -1;
1708 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl2 failed\n");
1710 if (0)
1712 /* null cases that crash on native */
1713 IImageList_Merge(imgl1, -1, NULL, 0, 0, 0, &IID_IImageList, (void**)&merge);
1714 IImageList_Merge(imgl1, -1, (IUnknown*) imgl2, 0, 0, 0, &IID_IImageList, NULL);
1717 /* If himl1 has no images, merge still succeeds */
1718 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1719 ok(hr == S_OK, "merge himl1,-1 failed\n");
1720 if (hr == S_OK) IImageList_Release(merge);
1722 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1723 ok(hr == S_OK, "merge himl1,0 failed\n");
1724 if (hr == S_OK) IImageList_Release(merge);
1726 /* Same happens if himl2 is empty */
1727 IImageList_Release(imgl2);
1728 himl2 = ImageList_Create(32,32,0,0,3);
1729 ok(himl2 != NULL,"failed to recreate himl2\n");
1731 imgl2 = (IImageList *) himl2;
1733 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
1734 ok(hr == S_OK, "merge himl2,-1 failed\n");
1735 if (hr == S_OK) IImageList_Release(merge);
1737 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1738 ok(hr == S_OK, "merge himl2,0 failed\n");
1739 if (hr == S_OK) IImageList_Release(merge);
1741 /* Now try merging an image with itself */
1742 ret = -1;
1743 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"re-add icon1 to himl2 failed\n");
1745 hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1746 ok(hr == S_OK, "merge himl2 with itself failed\n");
1747 if (hr == S_OK) IImageList_Release(merge);
1749 /* Try merging 2 different image lists */
1750 ret = -1;
1751 ok( IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl1 failed\n");
1753 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1754 ok(hr == S_OK, "merge himl1 with himl2 failed\n");
1755 if (hr == S_OK) IImageList_Release(merge);
1757 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
1758 ok(hr == S_OK, "merge himl1 with himl2 8,16 failed\n");
1759 if (hr == S_OK) IImageList_Release(merge);
1761 IImageList_Release(imgl1);
1762 IImageList_Release(imgl2);
1764 DestroyIcon(hicon1);
1765 DestroyWindow(hwnd);
1768 static void test_iconsize(void)
1770 HIMAGELIST himl;
1771 INT cx, cy;
1772 BOOL ret;
1774 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1775 /* null pointers, not zero imagelist dimensions */
1776 ret = ImageList_GetIconSize(himl, NULL, NULL);
1777 ok(!ret, "got %d\n", ret);
1779 /* doesn't touch return pointers */
1780 cx = 0x1abe11ed;
1781 ret = ImageList_GetIconSize(himl, &cx, NULL);
1782 ok(!ret, "got %d\n", ret);
1783 ok(cx == 0x1abe11ed, "got %d\n", cx);
1785 cy = 0x1abe11ed;
1786 ret = ImageList_GetIconSize(himl, NULL, &cy);
1787 ok(!ret, "got %d\n", ret);
1788 ok(cy == 0x1abe11ed, "got %d\n", cy);
1790 ImageList_Destroy(himl);
1792 ret = ImageList_GetIconSize((HIMAGELIST)0xdeadbeef, &cx, &cy);
1793 ok(!ret, "got %d\n", ret);
1796 static void test_create_destroy(void)
1798 HIMAGELIST himl;
1799 BOOL rc;
1801 /* list with zero or negative image dimensions */
1802 himl = ImageList_Create(0, 0, ILC_COLOR16, 0, 3);
1803 ok(himl == NULL, "got %p\n", himl);
1805 himl = ImageList_Create(0, 16, ILC_COLOR16, 0, 3);
1806 ok(himl == NULL, "got %p\n", himl);
1808 himl = ImageList_Create(16, 0, ILC_COLOR16, 0, 3);
1809 ok(himl == NULL, "got %p\n", himl);
1811 himl = ImageList_Create(16, -1, ILC_COLOR16, 0, 3);
1812 ok(himl == NULL, "got %p\n", himl);
1814 himl = ImageList_Create(-1, 16, ILC_COLOR16, 0, 3);
1815 ok(himl == NULL, "got %p\n", himl);
1817 rc = ImageList_Destroy((HIMAGELIST)0xdeadbeef);
1818 ok(rc == FALSE, "ImageList_Destroy(0xdeadbeef) should fail and not crash\n");
1821 static void test_IImageList_Clone(void)
1823 IImageList *imgl, *imgl2;
1824 HIMAGELIST himl;
1825 HRESULT hr;
1826 ULONG ref;
1828 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1829 imgl = (IImageList*)himl;
1831 if (0)
1833 /* crashes on native */
1834 IImageList_Clone(imgl, &IID_IImageList, NULL);
1837 hr = IImageList_Clone(imgl, &IID_IImageList, (void**)&imgl2);
1838 ok(hr == S_OK, "got 0x%08x\n", hr);
1839 ref = IImageList_Release(imgl2);
1840 ok(ref == 0, "got %u\n", ref);
1842 IImageList_Release(imgl);
1845 static void test_IImageList_GetBkColor(void)
1847 IImageList *imgl;
1848 HIMAGELIST himl;
1849 COLORREF color;
1850 HRESULT hr;
1852 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1853 imgl = (IImageList*)himl;
1855 if (0)
1857 /* crashes on native */
1858 IImageList_GetBkColor(imgl, NULL);
1861 hr = IImageList_GetBkColor(imgl, &color);
1862 ok(hr == S_OK, "got 0x%08x\n", hr);
1864 IImageList_Release(imgl);
1867 static void test_IImageList_SetBkColor(void)
1869 IImageList *imgl;
1870 HIMAGELIST himl;
1871 COLORREF color;
1872 HRESULT hr;
1874 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1875 imgl = (IImageList*)himl;
1877 if (0)
1879 /* crashes on native */
1880 IImageList_SetBkColor(imgl, RGB(0, 0, 0), NULL);
1883 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1884 ok(hr == S_OK, "got 0x%08x\n", hr);
1886 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1887 ok(hr == S_OK, "got 0x%08x\n", hr);
1889 color = 0xdeadbeef;
1890 hr = IImageList_GetBkColor(imgl, &color);
1891 ok(hr == S_OK, "got 0x%08x\n", hr);
1892 ok(color == CLR_NONE, "got %x\n", color);
1894 IImageList_Release(imgl);
1897 static void test_IImageList_GetImageCount(void)
1899 IImageList *imgl;
1900 HIMAGELIST himl;
1901 int count;
1902 HRESULT hr;
1904 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1905 imgl = (IImageList*)himl;
1907 if (0)
1909 /* crashes on native */
1910 IImageList_GetImageCount(imgl, NULL);
1913 count = -1;
1914 hr = IImageList_GetImageCount(imgl, &count);
1915 ok(hr == S_OK, "got 0x%08x\n", hr);
1916 ok(count == 0, "got %d\n", count);
1918 IImageList_Release(imgl);
1921 static void test_IImageList_GetIconSize(void)
1923 IImageList *imgl;
1924 HIMAGELIST himl;
1925 int cx, cy;
1926 HRESULT hr;
1928 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1929 imgl = (IImageList*)himl;
1931 hr = IImageList_GetIconSize(imgl, NULL, NULL);
1932 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1934 hr = IImageList_GetIconSize(imgl, &cx, NULL);
1935 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1937 hr = IImageList_GetIconSize(imgl, NULL, &cy);
1938 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1940 IImageList_Release(imgl);
1943 START_TEST(imagelist)
1945 ULONG_PTR ctx_cookie;
1946 HANDLE hCtx;
1948 HMODULE hComCtl32 = GetModuleHandle("comctl32.dll");
1949 pImageList_Create = NULL; /* These are not needed for non-v6.0 tests*/
1950 pImageList_Add = NULL;
1951 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1952 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1954 hinst = GetModuleHandleA(NULL);
1956 InitCommonControls();
1958 test_create_destroy();
1959 test_hotspot();
1960 test_add_remove();
1961 test_imagecount();
1962 test_DrawIndirect();
1963 test_merge();
1964 test_imagelist_storage();
1965 test_iconsize();
1967 FreeLibrary(hComCtl32);
1969 /* Now perform v6 tests */
1971 if (!load_v6_module(&ctx_cookie, &hCtx))
1972 return;
1974 /* Reload comctl32 */
1975 hComCtl32 = LoadLibraryA("comctl32.dll");
1976 pImageList_Create = (void*)GetProcAddress(hComCtl32, "ImageList_Create");
1977 pImageList_Add = (void*)GetProcAddress(hComCtl32, "ImageList_Add");
1978 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1979 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1980 pImageList_CoCreateInstance = (void*)GetProcAddress(hComCtl32, "ImageList_CoCreateInstance");
1981 pHIMAGELIST_QueryInterface = (void*)GetProcAddress(hComCtl32, "HIMAGELIST_QueryInterface");
1983 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1985 /* Do v6.0 tests */
1986 test_ImageList_DrawIndirect();
1987 test_shell_imagelist();
1988 test_iimagelist();
1990 test_hotspot_v6();
1991 test_IImageList_Add_Remove();
1992 test_IImageList_Get_SetImageCount();
1993 test_IImageList_Draw();
1994 test_IImageList_Merge();
1995 test_IImageList_Clone();
1996 test_IImageList_GetBkColor();
1997 test_IImageList_SetBkColor();
1998 test_IImageList_GetImageCount();
1999 test_IImageList_GetIconSize();
2001 CoUninitialize();
2003 unload_v6_module(ctx_cookie, hCtx);