comctl32: Fix TB_SETSTYLE behaviour and return value.
[wine/multimedia.git] / dlls / comctl32 / tests / imagelist.c
blob588a5b38735f364db858b2c1801a50448105dcc7
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 || broken(!(ilh->flags & 0xfe) && (flags & 0xfe) == ILC_COLOR4), /* <= w2k */
775 "wrong flags %04x\n", ilh->flags);
776 ok(ilh->ovls[0] == -1, "wrong ovls[0] %04x\n", ilh->ovls[0]);
777 ok(ilh->ovls[1] == -1, "wrong ovls[1] %04x\n", ilh->ovls[1]);
778 ok(ilh->ovls[2] == -1, "wrong ovls[2] %04x\n", ilh->ovls[2]);
779 ok(ilh->ovls[3] == -1, "wrong ovls[3] %04x\n", ilh->ovls[3]);
782 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
784 HDC hdc;
785 char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
786 BITMAPINFO *bmi = (BITMAPINFO *)bmibuf;
787 HBITMAP hbmp, hbmp_old;
788 HBRUSH hbrush;
789 RECT rc = { 0, 0, cx, cy };
791 hdc = CreateCompatibleDC(0);
793 memset(bmi, 0, sizeof(*bmi));
794 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
795 bmi->bmiHeader.biHeight = cx;
796 bmi->bmiHeader.biWidth = cy;
797 bmi->bmiHeader.biBitCount = 24;
798 bmi->bmiHeader.biPlanes = 1;
799 bmi->bmiHeader.biCompression = BI_RGB;
800 hbmp = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
802 hbmp_old = SelectObject(hdc, hbmp);
804 hbrush = CreateSolidBrush(color);
805 FillRect(hdc, &rc, hbrush);
806 DeleteObject(hbrush);
808 DrawText(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
810 SelectObject(hdc, hbmp_old);
811 DeleteDC(hdc);
813 return hbmp;
816 #define iml_clear_stream_data() \
817 HeapFree(GetProcessHeap(), 0, Test_Stream.iml_data); \
818 Test_Stream.iml_data = NULL; \
819 Test_Stream.iml_data_size = 0;
821 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, INT grow,
822 INT width, INT height, INT flags, const char *comment)
824 INT ret, cxx, cyy, size;
826 trace("%s\n", comment);
828 ret = ImageList_GetImageCount(himl);
829 ok(ret == cur, "expected image count %d got %d\n", cur, ret);
831 ret = ImageList_GetIconSize(himl, &cxx, &cyy);
832 ok(ret, "ImageList_GetIconSize failed\n");
833 ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx);
834 ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy);
836 iml_clear_stream_data();
837 ret = ImageList_Write(himl, &Test_Stream.IStream_iface);
838 ok(ret, "ImageList_Write failed\n");
840 ok(Test_Stream.iml_data != 0, "ImageList_Write didn't write any data\n");
841 ok(Test_Stream.iml_data_size > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n");
843 check_ilhead_data(Test_Stream.iml_data, cx, cy, cur, max, grow, flags);
844 size = check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD),
845 Test_Stream.iml_data_size - sizeof(ILHEAD),
846 width, height, flags & 0xfe, comment);
847 if (size < Test_Stream.iml_data_size - sizeof(ILHEAD)) /* mask is present */
849 ok( flags & ILC_MASK, "extra data %u/%u but mask not expected\n",
850 Test_Stream.iml_data_size, size );
851 check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD) + size,
852 Test_Stream.iml_data_size - sizeof(ILHEAD) - size,
853 width, height, 1, comment);
857 static void image_list_init(HIMAGELIST himl)
859 HBITMAP hbm;
860 char comment[16];
861 INT n = 1;
862 DWORD i;
863 static const struct test_data
865 BYTE grey;
866 INT cx, cy, cur, max, grow, width, height, bpp;
867 const char *comment;
868 } td[] =
870 { 255, BMP_CX, BMP_CX, 1, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 1" },
871 { 170, BMP_CX, BMP_CX, 2, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 2" },
872 { 85, BMP_CX, BMP_CX, 3, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 3" },
873 { 0, BMP_CX, BMP_CX, 4, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 4" },
874 { 0, BMP_CX, BMP_CX, 5, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 5" },
875 { 85, BMP_CX, BMP_CX, 6, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 6" },
876 { 170, BMP_CX, BMP_CX, 7, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 7" },
877 { 255, BMP_CX, BMP_CX, 8, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 8" },
878 { 255, BMP_CX, BMP_CX, 9, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 9" },
879 { 170, BMP_CX, BMP_CX, 10, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 10" },
880 { 85, BMP_CX, BMP_CX, 11, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 11" },
881 { 0, BMP_CX, BMP_CX, 12, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 12" },
882 { 0, BMP_CX, BMP_CX, 13, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 13" },
883 { 85, BMP_CX, BMP_CX, 14, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 14" },
884 { 170, BMP_CX, BMP_CX, 15, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 15" },
885 { 255, BMP_CX, BMP_CX, 16, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 16" },
886 { 255, BMP_CX, BMP_CX, 17, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 17" },
887 { 170, BMP_CX, BMP_CX, 18, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 18" },
888 { 85, BMP_CX, BMP_CX, 19, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 19" },
889 { 0, BMP_CX, BMP_CX, 20, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 20" },
890 { 0, BMP_CX, BMP_CX, 21, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 21" },
891 { 85, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 22" },
892 { 170, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 23" },
893 { 255, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 24" }
896 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "total 0");
898 #define add_bitmap(grey) \
899 sprintf(comment, "%d", n++); \
900 hbm = create_bitmap(BMP_CX, BMP_CX, RGB((grey),(grey),(grey)), comment); \
901 ImageList_Add(himl, hbm, NULL); \
902 DeleteObject(hbm);
904 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
906 add_bitmap(td[i].grey);
907 check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, td[i].grow,
908 td[i].width, td[i].height, td[i].bpp, td[i].comment);
910 #undef add_bitmap
913 static void test_imagelist_storage(void)
915 HIMAGELIST himl;
916 HBITMAP hbm;
917 HICON icon;
918 INT ret;
920 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
921 ok(himl != 0, "ImageList_Create failed\n");
923 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "empty");
925 image_list_init(himl);
926 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "orig");
928 ret = ImageList_Remove(himl, 4);
929 ok(ret, "ImageList_Remove failed\n");
930 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "1");
932 ret = ImageList_Remove(himl, 5);
933 ok(ret, "ImageList_Remove failed\n");
934 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "2");
936 ret = ImageList_Remove(himl, 6);
937 ok(ret, "ImageList_Remove failed\n");
938 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "3");
940 ret = ImageList_Remove(himl, 7);
941 ok(ret, "ImageList_Remove failed\n");
942 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "4");
944 ret = ImageList_Remove(himl, -2);
945 ok(!ret, "ImageList_Remove(-2) should fail\n");
946 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "5");
948 ret = ImageList_Remove(himl, 20);
949 ok(!ret, "ImageList_Remove(20) should fail\n");
950 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "6");
952 ret = ImageList_Remove(himl, -1);
953 ok(ret, "ImageList_Remove(-1) failed\n");
954 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "7");
956 ret = ImageList_Destroy(himl);
957 ok(ret, "ImageList_Destroy failed\n");
959 iml_clear_stream_data();
961 /* test ImageList_Create storage allocation */
963 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 0, 32);
964 ok(himl != 0, "ImageList_Create failed\n");
965 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 32, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "init 0 grow 32");
966 hbm = create_bitmap(BMP_CX * 9, BMP_CX, 0, "9");
967 ret = ImageList_Add(himl, hbm, NULL);
968 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
969 check_iml_data(himl, BMP_CX, BMP_CX, 1, 34, 32, BMP_CX * 4, BMP_CX * 9, ILC_COLOR24, "add 1 x 9");
970 DeleteObject(hbm);
971 ret = ImageList_Destroy(himl);
972 ok(ret, "ImageList_Destroy failed\n");
973 iml_clear_stream_data();
975 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 4);
976 ok(himl != 0, "ImageList_Create failed\n");
977 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 4 grow 4");
978 hbm = create_bitmap(BMP_CX, BMP_CX * 9, 0, "9");
979 ret = ImageList_Add(himl, hbm, NULL);
980 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
981 check_iml_data(himl, BMP_CX, BMP_CX, 9, 15, 4, BMP_CX * 4, BMP_CX * 4, ILC_COLOR24, "add 9 x 1");
982 ret = ImageList_Add(himl, hbm, NULL);
983 ok(ret == 9, "ImageList_Add returned %d, expected 9\n", ret);
984 check_iml_data(himl, BMP_CX, BMP_CX, 18, 25, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "add 9 x 1");
985 DeleteObject(hbm);
986 ret = ImageList_Destroy(himl);
987 ok(ret, "ImageList_Destroy failed\n");
988 iml_clear_stream_data();
990 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 207, 209);
991 ok(himl != 0, "ImageList_Create failed\n");
992 check_iml_data(himl, BMP_CX, BMP_CX, 0, 208, 212, BMP_CX * 4, BMP_CX * 52, ILC_COLOR24, "init 207 grow 209");
993 ret = ImageList_Destroy(himl);
994 ok(ret, "ImageList_Destroy failed\n");
995 iml_clear_stream_data();
997 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 209, 207);
998 ok(himl != 0, "ImageList_Create failed\n");
999 check_iml_data(himl, BMP_CX, BMP_CX, 0, 210, 208, BMP_CX * 4, BMP_CX * 53, ILC_COLOR24, "init 209 grow 207");
1000 ret = ImageList_Destroy(himl);
1001 ok(ret, "ImageList_Destroy failed\n");
1002 iml_clear_stream_data();
1004 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 14, 4);
1005 ok(himl != 0, "ImageList_Create failed\n");
1006 check_iml_data(himl, BMP_CX, BMP_CX, 0, 15, 4, BMP_CX * 4, BMP_CX * 4, ILC_COLOR24, "init 14 grow 4");
1007 ret = ImageList_Destroy(himl);
1008 ok(ret, "ImageList_Destroy failed\n");
1009 iml_clear_stream_data();
1011 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 5, 9);
1012 ok(himl != 0, "ImageList_Create failed\n");
1013 check_iml_data(himl, BMP_CX, BMP_CX, 0, 6, 12, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 5 grow 9");
1014 ret = ImageList_Destroy(himl);
1015 ok(ret, "ImageList_Destroy failed\n");
1016 iml_clear_stream_data();
1018 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 9, 5);
1019 ok(himl != 0, "ImageList_Create failed\n");
1020 check_iml_data(himl, BMP_CX, BMP_CX, 0, 10, 8, BMP_CX * 4, BMP_CX * 3, ILC_COLOR24, "init 9 grow 5");
1021 ret = ImageList_Destroy(himl);
1022 ok(ret, "ImageList_Destroy failed\n");
1023 iml_clear_stream_data();
1025 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 2, 4);
1026 ok(himl != 0, "ImageList_Create failed\n");
1027 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "init 2 grow 4");
1028 ret = ImageList_Destroy(himl);
1029 ok(ret, "ImageList_Destroy failed\n");
1030 iml_clear_stream_data();
1032 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 2);
1033 ok(himl != 0, "ImageList_Create failed\n");
1034 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 4 grow 2");
1035 ret = ImageList_Destroy(himl);
1036 ok(ret, "ImageList_Destroy failed\n");
1037 iml_clear_stream_data();
1039 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR8, 4, 2);
1040 ok(himl != 0, "ImageList_Create failed\n");
1041 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR8, "bpp 8");
1042 ret = ImageList_Destroy(himl);
1043 ok(ret, "ImageList_Destroy failed\n");
1044 iml_clear_stream_data();
1046 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4, 4, 2);
1047 ok(himl != 0, "ImageList_Create failed\n");
1048 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp 4");
1049 ret = ImageList_Destroy(himl);
1050 ok(ret, "ImageList_Destroy failed\n");
1051 iml_clear_stream_data();
1053 himl = ImageList_Create(BMP_CX, BMP_CX, 0, 4, 2);
1054 ok(himl != 0, "ImageList_Create failed\n");
1055 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp default");
1056 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1057 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1058 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1059 DestroyIcon( icon );
1060 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp default");
1061 ret = ImageList_Destroy(himl);
1062 ok(ret, "ImageList_Destroy failed\n");
1063 iml_clear_stream_data();
1065 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24|ILC_MASK, 4, 2);
1066 ok(himl != 0, "ImageList_Create failed\n");
1067 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24|ILC_MASK,
1068 "bpp 24 + mask");
1069 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1070 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1071 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1072 DestroyIcon( icon );
1073 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24|ILC_MASK,
1074 "bpp 24 + mask");
1075 ret = ImageList_Destroy(himl);
1076 ok(ret, "ImageList_Destroy failed\n");
1077 iml_clear_stream_data();
1079 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 4, 2);
1080 ok(himl != 0, "ImageList_Create failed\n");
1081 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4|ILC_MASK,
1082 "bpp 4 + mask");
1083 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1084 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1085 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1086 DestroyIcon( icon );
1087 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4|ILC_MASK,
1088 "bpp 4 + mask");
1089 ret = ImageList_Destroy(himl);
1090 ok(ret, "ImageList_Destroy failed\n");
1091 iml_clear_stream_data();
1094 static void test_shell_imagelist(void)
1096 BOOL (WINAPI *pSHGetImageList)(INT, REFIID, void**);
1097 IImageList *iml = NULL;
1098 HMODULE hShell32;
1099 HRESULT hr;
1100 int out = 0;
1101 RECT rect;
1102 int cx, cy;
1104 /* Try to load function from shell32 */
1105 hShell32 = LoadLibrary("shell32.dll");
1106 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1108 if (!pSHGetImageList)
1110 win_skip("SHGetImageList not available, skipping test\n");
1111 return;
1114 /* Get system image list */
1115 hr = (pSHGetImageList)(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1117 ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1119 if (hr != S_OK)
1120 return;
1122 IImageList_GetImageCount(iml, &out);
1123 ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1125 /* Fetch the small icon size */
1126 cx = GetSystemMetrics(SM_CXSMICON);
1127 cy = GetSystemMetrics(SM_CYSMICON);
1129 /* Check icon size matches */
1130 IImageList_GetImageRect(iml, 0, &rect);
1131 ok(((rect.right == cx) && (rect.bottom == cy)),
1132 "IImageList_GetImageRect returned r:%d,b:%d\n",
1133 rect.right, rect.bottom);
1135 IImageList_Release(iml);
1136 FreeLibrary(hShell32);
1139 static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
1141 HBITMAP hBitmap;
1142 UINT32 *buffer = NULL;
1143 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
1144 0, 0, 0, 0, 0}};
1146 hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1147 ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1149 if(!hBitmap || !buffer)
1151 DeleteObject(hBitmap);
1152 return NULL;
1155 buffer[0] = pixel1;
1156 buffer[1] = pixel2;
1158 return hBitmap;
1161 static BOOL colour_match(UINT32 x, UINT32 y)
1163 const INT32 tolerance = 8;
1165 const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1166 const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1167 const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1169 return (dr <= tolerance && dg <= tolerance && db <= tolerance);
1172 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1173 UINT32 expected, int line)
1175 bits[0] = 0x00FFFFFF;
1176 pImageList_DrawIndirect(ildp);
1177 ok(colour_match(bits[0], expected),
1178 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1179 bits[0] & 0x00FFFFFF, expected, line);
1183 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1184 UINT fStyle, UINT32 expected, int line)
1186 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1187 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1188 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1191 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1192 DWORD dwRop, UINT32 expected, int line)
1194 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1195 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1196 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1199 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1200 UINT fState, DWORD Frame, UINT32 expected, int line)
1202 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1203 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1204 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1207 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1208 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1209 UINT32 broken_expected, int line)
1211 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1212 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1213 bits[0] = 0x00FFFFFF;
1214 pImageList_DrawIndirect(&ildp);
1215 ok(colour_match(bits[0], expected) ||
1216 broken(colour_match(bits[0], broken_expected)),
1217 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1218 bits[0] & 0x00FFFFFF, expected, line);
1221 static void test_ImageList_DrawIndirect(void)
1223 HIMAGELIST himl = NULL;
1224 int ret;
1225 HDC hdcDst = NULL;
1226 HBITMAP hbmOld = NULL, hbmDst = NULL;
1227 HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1228 HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
1229 int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1230 UINT32 *bits = 0;
1231 UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1232 int bpp, broken_value;
1234 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1235 0, 0, 0, 0, 0}};
1237 hdcDst = CreateCompatibleDC(0);
1238 ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1239 if (!hdcDst)
1240 return;
1241 bpp = GetDeviceCaps(hdcDst, BITSPIXEL);
1243 hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1244 ok(hbmMask != 0, "CreateBitmap failed\n");
1245 if(!hbmMask) goto cleanup;
1247 hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1248 ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1249 if(!hbmInverseMask) goto cleanup;
1251 himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1252 ok(himl != 0, "ImageList_Create failed\n");
1253 if(!himl) goto cleanup;
1255 /* Add a no-alpha image */
1256 hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
1257 if(!hbmImage) goto cleanup;
1259 iImage = pImageList_Add(himl, hbmImage, hbmMask);
1260 ok(iImage != -1, "ImageList_Add failed\n");
1261 if(iImage == -1) goto cleanup;
1263 /* Add an alpha image */
1264 hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
1265 if(!hbmAlphaImage) goto cleanup;
1267 iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1268 ok(iAlphaImage != -1, "ImageList_Add failed\n");
1269 if(iAlphaImage == -1) goto cleanup;
1271 /* Add a transparent alpha image */
1272 hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
1273 if(!hbmTransparentImage) goto cleanup;
1275 iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1276 ok(iTransparentImage != -1, "ImageList_Add failed\n");
1277 if(iTransparentImage == -1) goto cleanup;
1279 /* 32-bit Tests */
1280 bitmapInfo.bmiHeader.biBitCount = 32;
1281 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1282 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1283 if (!hbmDst || !bits)
1284 goto cleanup;
1285 hbmOld = SelectObject(hdcDst, hbmDst);
1287 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1288 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1289 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
1290 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1291 else broken_value = 0x00B4BDC4;
1292 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1293 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1294 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1295 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1297 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
1298 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
1300 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1301 else broken_value = 0x009DA8B1;
1302 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1303 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1304 else broken_value = 0x008C99A3;
1305 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1306 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
1307 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
1308 todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
1310 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
1312 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1313 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
1315 /* ILD_ROP is ignored when the image has an alpha channel */
1316 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
1317 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
1319 todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
1320 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
1322 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
1323 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
1325 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
1326 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
1327 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
1329 cleanup:
1331 if(hbmOld)
1332 SelectObject(hdcDst, hbmOld);
1333 if(hbmDst)
1334 DeleteObject(hbmDst);
1336 if(hdcDst)
1337 DeleteDC(hdcDst);
1339 if(hbmMask)
1340 DeleteObject(hbmMask);
1341 if(hbmInverseMask)
1342 DeleteObject(hbmInverseMask);
1344 if(hbmImage)
1345 DeleteObject(hbmImage);
1346 if(hbmAlphaImage)
1347 DeleteObject(hbmAlphaImage);
1348 if(hbmTransparentImage)
1349 DeleteObject(hbmTransparentImage);
1351 if(himl)
1353 ret = ImageList_Destroy(himl);
1354 ok(ret, "ImageList_Destroy failed\n");
1358 static void test_iimagelist(void)
1360 IImageList *imgl, *imgl2;
1361 HIMAGELIST himl;
1362 HRESULT hr;
1363 ULONG ret;
1365 if (!pHIMAGELIST_QueryInterface)
1367 win_skip("XP imagelist functions not available\n");
1368 return;
1371 /* test reference counting on destruction */
1372 imgl = (IImageList*)createImageList(32, 32);
1373 ret = IUnknown_AddRef(imgl);
1374 ok(ret == 2, "Expected 2, got %d\n", ret);
1375 ret = ImageList_Destroy((HIMAGELIST)imgl);
1376 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1377 ret = ImageList_Destroy((HIMAGELIST)imgl);
1378 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1379 ret = ImageList_Destroy((HIMAGELIST)imgl);
1380 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1382 imgl = (IImageList*)createImageList(32, 32);
1383 ret = IUnknown_AddRef(imgl);
1384 ok(ret == 2, "Expected 2, got %d\n", ret);
1385 ret = ImageList_Destroy((HIMAGELIST)imgl);
1386 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1387 ret = IImageList_Release(imgl);
1388 ok(ret == 0, "Expected 0, got %d\n", ret);
1389 ret = ImageList_Destroy((HIMAGELIST)imgl);
1390 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1392 /* ref counting, HIMAGELIST_QueryInterface adds a reference */
1393 imgl = (IImageList*)createImageList(32, 32);
1394 hr = pHIMAGELIST_QueryInterface((HIMAGELIST)imgl, &IID_IImageList, (void**)&imgl2);
1395 ok(hr == S_OK, "got 0x%08x\n", hr);
1396 ok(imgl2 == imgl, "got different pointer\n");
1397 ret = IImageList_Release(imgl);
1398 ok(ret == 1, "got %u\n", ret);
1399 IImageList_Release(imgl);
1401 if (!pImageList_CoCreateInstance)
1403 win_skip("Vista imagelist functions not available\n");
1404 return;
1407 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1408 ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
1410 if (hr == S_OK)
1411 IImageList_Release(imgl);
1413 himl = createImageList(32, 32);
1415 if (!himl)
1416 return;
1418 hr = (pHIMAGELIST_QueryInterface)(himl, &IID_IImageList, (void **) &imgl);
1419 ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
1421 if (hr == S_OK)
1422 IImageList_Release(imgl);
1424 ImageList_Destroy(himl);
1427 static void test_hotspot_v6(void)
1429 struct hotspot {
1430 int dx;
1431 int dy;
1434 #define SIZEX1 47
1435 #define SIZEY1 31
1436 #define SIZEX2 11
1437 #define SIZEY2 17
1438 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
1439 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
1440 { 10, 7 },
1441 { SIZEX1, SIZEY1 },
1442 { -9, -8 },
1443 { -7, 35 }
1445 int i, j;
1446 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
1447 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
1448 IImageList *imgl1, *imgl2;
1449 HRESULT hr;
1451 /* cast to IImageList */
1452 imgl1 = (IImageList *) himl1;
1453 imgl2 = (IImageList *) himl2;
1455 for (i = 0; i < HOTSPOTS_MAX; i++) {
1456 for (j = 0; j < HOTSPOTS_MAX; j++) {
1457 int dx1 = hotspots[i].dx;
1458 int dy1 = hotspots[i].dy;
1459 int dx2 = hotspots[j].dx;
1460 int dy2 = hotspots[j].dy;
1461 int correctx, correcty, newx, newy;
1462 char loc[256];
1463 IImageList *imglNew;
1464 POINT ppt;
1466 hr = IImageList_BeginDrag(imgl1, 0, dx1, dy1);
1467 ok(SUCCEEDED(hr), "BeginDrag failed for { %d, %d }\n", dx1, dy1);
1468 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
1470 /* check merging the dragged image with a second image */
1471 hr = IImageList_SetDragCursorImage(imgl2, (IUnknown *) imgl2, 0, dx2, dy2);
1472 ok(SUCCEEDED(hr), "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
1473 dx1, dy1, dx2, dy2);
1474 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
1476 /* check new hotspot, it should be the same like the old one */
1477 hr = IImageList_GetDragImage(imgl2, NULL, &ppt, &IID_IImageList, (PVOID *) &imglNew);
1478 ok(SUCCEEDED(hr), "GetDragImage failed\n");
1479 ok(ppt.x == dx1 && ppt.y == dy1,
1480 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
1481 dx1, dy1, ppt.x, ppt.y);
1482 /* check size of new dragged image */
1483 IImageList_GetIconSize(imglNew, &newx, &newy);
1484 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
1485 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
1486 ok(newx == correctx && newy == correcty,
1487 "Expected drag image size [%d,%d] got [%d,%d]\n",
1488 correctx, correcty, newx, newy);
1489 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
1490 IImageList_EndDrag(imgl2);
1493 #undef SIZEX1
1494 #undef SIZEY1
1495 #undef SIZEX2
1496 #undef SIZEY2
1497 #undef HOTSPOTS_MAX
1498 IImageList_Release(imgl2);
1499 IImageList_Release(imgl1);
1502 static void test_IImageList_Add_Remove(void)
1504 IImageList *imgl;
1505 HIMAGELIST himl;
1506 HRESULT hr;
1508 HICON hicon1;
1509 HICON hicon2;
1510 HICON hicon3;
1512 int ret;
1514 /* create an imagelist to play with */
1515 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1516 ok(himl != 0,"failed to create imagelist\n");
1518 imgl = (IImageList *) himl;
1520 /* load the icons to add to the image list */
1521 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1522 ok(hicon1 != 0, "no hicon1\n");
1523 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1524 ok(hicon2 != 0, "no hicon2\n");
1525 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1526 ok(hicon3 != 0, "no hicon3\n");
1528 /* remove when nothing exists */
1529 hr = IImageList_Remove(imgl, 0);
1530 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1532 /* removing everything from an empty imagelist should succeed */
1533 hr = IImageList_Remove(imgl, -1);
1534 ok(hr == S_OK, "removed nonexistent icon\n");
1536 /* add three */
1537 ret = -1;
1538 ok( IImageList_ReplaceIcon(imgl, -1, hicon1, &ret) == S_OK && (ret == 0),"failed to add icon1\n");
1539 ret = -1;
1540 ok( IImageList_ReplaceIcon(imgl, -1, hicon2, &ret) == S_OK && (ret == 1),"failed to add icon2\n");
1541 ret = -1;
1542 ok( IImageList_ReplaceIcon(imgl, -1, hicon3, &ret) == S_OK && (ret == 2),"failed to add icon3\n");
1544 /* remove an index out of range */
1545 ok( IImageList_Remove(imgl, 4711) == E_INVALIDARG, "got 0x%08x\n", hr);
1547 /* remove three */
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");
1550 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1552 /* remove one extra */
1553 ok( IImageList_Remove(imgl, 0) == E_INVALIDARG, "got 0x%08x\n", hr);
1555 IImageList_Release(imgl);
1556 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1557 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1558 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1561 static void test_IImageList_Get_SetImageCount(void)
1563 IImageList *imgl;
1564 HIMAGELIST himl;
1565 HRESULT hr;
1566 INT ret;
1568 /* create an imagelist to play with */
1569 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1570 ok(himl != 0,"failed to create imagelist\n");
1572 imgl = (IImageList *) himl;
1574 /* check SetImageCount/GetImageCount */
1575 hr = IImageList_SetImageCount(imgl, 3);
1576 ok(hr == S_OK, "got 0x%08x\n", hr);
1577 ret = 0;
1578 hr = IImageList_GetImageCount(imgl, &ret);
1579 ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
1580 hr = IImageList_SetImageCount(imgl, 1);
1581 ok(hr == S_OK, "got 0x%08x\n", hr);
1582 ret = 0;
1583 hr = IImageList_GetImageCount(imgl, &ret);
1584 ok(hr == S_OK && ret == 1, "invalid image count after decrease to 1\n");
1585 hr = IImageList_SetImageCount(imgl, 0);
1586 ok(hr == S_OK, "got 0x%08x\n", hr);
1587 ret = -1;
1588 hr = IImageList_GetImageCount(imgl, &ret);
1589 ok(hr == S_OK && ret == 0, "invalid image count after decrease to 0\n");
1591 IImageList_Release(imgl);
1594 static void test_IImageList_Draw(void)
1596 IImageList *imgl;
1597 HIMAGELIST himl;
1599 HBITMAP hbm1;
1600 HBITMAP hbm2;
1601 HBITMAP hbm3;
1603 IMAGELISTDRAWPARAMS imldp;
1604 HWND hwndfortest;
1605 HRESULT hr;
1606 HDC hdc;
1607 int ret;
1609 hwndfortest = create_a_window();
1610 hdc = GetDC(hwndfortest);
1611 ok(hdc!=NULL, "couldn't get DC\n");
1613 /* create an imagelist to play with */
1614 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1615 ok(himl!=0,"failed to create imagelist\n");
1617 imgl = (IImageList *) himl;
1619 /* load the icons to add to the image list */
1620 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1621 ok(hbm1 != 0, "no bitmap 1\n");
1622 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1623 ok(hbm2 != 0, "no bitmap 2\n");
1624 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1625 ok(hbm3 != 0, "no bitmap 3\n");
1627 /* add three */
1628 ret = -1;
1629 ok( IImageList_Add(imgl, hbm1, 0, &ret) == S_OK && (ret == 0), "failed to add bitmap 1\n");
1630 ret = -1;
1631 ok( IImageList_Add(imgl, hbm2, 0, &ret) == S_OK && (ret == 1), "failed to add bitmap 2\n");
1633 ok( IImageList_SetImageCount(imgl, 3) == S_OK, "Setimage count failed\n");
1634 ok( IImageList_Replace(imgl, 2, hbm3, 0) == S_OK, "failed to replace bitmap 3\n");
1636 if (0)
1638 /* crashes on native */
1639 IImageList_Draw(imgl, NULL);
1642 memset(&imldp, 0, sizeof (imldp));
1643 hr = IImageList_Draw(imgl, &imldp);
1644 ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
1646 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
1647 imldp.hdcDst = hdc;
1648 imldp.himl = himl;
1650 REDRAW(hwndfortest);
1651 WAIT;
1653 imldp.fStyle = SRCCOPY;
1654 imldp.rgbBk = CLR_DEFAULT;
1655 imldp.rgbFg = CLR_DEFAULT;
1656 imldp.y = 100;
1657 imldp.x = 100;
1658 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1659 imldp.i ++;
1660 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1661 imldp.i ++;
1662 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1663 imldp.i ++;
1664 ok( IImageList_Draw(imgl, &imldp) == E_INVALIDARG, "should fail\n");
1666 /* remove three */
1667 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 1st bitmap\n");
1668 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 2nd bitmap\n");
1669 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 3rd bitmap\n");
1671 /* destroy it */
1672 IImageList_Release(imgl);
1674 /* bitmaps should not be deleted by the imagelist */
1675 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1676 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1677 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1679 ReleaseDC(hwndfortest, hdc);
1680 DestroyWindow(hwndfortest);
1683 static void test_IImageList_Merge(void)
1685 HIMAGELIST himl1, himl2;
1686 IImageList *imgl1, *imgl2, *merge;
1687 HICON hicon1;
1688 HWND hwnd = create_a_window();
1689 HRESULT hr;
1690 int ret;
1692 himl1 = ImageList_Create(32,32,0,0,3);
1693 ok(himl1 != NULL,"failed to create himl1\n");
1695 himl2 = ImageList_Create(32,32,0,0,3);
1696 ok(himl2 != NULL,"failed to create himl2\n");
1698 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1699 ok(hicon1 != NULL, "failed to create hicon1\n");
1701 if (!himl1 || !himl2 || !hicon1)
1702 return;
1704 /* cast to IImageList */
1705 imgl1 = (IImageList *) himl1;
1706 imgl2 = (IImageList *) himl2;
1708 ret = -1;
1709 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl2 failed\n");
1711 if (0)
1713 /* null cases that crash on native */
1714 IImageList_Merge(imgl1, -1, NULL, 0, 0, 0, &IID_IImageList, (void**)&merge);
1715 IImageList_Merge(imgl1, -1, (IUnknown*) imgl2, 0, 0, 0, &IID_IImageList, NULL);
1718 /* If himl1 has no images, merge still succeeds */
1719 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1720 ok(hr == S_OK, "merge himl1,-1 failed\n");
1721 if (hr == S_OK) IImageList_Release(merge);
1723 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1724 ok(hr == S_OK, "merge himl1,0 failed\n");
1725 if (hr == S_OK) IImageList_Release(merge);
1727 /* Same happens if himl2 is empty */
1728 IImageList_Release(imgl2);
1729 himl2 = ImageList_Create(32,32,0,0,3);
1730 ok(himl2 != NULL,"failed to recreate himl2\n");
1732 imgl2 = (IImageList *) himl2;
1734 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
1735 ok(hr == S_OK, "merge himl2,-1 failed\n");
1736 if (hr == S_OK) IImageList_Release(merge);
1738 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1739 ok(hr == S_OK, "merge himl2,0 failed\n");
1740 if (hr == S_OK) IImageList_Release(merge);
1742 /* Now try merging an image with itself */
1743 ret = -1;
1744 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"re-add icon1 to himl2 failed\n");
1746 hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1747 ok(hr == S_OK, "merge himl2 with itself failed\n");
1748 if (hr == S_OK) IImageList_Release(merge);
1750 /* Try merging 2 different image lists */
1751 ret = -1;
1752 ok( IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl1 failed\n");
1754 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1755 ok(hr == S_OK, "merge himl1 with himl2 failed\n");
1756 if (hr == S_OK) IImageList_Release(merge);
1758 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
1759 ok(hr == S_OK, "merge himl1 with himl2 8,16 failed\n");
1760 if (hr == S_OK) IImageList_Release(merge);
1762 IImageList_Release(imgl1);
1763 IImageList_Release(imgl2);
1765 DestroyIcon(hicon1);
1766 DestroyWindow(hwnd);
1769 static void test_iconsize(void)
1771 HIMAGELIST himl;
1772 INT cx, cy;
1773 BOOL ret;
1775 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1776 /* null pointers, not zero imagelist dimensions */
1777 ret = ImageList_GetIconSize(himl, NULL, NULL);
1778 ok(!ret, "got %d\n", ret);
1780 /* doesn't touch return pointers */
1781 cx = 0x1abe11ed;
1782 ret = ImageList_GetIconSize(himl, &cx, NULL);
1783 ok(!ret, "got %d\n", ret);
1784 ok(cx == 0x1abe11ed, "got %d\n", cx);
1786 cy = 0x1abe11ed;
1787 ret = ImageList_GetIconSize(himl, NULL, &cy);
1788 ok(!ret, "got %d\n", ret);
1789 ok(cy == 0x1abe11ed, "got %d\n", cy);
1791 ImageList_Destroy(himl);
1793 ret = ImageList_GetIconSize((HIMAGELIST)0xdeadbeef, &cx, &cy);
1794 ok(!ret, "got %d\n", ret);
1797 static void test_create_destroy(void)
1799 HIMAGELIST himl;
1800 BOOL rc;
1802 /* list with zero or negative image dimensions */
1803 himl = ImageList_Create(0, 0, ILC_COLOR16, 0, 3);
1804 ok(himl == NULL, "got %p\n", himl);
1806 himl = ImageList_Create(0, 16, ILC_COLOR16, 0, 3);
1807 ok(himl == NULL, "got %p\n", himl);
1809 himl = ImageList_Create(16, 0, ILC_COLOR16, 0, 3);
1810 ok(himl == NULL, "got %p\n", himl);
1812 himl = ImageList_Create(16, -1, ILC_COLOR16, 0, 3);
1813 ok(himl == NULL, "got %p\n", himl);
1815 himl = ImageList_Create(-1, 16, ILC_COLOR16, 0, 3);
1816 ok(himl == NULL, "got %p\n", himl);
1818 rc = ImageList_Destroy((HIMAGELIST)0xdeadbeef);
1819 ok(rc == FALSE, "ImageList_Destroy(0xdeadbeef) should fail and not crash\n");
1822 static void test_IImageList_Clone(void)
1824 IImageList *imgl, *imgl2;
1825 HIMAGELIST himl;
1826 HRESULT hr;
1827 ULONG ref;
1829 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1830 imgl = (IImageList*)himl;
1832 if (0)
1834 /* crashes on native */
1835 IImageList_Clone(imgl, &IID_IImageList, NULL);
1838 hr = IImageList_Clone(imgl, &IID_IImageList, (void**)&imgl2);
1839 ok(hr == S_OK, "got 0x%08x\n", hr);
1840 ref = IImageList_Release(imgl2);
1841 ok(ref == 0, "got %u\n", ref);
1843 IImageList_Release(imgl);
1846 static void test_IImageList_GetBkColor(void)
1848 IImageList *imgl;
1849 HIMAGELIST himl;
1850 COLORREF color;
1851 HRESULT hr;
1853 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1854 imgl = (IImageList*)himl;
1856 if (0)
1858 /* crashes on native */
1859 IImageList_GetBkColor(imgl, NULL);
1862 hr = IImageList_GetBkColor(imgl, &color);
1863 ok(hr == S_OK, "got 0x%08x\n", hr);
1865 IImageList_Release(imgl);
1868 static void test_IImageList_SetBkColor(void)
1870 IImageList *imgl;
1871 HIMAGELIST himl;
1872 COLORREF color;
1873 HRESULT hr;
1875 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1876 imgl = (IImageList*)himl;
1878 if (0)
1880 /* crashes on native */
1881 IImageList_SetBkColor(imgl, RGB(0, 0, 0), NULL);
1884 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1885 ok(hr == S_OK, "got 0x%08x\n", hr);
1887 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1888 ok(hr == S_OK, "got 0x%08x\n", hr);
1890 color = 0xdeadbeef;
1891 hr = IImageList_GetBkColor(imgl, &color);
1892 ok(hr == S_OK, "got 0x%08x\n", hr);
1893 ok(color == CLR_NONE, "got %x\n", color);
1895 IImageList_Release(imgl);
1898 static void test_IImageList_GetImageCount(void)
1900 IImageList *imgl;
1901 HIMAGELIST himl;
1902 int count;
1903 HRESULT hr;
1905 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1906 imgl = (IImageList*)himl;
1908 if (0)
1910 /* crashes on native */
1911 IImageList_GetImageCount(imgl, NULL);
1914 count = -1;
1915 hr = IImageList_GetImageCount(imgl, &count);
1916 ok(hr == S_OK, "got 0x%08x\n", hr);
1917 ok(count == 0, "got %d\n", count);
1919 IImageList_Release(imgl);
1922 static void test_IImageList_GetIconSize(void)
1924 IImageList *imgl;
1925 HIMAGELIST himl;
1926 int cx, cy;
1927 HRESULT hr;
1929 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1930 imgl = (IImageList*)himl;
1932 hr = IImageList_GetIconSize(imgl, NULL, NULL);
1933 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1935 hr = IImageList_GetIconSize(imgl, &cx, NULL);
1936 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1938 hr = IImageList_GetIconSize(imgl, NULL, &cy);
1939 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1941 IImageList_Release(imgl);
1944 START_TEST(imagelist)
1946 ULONG_PTR ctx_cookie;
1947 HANDLE hCtx;
1949 HMODULE hComCtl32 = GetModuleHandle("comctl32.dll");
1950 pImageList_Create = NULL; /* These are not needed for non-v6.0 tests*/
1951 pImageList_Add = NULL;
1952 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1953 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1955 hinst = GetModuleHandleA(NULL);
1957 InitCommonControls();
1959 test_create_destroy();
1960 test_hotspot();
1961 test_add_remove();
1962 test_imagecount();
1963 test_DrawIndirect();
1964 test_merge();
1965 test_imagelist_storage();
1966 test_iconsize();
1968 FreeLibrary(hComCtl32);
1970 /* Now perform v6 tests */
1972 if (!load_v6_module(&ctx_cookie, &hCtx))
1973 return;
1975 /* Reload comctl32 */
1976 hComCtl32 = LoadLibraryA("comctl32.dll");
1977 pImageList_Create = (void*)GetProcAddress(hComCtl32, "ImageList_Create");
1978 pImageList_Add = (void*)GetProcAddress(hComCtl32, "ImageList_Add");
1979 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1980 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1981 pImageList_CoCreateInstance = (void*)GetProcAddress(hComCtl32, "ImageList_CoCreateInstance");
1982 pHIMAGELIST_QueryInterface = (void*)GetProcAddress(hComCtl32, "HIMAGELIST_QueryInterface");
1984 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1986 /* Do v6.0 tests */
1987 test_ImageList_DrawIndirect();
1988 test_shell_imagelist();
1989 test_iimagelist();
1991 test_hotspot_v6();
1992 test_IImageList_Add_Remove();
1993 test_IImageList_Get_SetImageCount();
1994 test_IImageList_Draw();
1995 test_IImageList_Merge();
1996 test_IImageList_Clone();
1997 test_IImageList_GetBkColor();
1998 test_IImageList_SetBkColor();
1999 test_IImageList_GetImageCount();
2000 test_IImageList_GetIconSize();
2002 CoUninitialize();
2004 unload_v6_module(ctx_cookie, hCtx);