dplayx: Code to forward player creation
[wine/gsoc_dplay.git] / dlls / comctl32 / tests / imagelist.c
blob9bb0253dff2ded13881ea7420005ba0d803e962e
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 BOOL (WINAPI *pImageList_DrawIndirect)(IMAGELISTDRAWPARAMS*);
74 static BOOL (WINAPI *pImageList_SetImageCount)(HIMAGELIST,UINT);
76 static HDC desktopDC;
77 static HINSTANCE hinst;
79 /* These macros build cursor/bitmap data in 4x4 pixel blocks */
80 #define B(x,y) ((x?0xf0:0)|(y?0xf:0))
81 #define ROW1(a,b,c,d,e,f,g,h) B(a,b),B(c,d),B(e,f),B(g,h)
82 #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), \
83 ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h)
84 #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)
85 #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), \
86 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), \
87 ROW2(a,b,c,d,e,f,g,h,i,j,k,l)
89 static const BYTE empty_bits[48*48/8];
91 static const BYTE icon_bits[32*32/8] =
93 ROW32(0,0,0,0,0,0,0,0),
94 ROW32(0,0,1,1,1,1,0,0),
95 ROW32(0,1,1,1,1,1,1,0),
96 ROW32(0,1,1,0,0,1,1,0),
97 ROW32(0,1,1,0,0,1,1,0),
98 ROW32(0,1,1,1,1,1,1,0),
99 ROW32(0,0,1,1,1,1,0,0),
100 ROW32(0,0,0,0,0,0,0,0)
103 static const BYTE bitmap_bits[48*48/8] =
105 ROW48(0,0,0,0,0,0,0,0,0,0,0,0),
106 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
107 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
108 ROW48(0,1,0,0,0,0,0,0,1,0,1,0),
109 ROW48(0,1,0,0,0,0,0,1,0,0,1,0),
110 ROW48(0,1,0,0,0,0,1,0,0,0,1,0),
111 ROW48(0,1,0,0,0,1,0,0,0,0,1,0),
112 ROW48(0,1,0,0,1,0,0,0,0,0,1,0),
113 ROW48(0,1,0,1,0,0,0,0,0,0,1,0),
114 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
115 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
116 ROW48(0,0,0,0,0,0,0,0,0,0,0,0)
119 static HIMAGELIST createImageList(int cx, int cy)
121 /* Create an ImageList and put an image into it */
122 HIMAGELIST himl = ImageList_Create(cx, cy, ILC_COLOR, 1, 1);
123 HBITMAP hbm = CreateBitmap(48, 48, 1, 1, bitmap_bits);
124 ImageList_Add(himl, hbm, NULL);
125 return himl;
128 static HWND create_a_window(void)
130 char className[] = "bmwnd";
131 char winName[] = "Test Bitmap";
132 HWND hWnd;
133 static int registered = 0;
135 if (!registered)
137 WNDCLASSA cls;
139 cls.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
140 cls.lpfnWndProc = DefWindowProcA;
141 cls.cbClsExtra = 0;
142 cls.cbWndExtra = 0;
143 cls.hInstance = 0;
144 cls.hIcon = LoadIconA (0, IDI_APPLICATION);
145 cls.hCursor = LoadCursorA (0, IDC_ARROW);
146 cls.hbrBackground = GetStockObject (WHITE_BRUSH);
147 cls.lpszMenuName = 0;
148 cls.lpszClassName = className;
150 RegisterClassA (&cls);
151 registered = 1;
154 /* Setup window */
155 hWnd = CreateWindowA (className, winName,
156 WS_OVERLAPPEDWINDOW ,
157 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
158 0, hinst, 0);
160 #ifdef VISIBLE
161 ShowWindow (hWnd, SW_SHOW);
162 #endif
163 REDRAW(hWnd);
164 WAIT;
166 return hWnd;
169 static HDC show_image(HWND hwnd, HIMAGELIST himl, int idx, int size,
170 LPCSTR loc, BOOL clear)
172 HDC hdc = NULL;
173 #ifdef VISIBLE
174 if (!himl) return NULL;
176 SetWindowText(hwnd, loc);
177 hdc = GetDC(hwnd);
178 ImageList_Draw(himl, idx, hdc, 0, 0, ILD_TRANSPARENT);
180 REDRAW(hwnd);
181 WAIT;
183 if (clear)
185 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
186 ReleaseDC(hwnd, hdc);
187 hdc = NULL;
189 #endif /* VISIBLE */
190 return hdc;
193 /* Useful for checking differences */
194 #if 0
195 static void dump_bits(const BYTE *p, const BYTE *q, int size)
197 int i, j;
199 size /= 8;
201 for (i = 0; i < size * 2; i++)
203 printf("|");
204 for (j = 0; j < size; j++)
205 printf("%c%c", p[j] & 0xf0 ? 'X' : ' ', p[j] & 0xf ? 'X' : ' ');
206 printf(" -- ");
207 for (j = 0; j < size; j++)
208 printf("%c%c", q[j] & 0xf0 ? 'X' : ' ', q[j] & 0xf ? 'X' : ' ');
209 printf("|\n");
210 p += size * 4;
211 q += size * 4;
213 printf("\n");
215 #endif
217 static void check_bits(HWND hwnd, HIMAGELIST himl, int idx, int size,
218 const BYTE *checkbits, LPCSTR loc)
220 #ifdef VISIBLE
221 BYTE bits[100*100/8];
222 COLORREF c;
223 HDC hdc;
224 int x, y, i = -1;
226 if (!himl) return;
228 memset(bits, 0, sizeof(bits));
229 hdc = show_image(hwnd, himl, idx, size, loc, FALSE);
231 c = GetPixel(hdc, 0, 0);
233 for (y = 0; y < size; y ++)
235 for (x = 0; x < size; x++)
237 if (!(x & 0x7)) i++;
238 if (GetPixel(hdc, x, y) != c) bits[i] |= (0x80 >> (x & 0x7));
242 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
243 ReleaseDC(hwnd, hdc);
245 ok (memcmp(bits, checkbits, (size * size)/8) == 0,
246 "%s: bits different\n", loc);
247 if (memcmp(bits, checkbits, (size * size)/8))
248 dump_bits(bits, checkbits, size);
249 #endif /* VISIBLE */
252 static void testHotspot (void)
254 struct hotspot {
255 int dx;
256 int dy;
259 #define SIZEX1 47
260 #define SIZEY1 31
261 #define SIZEX2 11
262 #define SIZEY2 17
263 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
264 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
265 { 10, 7 },
266 { SIZEX1, SIZEY1 },
267 { -9, -8 },
268 { -7, 35 }
270 int i, j, ret;
271 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
272 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
273 HWND hwnd = create_a_window();
276 for (i = 0; i < HOTSPOTS_MAX; i++) {
277 for (j = 0; j < HOTSPOTS_MAX; j++) {
278 int dx1 = hotspots[i].dx;
279 int dy1 = hotspots[i].dy;
280 int dx2 = hotspots[j].dx;
281 int dy2 = hotspots[j].dy;
282 int correctx, correcty, newx, newy;
283 char loc[256];
284 HIMAGELIST himlNew;
285 POINT ppt;
287 ret = ImageList_BeginDrag(himl1, 0, dx1, dy1);
288 ok(ret != 0, "BeginDrag failed for { %d, %d }\n", dx1, dy1);
289 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
290 show_image(hwnd, himl1, 0, max(SIZEX1, SIZEY1), loc, TRUE);
292 /* check merging the dragged image with a second image */
293 ret = ImageList_SetDragCursorImage(himl2, 0, dx2, dy2);
294 ok(ret != 0, "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
295 dx1, dy1, dx2, dy2);
296 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
297 show_image(hwnd, himl2, 0, max(SIZEX2, SIZEY2), loc, TRUE);
299 /* check new hotspot, it should be the same like the old one */
300 himlNew = ImageList_GetDragImage(NULL, &ppt);
301 ok(ppt.x == dx1 && ppt.y == dy1,
302 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
303 dx1, dy1, ppt.x, ppt.y);
304 /* check size of new dragged image */
305 ImageList_GetIconSize(himlNew, &newx, &newy);
306 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
307 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
308 ok(newx == correctx && newy == correcty,
309 "Expected drag image size [%d,%d] got [%d,%d]\n",
310 correctx, correcty, newx, newy);
311 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
312 show_image(hwnd, himlNew, 0, max(correctx, correcty), loc, TRUE);
313 ImageList_EndDrag();
316 #undef SIZEX1
317 #undef SIZEY1
318 #undef SIZEX2
319 #undef SIZEY2
320 #undef HOTSPOTS_MAX
321 ImageList_Destroy(himl2);
322 ImageList_Destroy(himl1);
323 DestroyWindow(hwnd);
326 static BOOL DoTest1(void)
328 HIMAGELIST himl ;
330 HICON hicon1 ;
331 HICON hicon2 ;
332 HICON hicon3 ;
334 /* create an imagelist to play with */
335 himl = ImageList_Create(84,84,0x10,0,3);
336 ok(himl!=0,"failed to create imagelist\n");
338 /* load the icons to add to the image list */
339 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
340 ok(hicon1 != 0, "no hicon1\n");
341 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
342 ok(hicon2 != 0, "no hicon2\n");
343 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
344 ok(hicon3 != 0, "no hicon3\n");
346 /* remove when nothing exists */
347 ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
348 /* removing everything from an empty imagelist should succeed */
349 ok(ImageList_RemoveAll(himl),"removed nonexistent icon\n");
351 /* add three */
352 ok(0==ImageList_AddIcon(himl, hicon1),"failed to add icon1\n");
353 ok(1==ImageList_AddIcon(himl, hicon2),"failed to add icon2\n");
354 ok(2==ImageList_AddIcon(himl, hicon3),"failed to add icon3\n");
356 /* remove an index out of range */
357 ok(!ImageList_Remove(himl,4711),"removed nonexistent icon\n");
359 /* remove three */
360 ok(ImageList_Remove(himl,0),"can't remove 0\n");
361 ok(ImageList_Remove(himl,0),"can't remove 0\n");
362 ok(ImageList_Remove(himl,0),"can't remove 0\n");
364 /* remove one extra */
365 ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
367 /* check SetImageCount/GetImageCount */
368 if (pImageList_SetImageCount)
370 ok(pImageList_SetImageCount(himl, 3), "couldn't increase image count\n");
371 ok(ImageList_GetImageCount(himl) == 3, "invalid image count after increase\n");
372 ok(pImageList_SetImageCount(himl, 1), "couldn't decrease image count\n");
373 ok(ImageList_GetImageCount(himl) == 1, "invalid image count after decrease to 1\n");
374 ok(pImageList_SetImageCount(himl, 0), "couldn't decrease image count\n");
375 ok(ImageList_GetImageCount(himl) == 0, "invalid image count after decrease to 0\n");
377 else
379 skip("skipped ImageList_SetImageCount tests\n");
382 /* destroy it */
383 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
385 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
386 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
387 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
389 return TRUE;
392 static BOOL DoTest2(void)
394 HIMAGELIST himl ;
396 HICON hicon1 ;
397 HICON hicon2 ;
398 HICON hicon3 ;
400 /* create an imagelist to play with */
401 himl = ImageList_Create(84,84,0x10,0,3);
402 ok(himl!=0,"failed to create imagelist\n");
404 /* load the icons to add to the image list */
405 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
406 ok(hicon1 != 0, "no hicon1\n");
407 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
408 ok(hicon2 != 0, "no hicon2\n");
409 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
410 ok(hicon3 != 0, "no hicon3\n");
412 /* add three */
413 ok(0==ImageList_AddIcon(himl, hicon1),"failed to add icon1\n");
414 ok(1==ImageList_AddIcon(himl, hicon2),"failed to add icon2\n");
415 ok(2==ImageList_AddIcon(himl, hicon3),"failed to add icon3\n");
417 /* destroy it */
418 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
420 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
421 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
422 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
424 return TRUE;
427 static BOOL DoTest3(void)
429 HIMAGELIST himl;
431 HBITMAP hbm1;
432 HBITMAP hbm2;
433 HBITMAP hbm3;
435 IMAGELISTDRAWPARAMS imldp;
436 HDC hdc;
437 HWND hwndfortest;
439 if (!pImageList_DrawIndirect)
441 win_skip("ImageList_DrawIndirect not available, skipping test\n");
442 return TRUE;
445 hwndfortest = create_a_window();
446 hdc = GetDC(hwndfortest);
447 ok(hdc!=NULL, "couldn't get DC\n");
449 /* create an imagelist to play with */
450 himl = ImageList_Create(48,48,0x10,0,3);
451 ok(himl!=0,"failed to create imagelist\n");
453 /* load the icons to add to the image list */
454 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
455 ok(hbm1 != 0, "no bitmap 1\n");
456 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
457 ok(hbm2 != 0, "no bitmap 2\n");
458 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
459 ok(hbm3 != 0, "no bitmap 3\n");
461 /* add three */
462 ok(0==ImageList_Add(himl, hbm1, 0),"failed to add bitmap 1\n");
463 ok(1==ImageList_Add(himl, hbm2, 0),"failed to add bitmap 2\n");
465 if (pImageList_SetImageCount)
467 ok(pImageList_SetImageCount(himl,3),"Setimage count failed\n");
468 /*ok(2==ImageList_Add(himl, hbm3, NULL),"failed to add bitmap 3\n"); */
469 ok(ImageList_Replace(himl, 2, hbm3, 0),"failed to replace bitmap 3\n");
472 memset(&imldp, 0, sizeof (imldp));
473 ok(!pImageList_DrawIndirect(&imldp), "zero data succeeded!\n");
474 imldp.cbSize = sizeof (imldp);
475 ok(!pImageList_DrawIndirect(&imldp), "zero hdc succeeded!\n");
476 imldp.hdcDst = hdc;
477 ok(!pImageList_DrawIndirect(&imldp),"zero himl succeeded!\n");
478 imldp.himl = himl;
479 if (!pImageList_DrawIndirect(&imldp))
481 /* Earlier versions of native comctl32 use a smaller structure */
482 imldp.cbSize -= 3 * sizeof(DWORD);
483 ok(pImageList_DrawIndirect(&imldp),"DrawIndirect should succeed\n");
485 REDRAW(hwndfortest);
486 WAIT;
488 imldp.fStyle = SRCCOPY;
489 imldp.rgbBk = CLR_DEFAULT;
490 imldp.rgbFg = CLR_DEFAULT;
491 imldp.y = 100;
492 imldp.x = 100;
493 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
494 imldp.i ++;
495 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
496 imldp.i ++;
497 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
498 imldp.i ++;
499 ok(!pImageList_DrawIndirect(&imldp),"should fail\n");
501 /* remove three */
502 ok(ImageList_Remove(himl, 0), "removing 1st bitmap\n");
503 ok(ImageList_Remove(himl, 0), "removing 2nd bitmap\n");
504 ok(ImageList_Remove(himl, 0), "removing 3rd bitmap\n");
506 /* destroy it */
507 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
509 /* bitmaps should not be deleted by the imagelist */
510 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
511 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
512 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
514 ReleaseDC(hwndfortest, hdc);
515 DestroyWindow(hwndfortest);
517 return TRUE;
520 static void testMerge(void)
522 HIMAGELIST himl1, himl2, hmerge;
523 HICON hicon1;
524 HWND hwnd = create_a_window();
526 himl1 = ImageList_Create(32,32,0,0,3);
527 ok(himl1 != NULL,"failed to create himl1\n");
529 himl2 = ImageList_Create(32,32,0,0,3);
530 ok(himl2 != NULL,"failed to create himl2\n");
532 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
533 ok(hicon1 != NULL, "failed to create hicon1\n");
535 if (!himl1 || !himl2 || !hicon1)
536 return;
538 ok(0==ImageList_AddIcon(himl2, hicon1),"add icon1 to himl2 failed\n");
539 check_bits(hwnd, himl2, 0, 32, icon_bits, "add icon1 to himl2");
541 /* If himl1 has no images, merge still succeeds */
542 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
543 ok(hmerge != NULL, "merge himl1,-1 failed\n");
544 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,-1");
545 if (hmerge) ImageList_Destroy(hmerge);
547 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
548 ok(hmerge != NULL,"merge himl1,0 failed\n");
549 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,0");
550 if (hmerge) ImageList_Destroy(hmerge);
552 /* Same happens if himl2 is empty */
553 ImageList_Destroy(himl2);
554 himl2 = ImageList_Create(32,32,0,0,3);
555 ok(himl2 != NULL,"failed to recreate himl2\n");
556 if (!himl2)
557 return;
559 hmerge = ImageList_Merge(himl1, -1, himl2, -1, 0, 0);
560 ok(hmerge != NULL, "merge himl2,-1 failed\n");
561 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,-1");
562 if (hmerge) ImageList_Destroy(hmerge);
564 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
565 ok(hmerge != NULL, "merge himl2,0 failed\n");
566 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,0");
567 if (hmerge) ImageList_Destroy(hmerge);
569 /* Now try merging an image with itself */
570 ok(0==ImageList_AddIcon(himl2, hicon1),"re-add icon1 to himl2 failed\n");
572 hmerge = ImageList_Merge(himl2, 0, himl2, 0, 0, 0);
573 ok(hmerge != NULL, "merge himl2 with itself failed\n");
574 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2 with itself");
575 if (hmerge) ImageList_Destroy(hmerge);
577 /* Try merging 2 different image lists */
578 ok(0==ImageList_AddIcon(himl1, hicon1),"add icon1 to himl1 failed\n");
580 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
581 ok(hmerge != NULL, "merge himl1 with himl2 failed\n");
582 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2");
583 if (hmerge) ImageList_Destroy(hmerge);
585 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 8, 16);
586 ok(hmerge != NULL, "merge himl1 with himl2 8,16 failed\n");
587 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2, 8,16");
588 if (hmerge) ImageList_Destroy(hmerge);
590 ImageList_Destroy(himl1);
591 ImageList_Destroy(himl2);
592 DestroyIcon(hicon1);
593 DestroyWindow(hwnd);
596 /*********************** imagelist storage test ***************************/
598 #define BMP_CX 48
600 struct my_IStream
602 IStream is;
603 char *iml_data; /* written imagelist data */
604 ULONG iml_data_size;
607 static HRESULT STDMETHODCALLTYPE Test_Stream_QueryInterface(
608 IStream* This,
609 REFIID riid,
610 void** ppvObject)
612 assert(0);
613 return E_NOTIMPL;
616 static ULONG STDMETHODCALLTYPE Test_Stream_AddRef(
617 IStream* This)
619 assert(0);
620 return 2;
623 static ULONG STDMETHODCALLTYPE Test_Stream_Release(
624 IStream* This)
626 assert(0);
627 return 1;
630 static HRESULT STDMETHODCALLTYPE Test_Stream_Read(
631 IStream* This,
632 void* pv,
633 ULONG cb,
634 ULONG* pcbRead)
636 assert(0);
637 return E_NOTIMPL;
640 static BOOL allocate_storage(struct my_IStream *my_is, ULONG add)
642 my_is->iml_data_size += add;
644 if (!my_is->iml_data)
645 my_is->iml_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data_size);
646 else
647 my_is->iml_data = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data, my_is->iml_data_size);
649 return my_is->iml_data ? TRUE : FALSE;
652 static HRESULT STDMETHODCALLTYPE Test_Stream_Write(
653 IStream* This,
654 const void* pv,
655 ULONG cb,
656 ULONG* pcbWritten)
658 struct my_IStream *my_is = (struct my_IStream *)This;
659 ULONG current_iml_data_size = my_is->iml_data_size;
661 if (!allocate_storage(my_is, cb)) return E_FAIL;
663 memcpy(my_is->iml_data + current_iml_data_size, pv, cb);
664 if (pcbWritten) *pcbWritten = cb;
666 return S_OK;
669 static HRESULT STDMETHODCALLTYPE Test_Stream_Seek(
670 IStream* This,
671 LARGE_INTEGER dlibMove,
672 DWORD dwOrigin,
673 ULARGE_INTEGER* plibNewPosition)
675 assert(0);
676 return E_NOTIMPL;
679 static HRESULT STDMETHODCALLTYPE Test_Stream_SetSize(
680 IStream* This,
681 ULARGE_INTEGER libNewSize)
683 assert(0);
684 return E_NOTIMPL;
687 static HRESULT STDMETHODCALLTYPE Test_Stream_CopyTo(
688 IStream* This,
689 IStream* pstm,
690 ULARGE_INTEGER cb,
691 ULARGE_INTEGER* pcbRead,
692 ULARGE_INTEGER* pcbWritten)
694 assert(0);
695 return E_NOTIMPL;
698 static HRESULT STDMETHODCALLTYPE Test_Stream_Commit(
699 IStream* This,
700 DWORD grfCommitFlags)
702 assert(0);
703 return E_NOTIMPL;
706 static HRESULT STDMETHODCALLTYPE Test_Stream_Revert(
707 IStream* This)
709 assert(0);
710 return E_NOTIMPL;
713 static HRESULT STDMETHODCALLTYPE Test_Stream_LockRegion(
714 IStream* This,
715 ULARGE_INTEGER libOffset,
716 ULARGE_INTEGER cb,
717 DWORD dwLockType)
719 assert(0);
720 return E_NOTIMPL;
723 static HRESULT STDMETHODCALLTYPE Test_Stream_UnlockRegion(
724 IStream* This,
725 ULARGE_INTEGER libOffset,
726 ULARGE_INTEGER cb,
727 DWORD dwLockType)
729 assert(0);
730 return E_NOTIMPL;
733 static HRESULT STDMETHODCALLTYPE Test_Stream_Stat(
734 IStream* This,
735 STATSTG* pstatstg,
736 DWORD grfStatFlag)
738 assert(0);
739 return E_NOTIMPL;
742 static HRESULT STDMETHODCALLTYPE Test_Stream_Clone(
743 IStream* This,
744 IStream** ppstm)
746 assert(0);
747 return E_NOTIMPL;
750 static const IStreamVtbl Test_Stream_Vtbl =
752 Test_Stream_QueryInterface,
753 Test_Stream_AddRef,
754 Test_Stream_Release,
755 Test_Stream_Read,
756 Test_Stream_Write,
757 Test_Stream_Seek,
758 Test_Stream_SetSize,
759 Test_Stream_CopyTo,
760 Test_Stream_Commit,
761 Test_Stream_Revert,
762 Test_Stream_LockRegion,
763 Test_Stream_UnlockRegion,
764 Test_Stream_Stat,
765 Test_Stream_Clone
768 static struct my_IStream Test_Stream = { { &Test_Stream_Vtbl }, 0, 0 };
770 static INT DIB_GetWidthBytes( int width, int bpp )
772 int words;
774 switch (bpp)
776 case 1: words = (width + 31) / 32; break;
777 case 4: words = (width + 7) / 8; break;
778 case 8: words = (width + 3) / 4; break;
779 case 15:
780 case 16: words = (width + 1) / 2; break;
781 case 24: words = (width * 3 + 3)/4; break;
782 case 32: words = width; break;
784 default:
785 words=0;
786 trace("Unknown depth %d, please report.\n", bpp );
787 assert(0);
788 break;
790 return 4 * words;
793 static void check_bitmap_data(const char *bm_data, ULONG bm_data_size,
794 INT width, INT height, INT bpp,
795 const char *comment)
797 const BITMAPFILEHEADER *bmfh = (const BITMAPFILEHEADER *)bm_data;
798 const BITMAPINFOHEADER *bmih = (const BITMAPINFOHEADER *)(bm_data + sizeof(*bmfh));
799 ULONG hdr_size, image_size;
801 hdr_size = sizeof(*bmfh) + sizeof(*bmih);
802 if (bmih->biBitCount <= 8) hdr_size += (1 << bpp) * sizeof(RGBQUAD);
804 ok(bmfh->bfType == (('M' << 8) | 'B'), "wrong bfType 0x%02x\n", bmfh->bfType);
805 ok(bmfh->bfSize == hdr_size, "wrong bfSize 0x%02x\n", bmfh->bfSize);
806 ok(bmfh->bfReserved1 == 0, "wrong bfReserved1 0x%02x\n", bmfh->bfReserved1);
807 ok(bmfh->bfReserved2 == 0, "wrong bfReserved2 0x%02x\n", bmfh->bfReserved2);
808 ok(bmfh->bfOffBits == hdr_size, "wrong bfOffBits 0x%02x\n", bmfh->bfOffBits);
810 ok(bmih->biSize == sizeof(*bmih), "wrong biSize %d\n", bmih->biSize);
811 ok(bmih->biWidth == width, "wrong biWidth %d (expected %d)\n", bmih->biWidth, width);
812 ok(bmih->biHeight == height, "wrong biHeight %d (expected %d)\n", bmih->biHeight, height);
813 ok(bmih->biPlanes == 1, "wrong biPlanes %d\n", bmih->biPlanes);
814 ok(bmih->biBitCount == bpp, "wrong biBitCount %d\n", bmih->biBitCount);
816 image_size = DIB_GetWidthBytes(bmih->biWidth, bmih->biBitCount) * bmih->biHeight;
817 ok(bmih->biSizeImage == image_size, "wrong biSizeImage %u\n", bmih->biSizeImage);
818 #if 0
820 char fname[256];
821 FILE *f;
822 sprintf(fname, "bmp_%s.bmp", comment);
823 f = fopen(fname, "wb");
824 fwrite(bm_data, 1, bm_data_size, f);
825 fclose(f);
827 #endif
830 static void check_ilhead_data(const char *ilh_data, INT cx, INT cy, INT cur, INT max)
832 ILHEAD *ilh = (ILHEAD *)ilh_data;
834 ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
835 ok(ilh->usVersion == 0x101, "wrong usVersion %x (expected 0x101)\n", ilh->usVersion);
836 ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
837 ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
838 ok(ilh->cGrow == 4, "wrong cGrow %d (expected 4)\n", ilh->cGrow);
839 ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
840 ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
841 ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
842 ok(ilh->flags == ILC_COLOR24, "wrong flags %04x\n", ilh->flags);
843 ok(ilh->ovls[0] == -1 ||
844 ilh->ovls[0] == 0, /* win95 */
845 "wrong ovls[0] %04x\n", ilh->ovls[0]);
846 ok(ilh->ovls[1] == -1 ||
847 ilh->ovls[1] == 0, /* win95 */
848 "wrong ovls[1] %04x\n", ilh->ovls[1]);
849 ok(ilh->ovls[2] == -1 ||
850 ilh->ovls[2] == 0, /* win95 */
851 "wrong ovls[2] %04x\n", ilh->ovls[2]);
852 ok(ilh->ovls[3] == -1 ||
853 ilh->ovls[3] == 0, /* win95 */
854 "wrong ovls[3] %04x\n", ilh->ovls[3]);
857 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
859 HDC hdc;
860 char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
861 BITMAPINFO *bmi = (BITMAPINFO *)bmibuf;
862 HBITMAP hbmp, hbmp_old;
863 HBRUSH hbrush;
864 RECT rc = { 0, 0, cx, cy };
866 hdc = CreateCompatibleDC(0);
868 memset(bmi, 0, sizeof(*bmi));
869 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
870 bmi->bmiHeader.biHeight = cx;
871 bmi->bmiHeader.biWidth = cy;
872 bmi->bmiHeader.biBitCount = 24;
873 bmi->bmiHeader.biPlanes = 1;
874 bmi->bmiHeader.biCompression = BI_RGB;
875 hbmp = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
877 hbmp_old = SelectObject(hdc, hbmp);
879 hbrush = CreateSolidBrush(color);
880 FillRect(hdc, &rc, hbrush);
881 DeleteObject(hbrush);
883 DrawText(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
885 SelectObject(hdc, hbmp_old);
886 DeleteDC(hdc);
888 return hbmp;
891 static void image_list_init(HIMAGELIST himl)
893 HBITMAP hbm;
894 char comment[16];
895 INT n = 1;
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);
902 add_bitmap(255); add_bitmap(170); add_bitmap(85); add_bitmap(0);
903 add_bitmap(0); add_bitmap(85); add_bitmap(170); add_bitmap(255);
904 add_bitmap(255); add_bitmap(170); add_bitmap(85); add_bitmap(0);
905 add_bitmap(0); add_bitmap(85); add_bitmap(170); add_bitmap(255);
906 add_bitmap(255); add_bitmap(170); add_bitmap(85); add_bitmap(0);
907 add_bitmap(0); add_bitmap(85); add_bitmap(170); add_bitmap(255);
908 #undef add_bitmap
911 #define iml_clear_stream_data() \
912 HeapFree(GetProcessHeap(), 0, Test_Stream.iml_data); \
913 Test_Stream.iml_data = NULL; \
914 Test_Stream.iml_data_size = 0;
916 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max,
917 INT width, INT height, INT bpp, const char *comment)
919 INT ret, cxx, cyy;
921 ret = ImageList_GetImageCount(himl);
922 ok(ret == cur, "expected cur %d got %d\n", cur, ret);
924 ret = ImageList_GetIconSize(himl, &cxx, &cyy);
925 ok(ret, "ImageList_GetIconSize failed\n");
926 ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx);
927 ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy);
929 iml_clear_stream_data();
930 ret = ImageList_Write(himl, &Test_Stream.is);
931 ok(ret, "ImageList_Write failed\n");
933 ok(Test_Stream.iml_data != 0, "ImageList_Write didn't write any data\n");
934 ok(Test_Stream.iml_data_size > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n");
936 check_ilhead_data(Test_Stream.iml_data, cx, cy, cur, max);
937 check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD),
938 Test_Stream.iml_data_size - sizeof(ILHEAD),
939 width, height, bpp, comment);
942 static void test_imagelist_storage(void)
944 HIMAGELIST himl;
945 BOOL ret;
947 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
948 ok(himl != 0, "ImageList_Create failed\n");
950 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, BMP_CX * 4, BMP_CX * 1, 24, "empty");
952 image_list_init(himl);
953 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, BMP_CX * 4, BMP_CX * 7, 24, "orig");
955 ret = ImageList_Remove(himl, 4);
956 ok(ret, "ImageList_Remove failed\n");
957 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, BMP_CX * 4, BMP_CX * 7, 24, "1");
959 ret = ImageList_Remove(himl, 5);
960 ok(ret, "ImageList_Remove failed\n");
961 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, BMP_CX * 4, BMP_CX * 7, 24, "2");
963 ret = ImageList_Remove(himl, 6);
964 ok(ret, "ImageList_Remove failed\n");
965 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, BMP_CX * 4, BMP_CX * 7, 24, "3");
967 ret = ImageList_Remove(himl, 7);
968 ok(ret, "ImageList_Remove failed\n");
969 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, BMP_CX * 4, BMP_CX * 7, 24, "4");
971 ret = ImageList_Remove(himl, -2);
972 ok(!ret, "ImageList_Remove(-2) should fail\n");
973 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, BMP_CX * 4, BMP_CX * 7, 24, "5");
975 ret = ImageList_Remove(himl, 20);
976 ok(!ret, "ImageList_Remove(20) should fail\n");
977 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, BMP_CX * 4, BMP_CX * 7, 24, "6");
979 ret = ImageList_Remove(himl, -1);
980 ok(ret, "ImageList_Remove(-1) failed\n");
981 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, BMP_CX * 4, BMP_CX * 1, 24, "7");
983 ret = ImageList_Destroy(himl);
984 ok(ret, "ImageList_Destroy failed\n");
986 iml_clear_stream_data();
989 static void test_shell_imagelist(void)
991 BOOL (WINAPI *pSHGetImageList)(INT, REFIID, void**);
992 IImageList *iml = NULL;
993 HMODULE hShell32;
994 HRESULT hr;
995 int out = 0;
996 RECT rect;
998 /* Try to load function from shell32 */
999 hShell32 = LoadLibrary("shell32.dll");
1000 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1002 if (!pSHGetImageList)
1004 win_skip("SHGetImageList not available, skipping test\n");
1005 return;
1008 /* Get system image list */
1009 hr = (pSHGetImageList)(SHIL_LARGE, &IID_IImageList, (void**)&iml);
1011 todo_wine ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1013 if (hr != S_OK)
1014 return;
1016 IImageList_GetImageCount(iml, &out);
1017 todo_wine ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1019 /* right and bottom should be 32x32 for large icons, or 48x48 if larger
1020 icons enabled in control panel */
1021 IImageList_GetImageRect(iml, 0, &rect);
1022 todo_wine ok((((rect.right == 32) && (rect.bottom == 32)) ||
1023 ((rect.right == 48) && (rect.bottom == 48))),
1024 "IImageList_GetImageRect returned r:%d,b:%d\n",
1025 rect.right, rect.bottom);
1027 IImageList_Release(iml);
1028 FreeLibrary(hShell32);
1031 START_TEST(imagelist)
1033 ULONG_PTR ctx_cookie;
1035 HMODULE hComCtl32 = GetModuleHandle("comctl32.dll");
1036 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1037 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1039 desktopDC=GetDC(NULL);
1040 hinst = GetModuleHandleA(NULL);
1042 InitCommonControls();
1044 testHotspot();
1045 DoTest1();
1046 DoTest2();
1047 DoTest3();
1048 testMerge();
1049 test_imagelist_storage();
1051 /* Now perform v6 tests */
1053 if (!load_v6_module(&ctx_cookie))
1054 return;
1056 test_shell_imagelist();
1058 unload_v6_module(ctx_cookie);