push 8b07bf1f08b23b9893a622b47d2be359556765b1
[wine/hacks.git] / dlls / comctl32 / tests / imagelist.c
blobda3da42a41febb6e865d665cd741abe34b7ba299
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);
78 static HDC desktopDC;
79 static HINSTANCE hinst;
81 /* These macros build cursor/bitmap data in 4x4 pixel blocks */
82 #define B(x,y) ((x?0xf0:0)|(y?0xf:0))
83 #define ROW1(a,b,c,d,e,f,g,h) B(a,b),B(c,d),B(e,f),B(g,h)
84 #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), \
85 ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h)
86 #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)
87 #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), \
88 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), \
89 ROW2(a,b,c,d,e,f,g,h,i,j,k,l)
91 static const BYTE empty_bits[48*48/8];
93 static const BYTE icon_bits[32*32/8] =
95 ROW32(0,0,0,0,0,0,0,0),
96 ROW32(0,0,1,1,1,1,0,0),
97 ROW32(0,1,1,1,1,1,1,0),
98 ROW32(0,1,1,0,0,1,1,0),
99 ROW32(0,1,1,0,0,1,1,0),
100 ROW32(0,1,1,1,1,1,1,0),
101 ROW32(0,0,1,1,1,1,0,0),
102 ROW32(0,0,0,0,0,0,0,0)
105 static const BYTE bitmap_bits[48*48/8] =
107 ROW48(0,0,0,0,0,0,0,0,0,0,0,0),
108 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
109 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
110 ROW48(0,1,0,0,0,0,0,0,1,0,1,0),
111 ROW48(0,1,0,0,0,0,0,1,0,0,1,0),
112 ROW48(0,1,0,0,0,0,1,0,0,0,1,0),
113 ROW48(0,1,0,0,0,1,0,0,0,0,1,0),
114 ROW48(0,1,0,0,1,0,0,0,0,0,1,0),
115 ROW48(0,1,0,1,0,0,0,0,0,0,1,0),
116 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
117 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
118 ROW48(0,0,0,0,0,0,0,0,0,0,0,0)
121 static HIMAGELIST createImageList(int cx, int cy)
123 /* Create an ImageList and put an image into it */
124 HIMAGELIST himl = ImageList_Create(cx, cy, ILC_COLOR, 1, 1);
125 HBITMAP hbm = CreateBitmap(48, 48, 1, 1, bitmap_bits);
126 ImageList_Add(himl, hbm, NULL);
127 return himl;
130 static HWND create_a_window(void)
132 char className[] = "bmwnd";
133 char winName[] = "Test Bitmap";
134 HWND hWnd;
135 static int registered = 0;
137 if (!registered)
139 WNDCLASSA cls;
141 cls.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
142 cls.lpfnWndProc = DefWindowProcA;
143 cls.cbClsExtra = 0;
144 cls.cbWndExtra = 0;
145 cls.hInstance = 0;
146 cls.hIcon = LoadIconA (0, IDI_APPLICATION);
147 cls.hCursor = LoadCursorA (0, IDC_ARROW);
148 cls.hbrBackground = GetStockObject (WHITE_BRUSH);
149 cls.lpszMenuName = 0;
150 cls.lpszClassName = className;
152 RegisterClassA (&cls);
153 registered = 1;
156 /* Setup window */
157 hWnd = CreateWindowA (className, winName,
158 WS_OVERLAPPEDWINDOW ,
159 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
160 0, hinst, 0);
162 #ifdef VISIBLE
163 ShowWindow (hWnd, SW_SHOW);
164 #endif
165 REDRAW(hWnd);
166 WAIT;
168 return hWnd;
171 static HDC show_image(HWND hwnd, HIMAGELIST himl, int idx, int size,
172 LPCSTR loc, BOOL clear)
174 HDC hdc = NULL;
175 #ifdef VISIBLE
176 if (!himl) return NULL;
178 SetWindowText(hwnd, loc);
179 hdc = GetDC(hwnd);
180 ImageList_Draw(himl, idx, hdc, 0, 0, ILD_TRANSPARENT);
182 REDRAW(hwnd);
183 WAIT;
185 if (clear)
187 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
188 ReleaseDC(hwnd, hdc);
189 hdc = NULL;
191 #endif /* VISIBLE */
192 return hdc;
195 /* Useful for checking differences */
196 #if 0
197 static void dump_bits(const BYTE *p, const BYTE *q, int size)
199 int i, j;
201 size /= 8;
203 for (i = 0; i < size * 2; i++)
205 printf("|");
206 for (j = 0; j < size; j++)
207 printf("%c%c", p[j] & 0xf0 ? 'X' : ' ', p[j] & 0xf ? 'X' : ' ');
208 printf(" -- ");
209 for (j = 0; j < size; j++)
210 printf("%c%c", q[j] & 0xf0 ? 'X' : ' ', q[j] & 0xf ? 'X' : ' ');
211 printf("|\n");
212 p += size * 4;
213 q += size * 4;
215 printf("\n");
217 #endif
219 static void check_bits(HWND hwnd, HIMAGELIST himl, int idx, int size,
220 const BYTE *checkbits, LPCSTR loc)
222 #ifdef VISIBLE
223 BYTE bits[100*100/8];
224 COLORREF c;
225 HDC hdc;
226 int x, y, i = -1;
228 if (!himl) return;
230 memset(bits, 0, sizeof(bits));
231 hdc = show_image(hwnd, himl, idx, size, loc, FALSE);
233 c = GetPixel(hdc, 0, 0);
235 for (y = 0; y < size; y ++)
237 for (x = 0; x < size; x++)
239 if (!(x & 0x7)) i++;
240 if (GetPixel(hdc, x, y) != c) bits[i] |= (0x80 >> (x & 0x7));
244 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
245 ReleaseDC(hwnd, hdc);
247 ok (memcmp(bits, checkbits, (size * size)/8) == 0,
248 "%s: bits different\n", loc);
249 if (memcmp(bits, checkbits, (size * size)/8))
250 dump_bits(bits, checkbits, size);
251 #endif /* VISIBLE */
254 static void testHotspot (void)
256 struct hotspot {
257 int dx;
258 int dy;
261 #define SIZEX1 47
262 #define SIZEY1 31
263 #define SIZEX2 11
264 #define SIZEY2 17
265 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
266 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
267 { 10, 7 },
268 { SIZEX1, SIZEY1 },
269 { -9, -8 },
270 { -7, 35 }
272 int i, j, ret;
273 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
274 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
275 HWND hwnd = create_a_window();
278 for (i = 0; i < HOTSPOTS_MAX; i++) {
279 for (j = 0; j < HOTSPOTS_MAX; j++) {
280 int dx1 = hotspots[i].dx;
281 int dy1 = hotspots[i].dy;
282 int dx2 = hotspots[j].dx;
283 int dy2 = hotspots[j].dy;
284 int correctx, correcty, newx, newy;
285 char loc[256];
286 HIMAGELIST himlNew;
287 POINT ppt;
289 ret = ImageList_BeginDrag(himl1, 0, dx1, dy1);
290 ok(ret != 0, "BeginDrag failed for { %d, %d }\n", dx1, dy1);
291 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
292 show_image(hwnd, himl1, 0, max(SIZEX1, SIZEY1), loc, TRUE);
294 /* check merging the dragged image with a second image */
295 ret = ImageList_SetDragCursorImage(himl2, 0, dx2, dy2);
296 ok(ret != 0, "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
297 dx1, dy1, dx2, dy2);
298 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
299 show_image(hwnd, himl2, 0, max(SIZEX2, SIZEY2), loc, TRUE);
301 /* check new hotspot, it should be the same like the old one */
302 himlNew = ImageList_GetDragImage(NULL, &ppt);
303 ok(ppt.x == dx1 && ppt.y == dy1,
304 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
305 dx1, dy1, ppt.x, ppt.y);
306 /* check size of new dragged image */
307 ImageList_GetIconSize(himlNew, &newx, &newy);
308 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
309 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
310 ok(newx == correctx && newy == correcty,
311 "Expected drag image size [%d,%d] got [%d,%d]\n",
312 correctx, correcty, newx, newy);
313 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
314 show_image(hwnd, himlNew, 0, max(correctx, correcty), loc, TRUE);
315 ImageList_EndDrag();
318 #undef SIZEX1
319 #undef SIZEY1
320 #undef SIZEX2
321 #undef SIZEY2
322 #undef HOTSPOTS_MAX
323 ImageList_Destroy(himl2);
324 ImageList_Destroy(himl1);
325 DestroyWindow(hwnd);
328 static BOOL DoTest1(void)
330 HIMAGELIST himl ;
332 HICON hicon1 ;
333 HICON hicon2 ;
334 HICON hicon3 ;
336 /* create an imagelist to play with */
337 himl = ImageList_Create(84,84,0x10,0,3);
338 ok(himl!=0,"failed to create imagelist\n");
340 /* load the icons to add to the image list */
341 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
342 ok(hicon1 != 0, "no hicon1\n");
343 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
344 ok(hicon2 != 0, "no hicon2\n");
345 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
346 ok(hicon3 != 0, "no hicon3\n");
348 /* remove when nothing exists */
349 ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
350 /* removing everything from an empty imagelist should succeed */
351 ok(ImageList_RemoveAll(himl),"removed nonexistent icon\n");
353 /* add three */
354 ok(0==ImageList_AddIcon(himl, hicon1),"failed to add icon1\n");
355 ok(1==ImageList_AddIcon(himl, hicon2),"failed to add icon2\n");
356 ok(2==ImageList_AddIcon(himl, hicon3),"failed to add icon3\n");
358 /* remove an index out of range */
359 ok(!ImageList_Remove(himl,4711),"removed nonexistent icon\n");
361 /* remove three */
362 ok(ImageList_Remove(himl,0),"can't remove 0\n");
363 ok(ImageList_Remove(himl,0),"can't remove 0\n");
364 ok(ImageList_Remove(himl,0),"can't remove 0\n");
366 /* remove one extra */
367 ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
369 /* check SetImageCount/GetImageCount */
370 if (pImageList_SetImageCount)
372 ok(pImageList_SetImageCount(himl, 3), "couldn't increase image count\n");
373 ok(ImageList_GetImageCount(himl) == 3, "invalid image count after increase\n");
374 ok(pImageList_SetImageCount(himl, 1), "couldn't decrease image count\n");
375 ok(ImageList_GetImageCount(himl) == 1, "invalid image count after decrease to 1\n");
376 ok(pImageList_SetImageCount(himl, 0), "couldn't decrease image count\n");
377 ok(ImageList_GetImageCount(himl) == 0, "invalid image count after decrease to 0\n");
379 else
381 skip("skipped ImageList_SetImageCount tests\n");
384 /* destroy it */
385 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
387 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
388 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
389 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
391 return TRUE;
394 static BOOL DoTest2(void)
396 HIMAGELIST himl ;
398 HICON hicon1 ;
399 HICON hicon2 ;
400 HICON hicon3 ;
402 /* create an imagelist to play with */
403 himl = ImageList_Create(84,84,0x10,0,3);
404 ok(himl!=0,"failed to create imagelist\n");
406 /* load the icons to add to the image list */
407 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
408 ok(hicon1 != 0, "no hicon1\n");
409 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
410 ok(hicon2 != 0, "no hicon2\n");
411 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
412 ok(hicon3 != 0, "no hicon3\n");
414 /* add three */
415 ok(0==ImageList_AddIcon(himl, hicon1),"failed to add icon1\n");
416 ok(1==ImageList_AddIcon(himl, hicon2),"failed to add icon2\n");
417 ok(2==ImageList_AddIcon(himl, hicon3),"failed to add icon3\n");
419 /* destroy it */
420 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
422 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
423 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
424 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
426 return TRUE;
429 static BOOL DoTest3(void)
431 HIMAGELIST himl;
433 HBITMAP hbm1;
434 HBITMAP hbm2;
435 HBITMAP hbm3;
437 IMAGELISTDRAWPARAMS imldp;
438 HDC hdc;
439 HWND hwndfortest;
441 if (!pImageList_DrawIndirect)
443 win_skip("ImageList_DrawIndirect not available, skipping test\n");
444 return TRUE;
447 hwndfortest = create_a_window();
448 hdc = GetDC(hwndfortest);
449 ok(hdc!=NULL, "couldn't get DC\n");
451 /* create an imagelist to play with */
452 himl = ImageList_Create(48,48,0x10,0,3);
453 ok(himl!=0,"failed to create imagelist\n");
455 /* load the icons to add to the image list */
456 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
457 ok(hbm1 != 0, "no bitmap 1\n");
458 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
459 ok(hbm2 != 0, "no bitmap 2\n");
460 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
461 ok(hbm3 != 0, "no bitmap 3\n");
463 /* add three */
464 ok(0==ImageList_Add(himl, hbm1, 0),"failed to add bitmap 1\n");
465 ok(1==ImageList_Add(himl, hbm2, 0),"failed to add bitmap 2\n");
467 if (pImageList_SetImageCount)
469 ok(pImageList_SetImageCount(himl,3),"Setimage count failed\n");
470 /*ok(2==ImageList_Add(himl, hbm3, NULL),"failed to add bitmap 3\n"); */
471 ok(ImageList_Replace(himl, 2, hbm3, 0),"failed to replace bitmap 3\n");
474 memset(&imldp, 0, sizeof (imldp));
475 ok(!pImageList_DrawIndirect(&imldp), "zero data succeeded!\n");
476 imldp.cbSize = sizeof (imldp);
477 ok(!pImageList_DrawIndirect(&imldp), "zero hdc succeeded!\n");
478 imldp.hdcDst = hdc;
479 ok(!pImageList_DrawIndirect(&imldp),"zero himl succeeded!\n");
480 imldp.himl = himl;
481 if (!pImageList_DrawIndirect(&imldp))
483 /* Earlier versions of native comctl32 use a smaller structure */
484 imldp.cbSize -= 3 * sizeof(DWORD);
485 ok(pImageList_DrawIndirect(&imldp),"DrawIndirect should succeed\n");
487 REDRAW(hwndfortest);
488 WAIT;
490 imldp.fStyle = SRCCOPY;
491 imldp.rgbBk = CLR_DEFAULT;
492 imldp.rgbFg = CLR_DEFAULT;
493 imldp.y = 100;
494 imldp.x = 100;
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 succeed\n");
500 imldp.i ++;
501 ok(!pImageList_DrawIndirect(&imldp),"should fail\n");
503 /* remove three */
504 ok(ImageList_Remove(himl, 0), "removing 1st bitmap\n");
505 ok(ImageList_Remove(himl, 0), "removing 2nd bitmap\n");
506 ok(ImageList_Remove(himl, 0), "removing 3rd bitmap\n");
508 /* destroy it */
509 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
511 /* bitmaps should not be deleted by the imagelist */
512 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
513 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
514 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
516 ReleaseDC(hwndfortest, hdc);
517 DestroyWindow(hwndfortest);
519 return TRUE;
522 static void testMerge(void)
524 HIMAGELIST himl1, himl2, hmerge;
525 HICON hicon1;
526 HWND hwnd = create_a_window();
528 himl1 = ImageList_Create(32,32,0,0,3);
529 ok(himl1 != NULL,"failed to create himl1\n");
531 himl2 = ImageList_Create(32,32,0,0,3);
532 ok(himl2 != NULL,"failed to create himl2\n");
534 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
535 ok(hicon1 != NULL, "failed to create hicon1\n");
537 if (!himl1 || !himl2 || !hicon1)
538 return;
540 ok(0==ImageList_AddIcon(himl2, hicon1),"add icon1 to himl2 failed\n");
541 check_bits(hwnd, himl2, 0, 32, icon_bits, "add icon1 to himl2");
543 /* If himl1 has no images, merge still succeeds */
544 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
545 ok(hmerge != NULL, "merge himl1,-1 failed\n");
546 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,-1");
547 if (hmerge) ImageList_Destroy(hmerge);
549 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
550 ok(hmerge != NULL,"merge himl1,0 failed\n");
551 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,0");
552 if (hmerge) ImageList_Destroy(hmerge);
554 /* Same happens if himl2 is empty */
555 ImageList_Destroy(himl2);
556 himl2 = ImageList_Create(32,32,0,0,3);
557 ok(himl2 != NULL,"failed to recreate himl2\n");
558 if (!himl2)
559 return;
561 hmerge = ImageList_Merge(himl1, -1, himl2, -1, 0, 0);
562 ok(hmerge != NULL, "merge himl2,-1 failed\n");
563 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,-1");
564 if (hmerge) ImageList_Destroy(hmerge);
566 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
567 ok(hmerge != NULL, "merge himl2,0 failed\n");
568 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,0");
569 if (hmerge) ImageList_Destroy(hmerge);
571 /* Now try merging an image with itself */
572 ok(0==ImageList_AddIcon(himl2, hicon1),"re-add icon1 to himl2 failed\n");
574 hmerge = ImageList_Merge(himl2, 0, himl2, 0, 0, 0);
575 ok(hmerge != NULL, "merge himl2 with itself failed\n");
576 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2 with itself");
577 if (hmerge) ImageList_Destroy(hmerge);
579 /* Try merging 2 different image lists */
580 ok(0==ImageList_AddIcon(himl1, hicon1),"add icon1 to himl1 failed\n");
582 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
583 ok(hmerge != NULL, "merge himl1 with himl2 failed\n");
584 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2");
585 if (hmerge) ImageList_Destroy(hmerge);
587 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 8, 16);
588 ok(hmerge != NULL, "merge himl1 with himl2 8,16 failed\n");
589 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2, 8,16");
590 if (hmerge) ImageList_Destroy(hmerge);
592 ImageList_Destroy(himl1);
593 ImageList_Destroy(himl2);
594 DestroyIcon(hicon1);
595 DestroyWindow(hwnd);
598 /*********************** imagelist storage test ***************************/
600 #define BMP_CX 48
602 struct my_IStream
604 IStream is;
605 char *iml_data; /* written imagelist data */
606 ULONG iml_data_size;
609 static HRESULT STDMETHODCALLTYPE Test_Stream_QueryInterface(
610 IStream* This,
611 REFIID riid,
612 void** ppvObject)
614 assert(0);
615 return E_NOTIMPL;
618 static ULONG STDMETHODCALLTYPE Test_Stream_AddRef(
619 IStream* This)
621 assert(0);
622 return 2;
625 static ULONG STDMETHODCALLTYPE Test_Stream_Release(
626 IStream* This)
628 assert(0);
629 return 1;
632 static HRESULT STDMETHODCALLTYPE Test_Stream_Read(
633 IStream* This,
634 void* pv,
635 ULONG cb,
636 ULONG* pcbRead)
638 assert(0);
639 return E_NOTIMPL;
642 static BOOL allocate_storage(struct my_IStream *my_is, ULONG add)
644 my_is->iml_data_size += add;
646 if (!my_is->iml_data)
647 my_is->iml_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data_size);
648 else
649 my_is->iml_data = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data, my_is->iml_data_size);
651 return my_is->iml_data ? TRUE : FALSE;
654 static HRESULT STDMETHODCALLTYPE Test_Stream_Write(
655 IStream* This,
656 const void* pv,
657 ULONG cb,
658 ULONG* pcbWritten)
660 struct my_IStream *my_is = (struct my_IStream *)This;
661 ULONG current_iml_data_size = my_is->iml_data_size;
663 if (!allocate_storage(my_is, cb)) return E_FAIL;
665 memcpy(my_is->iml_data + current_iml_data_size, pv, cb);
666 if (pcbWritten) *pcbWritten = cb;
668 return S_OK;
671 static HRESULT STDMETHODCALLTYPE Test_Stream_Seek(
672 IStream* This,
673 LARGE_INTEGER dlibMove,
674 DWORD dwOrigin,
675 ULARGE_INTEGER* plibNewPosition)
677 assert(0);
678 return E_NOTIMPL;
681 static HRESULT STDMETHODCALLTYPE Test_Stream_SetSize(
682 IStream* This,
683 ULARGE_INTEGER libNewSize)
685 assert(0);
686 return E_NOTIMPL;
689 static HRESULT STDMETHODCALLTYPE Test_Stream_CopyTo(
690 IStream* This,
691 IStream* pstm,
692 ULARGE_INTEGER cb,
693 ULARGE_INTEGER* pcbRead,
694 ULARGE_INTEGER* pcbWritten)
696 assert(0);
697 return E_NOTIMPL;
700 static HRESULT STDMETHODCALLTYPE Test_Stream_Commit(
701 IStream* This,
702 DWORD grfCommitFlags)
704 assert(0);
705 return E_NOTIMPL;
708 static HRESULT STDMETHODCALLTYPE Test_Stream_Revert(
709 IStream* This)
711 assert(0);
712 return E_NOTIMPL;
715 static HRESULT STDMETHODCALLTYPE Test_Stream_LockRegion(
716 IStream* This,
717 ULARGE_INTEGER libOffset,
718 ULARGE_INTEGER cb,
719 DWORD dwLockType)
721 assert(0);
722 return E_NOTIMPL;
725 static HRESULT STDMETHODCALLTYPE Test_Stream_UnlockRegion(
726 IStream* This,
727 ULARGE_INTEGER libOffset,
728 ULARGE_INTEGER cb,
729 DWORD dwLockType)
731 assert(0);
732 return E_NOTIMPL;
735 static HRESULT STDMETHODCALLTYPE Test_Stream_Stat(
736 IStream* This,
737 STATSTG* pstatstg,
738 DWORD grfStatFlag)
740 assert(0);
741 return E_NOTIMPL;
744 static HRESULT STDMETHODCALLTYPE Test_Stream_Clone(
745 IStream* This,
746 IStream** ppstm)
748 assert(0);
749 return E_NOTIMPL;
752 static const IStreamVtbl Test_Stream_Vtbl =
754 Test_Stream_QueryInterface,
755 Test_Stream_AddRef,
756 Test_Stream_Release,
757 Test_Stream_Read,
758 Test_Stream_Write,
759 Test_Stream_Seek,
760 Test_Stream_SetSize,
761 Test_Stream_CopyTo,
762 Test_Stream_Commit,
763 Test_Stream_Revert,
764 Test_Stream_LockRegion,
765 Test_Stream_UnlockRegion,
766 Test_Stream_Stat,
767 Test_Stream_Clone
770 static struct my_IStream Test_Stream = { { &Test_Stream_Vtbl }, 0, 0 };
772 static INT DIB_GetWidthBytes( int width, int bpp )
774 int words;
776 switch (bpp)
778 case 1: words = (width + 31) / 32; break;
779 case 4: words = (width + 7) / 8; break;
780 case 8: words = (width + 3) / 4; break;
781 case 15:
782 case 16: words = (width + 1) / 2; break;
783 case 24: words = (width * 3 + 3)/4; break;
784 case 32: words = width; break;
786 default:
787 words=0;
788 trace("Unknown depth %d, please report.\n", bpp );
789 assert(0);
790 break;
792 return 4 * words;
795 static void check_bitmap_data(const char *bm_data, ULONG bm_data_size,
796 INT width, INT height, INT bpp,
797 const char *comment)
799 const BITMAPFILEHEADER *bmfh = (const BITMAPFILEHEADER *)bm_data;
800 const BITMAPINFOHEADER *bmih = (const BITMAPINFOHEADER *)(bm_data + sizeof(*bmfh));
801 ULONG hdr_size, image_size;
803 hdr_size = sizeof(*bmfh) + sizeof(*bmih);
804 if (bmih->biBitCount <= 8) hdr_size += (1 << bpp) * sizeof(RGBQUAD);
806 ok(bmfh->bfType == (('M' << 8) | 'B'), "wrong bfType 0x%02x\n", bmfh->bfType);
807 ok(bmfh->bfSize == hdr_size, "wrong bfSize 0x%02x\n", bmfh->bfSize);
808 ok(bmfh->bfReserved1 == 0, "wrong bfReserved1 0x%02x\n", bmfh->bfReserved1);
809 ok(bmfh->bfReserved2 == 0, "wrong bfReserved2 0x%02x\n", bmfh->bfReserved2);
810 ok(bmfh->bfOffBits == hdr_size, "wrong bfOffBits 0x%02x\n", bmfh->bfOffBits);
812 ok(bmih->biSize == sizeof(*bmih), "wrong biSize %d\n", bmih->biSize);
813 ok(bmih->biWidth == width, "wrong biWidth %d (expected %d)\n", bmih->biWidth, width);
814 ok(bmih->biHeight == height, "wrong biHeight %d (expected %d)\n", bmih->biHeight, height);
815 ok(bmih->biPlanes == 1, "wrong biPlanes %d\n", bmih->biPlanes);
816 ok(bmih->biBitCount == bpp, "wrong biBitCount %d\n", bmih->biBitCount);
818 image_size = DIB_GetWidthBytes(bmih->biWidth, bmih->biBitCount) * bmih->biHeight;
819 ok(bmih->biSizeImage == image_size, "wrong biSizeImage %u\n", bmih->biSizeImage);
820 #if 0
822 char fname[256];
823 FILE *f;
824 sprintf(fname, "bmp_%s.bmp", comment);
825 f = fopen(fname, "wb");
826 fwrite(bm_data, 1, bm_data_size, f);
827 fclose(f);
829 #endif
832 static void check_ilhead_data(const char *ilh_data, INT cx, INT cy, INT cur, INT max)
834 ILHEAD *ilh = (ILHEAD *)ilh_data;
836 ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
837 ok(ilh->usVersion == 0x101, "wrong usVersion %x (expected 0x101)\n", ilh->usVersion);
838 ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
839 ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
840 ok(ilh->cGrow == 4, "wrong cGrow %d (expected 4)\n", ilh->cGrow);
841 ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
842 ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
843 ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
844 ok(ilh->flags == ILC_COLOR24, "wrong flags %04x\n", ilh->flags);
845 ok(ilh->ovls[0] == -1 ||
846 ilh->ovls[0] == 0, /* win95 */
847 "wrong ovls[0] %04x\n", ilh->ovls[0]);
848 ok(ilh->ovls[1] == -1 ||
849 ilh->ovls[1] == 0, /* win95 */
850 "wrong ovls[1] %04x\n", ilh->ovls[1]);
851 ok(ilh->ovls[2] == -1 ||
852 ilh->ovls[2] == 0, /* win95 */
853 "wrong ovls[2] %04x\n", ilh->ovls[2]);
854 ok(ilh->ovls[3] == -1 ||
855 ilh->ovls[3] == 0, /* win95 */
856 "wrong ovls[3] %04x\n", ilh->ovls[3]);
859 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
861 HDC hdc;
862 char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
863 BITMAPINFO *bmi = (BITMAPINFO *)bmibuf;
864 HBITMAP hbmp, hbmp_old;
865 HBRUSH hbrush;
866 RECT rc = { 0, 0, cx, cy };
868 hdc = CreateCompatibleDC(0);
870 memset(bmi, 0, sizeof(*bmi));
871 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
872 bmi->bmiHeader.biHeight = cx;
873 bmi->bmiHeader.biWidth = cy;
874 bmi->bmiHeader.biBitCount = 24;
875 bmi->bmiHeader.biPlanes = 1;
876 bmi->bmiHeader.biCompression = BI_RGB;
877 hbmp = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
879 hbmp_old = SelectObject(hdc, hbmp);
881 hbrush = CreateSolidBrush(color);
882 FillRect(hdc, &rc, hbrush);
883 DeleteObject(hbrush);
885 DrawText(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
887 SelectObject(hdc, hbmp_old);
888 DeleteDC(hdc);
890 return hbmp;
893 static void image_list_init(HIMAGELIST himl)
895 HBITMAP hbm;
896 char comment[16];
897 INT n = 1;
899 #define add_bitmap(grey) \
900 sprintf(comment, "%d", n++); \
901 hbm = create_bitmap(BMP_CX, BMP_CX, RGB((grey),(grey),(grey)), comment); \
902 ImageList_Add(himl, hbm, NULL);
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 add_bitmap(255); add_bitmap(170); add_bitmap(85); add_bitmap(0);
909 add_bitmap(0); add_bitmap(85); add_bitmap(170); add_bitmap(255);
910 #undef add_bitmap
913 #define iml_clear_stream_data() \
914 HeapFree(GetProcessHeap(), 0, Test_Stream.iml_data); \
915 Test_Stream.iml_data = NULL; \
916 Test_Stream.iml_data_size = 0;
918 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max,
919 INT width, INT height, INT bpp, const char *comment)
921 INT ret, cxx, cyy;
923 ret = ImageList_GetImageCount(himl);
924 ok(ret == cur, "expected cur %d got %d\n", cur, ret);
926 ret = ImageList_GetIconSize(himl, &cxx, &cyy);
927 ok(ret, "ImageList_GetIconSize failed\n");
928 ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx);
929 ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy);
931 iml_clear_stream_data();
932 ret = ImageList_Write(himl, &Test_Stream.is);
933 ok(ret, "ImageList_Write failed\n");
935 ok(Test_Stream.iml_data != 0, "ImageList_Write didn't write any data\n");
936 ok(Test_Stream.iml_data_size > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n");
938 check_ilhead_data(Test_Stream.iml_data, cx, cy, cur, max);
939 check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD),
940 Test_Stream.iml_data_size - sizeof(ILHEAD),
941 width, height, bpp, comment);
944 static void test_imagelist_storage(void)
946 HIMAGELIST himl;
947 BOOL ret;
949 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
950 ok(himl != 0, "ImageList_Create failed\n");
952 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, BMP_CX * 4, BMP_CX * 1, 24, "empty");
954 image_list_init(himl);
955 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, BMP_CX * 4, BMP_CX * 7, 24, "orig");
957 ret = ImageList_Remove(himl, 4);
958 ok(ret, "ImageList_Remove failed\n");
959 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, BMP_CX * 4, BMP_CX * 7, 24, "1");
961 ret = ImageList_Remove(himl, 5);
962 ok(ret, "ImageList_Remove failed\n");
963 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, BMP_CX * 4, BMP_CX * 7, 24, "2");
965 ret = ImageList_Remove(himl, 6);
966 ok(ret, "ImageList_Remove failed\n");
967 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, BMP_CX * 4, BMP_CX * 7, 24, "3");
969 ret = ImageList_Remove(himl, 7);
970 ok(ret, "ImageList_Remove failed\n");
971 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, BMP_CX * 4, BMP_CX * 7, 24, "4");
973 ret = ImageList_Remove(himl, -2);
974 ok(!ret, "ImageList_Remove(-2) should fail\n");
975 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, BMP_CX * 4, BMP_CX * 7, 24, "5");
977 ret = ImageList_Remove(himl, 20);
978 ok(!ret, "ImageList_Remove(20) should fail\n");
979 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, BMP_CX * 4, BMP_CX * 7, 24, "6");
981 ret = ImageList_Remove(himl, -1);
982 ok(ret, "ImageList_Remove(-1) failed\n");
983 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, BMP_CX * 4, BMP_CX * 1, 24, "7");
985 ret = ImageList_Destroy(himl);
986 ok(ret, "ImageList_Destroy failed\n");
988 iml_clear_stream_data();
991 static void test_shell_imagelist(void)
993 BOOL (WINAPI *pSHGetImageList)(INT, REFIID, void**);
994 IImageList *iml = NULL;
995 HMODULE hShell32;
996 HRESULT hr;
997 int out = 0;
998 RECT rect;
1000 /* Try to load function from shell32 */
1001 hShell32 = LoadLibrary("shell32.dll");
1002 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1004 if (!pSHGetImageList)
1006 win_skip("SHGetImageList not available, skipping test\n");
1007 return;
1010 /* Get system image list */
1011 hr = (pSHGetImageList)(SHIL_LARGE, &IID_IImageList, (void**)&iml);
1013 todo_wine ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1015 if (hr != S_OK)
1016 return;
1018 IImageList_GetImageCount(iml, &out);
1019 todo_wine ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1021 /* right and bottom should be 32x32 for large icons, or 48x48 if larger
1022 icons enabled in control panel */
1023 IImageList_GetImageRect(iml, 0, &rect);
1024 todo_wine ok((((rect.right == 32) && (rect.bottom == 32)) ||
1025 ((rect.right == 48) && (rect.bottom == 48))),
1026 "IImageList_GetImageRect returned r:%d,b:%d\n",
1027 rect.right, rect.bottom);
1029 IImageList_Release(iml);
1030 FreeLibrary(hShell32);
1033 static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
1035 HBITMAP hBitmap;
1036 UINT32 *buffer = NULL;
1037 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
1038 0, 0, 0, 0, 0}};
1040 hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1041 ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1043 if(!hBitmap || !buffer)
1045 DeleteObject(hBitmap);
1046 return NULL;
1049 buffer[0] = pixel1;
1050 buffer[1] = pixel2;
1052 return hBitmap;
1055 static BOOL colour_match(UINT32 x, UINT32 y)
1057 const INT32 tolerance = 8;
1059 const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1060 const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1061 const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1063 return (dr <= tolerance && dg <= tolerance && db <= tolerance);
1066 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1067 UINT32 expected, int line)
1069 bits[0] = 0x00FFFFFF;
1070 pImageList_DrawIndirect(ildp);
1071 ok(colour_match(bits[0], expected),
1072 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1073 bits[0] & 0x00FFFFFF, expected, line);
1077 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1078 UINT fStyle, UINT32 expected, int line)
1080 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1081 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1082 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1085 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1086 DWORD dwRop, UINT32 expected, int line)
1088 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1089 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1090 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1093 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1094 UINT fState, DWORD Frame, UINT32 expected, int line)
1096 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1097 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1098 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1101 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1102 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1103 UINT32 broken_expected, int line)
1105 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1106 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1107 bits[0] = 0x00FFFFFF;
1108 pImageList_DrawIndirect(&ildp);
1109 ok(colour_match(bits[0], expected) ||
1110 broken(colour_match(bits[0], broken_expected)),
1111 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1112 bits[0] & 0x00FFFFFF, expected, line);
1115 static void test_ImageList_DrawIndirect(void)
1117 HIMAGELIST himl = NULL;
1118 int ret;
1119 HDC hdcDst = NULL;
1120 HBITMAP hbmOld = NULL, hbmDst = NULL;
1121 HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1122 HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
1123 int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1124 UINT32 *bits = 0;
1125 UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1127 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1128 0, 0, 0, 0, 0}};
1130 hdcDst = CreateCompatibleDC(0);
1131 ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1132 if (!hdcDst)
1133 return;
1135 hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1136 ok(hbmMask != 0, "CreateBitmap failed\n");
1137 if(!hbmMask) goto cleanup;
1139 hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1140 ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1141 if(!hbmInverseMask) goto cleanup;
1143 himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1144 ok(himl != 0, "ImageList_Create failed\n");
1145 if(!himl) goto cleanup;
1147 /* Add a no-alpha image */
1148 hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
1149 if(!hbmImage) goto cleanup;
1151 iImage = pImageList_Add(himl, hbmImage, hbmMask);
1152 ok(iImage != -1, "ImageList_Add failed\n");
1153 if(iImage == -1) goto cleanup;
1155 /* Add an alpha image */
1156 hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
1157 if(!hbmAlphaImage) goto cleanup;
1159 iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1160 ok(iAlphaImage != -1, "ImageList_Add failed\n");
1161 if(iAlphaImage == -1) goto cleanup;
1163 /* Add a transparent alpha image */
1164 hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
1165 if(!hbmTransparentImage) goto cleanup;
1167 iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1168 ok(iTransparentImage != -1, "ImageList_Add failed\n");
1169 if(iTransparentImage == -1) goto cleanup;
1171 /* 32-bit Tests */
1172 bitmapInfo.bmiHeader.biBitCount = 32;
1173 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1174 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1175 if (!hbmDst || !bits)
1176 goto cleanup;
1177 hbmOld = SelectObject(hdcDst, hbmDst);
1179 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1180 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1181 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
1182 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, 0x00B4BDC4, __LINE__);
1183 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1184 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1185 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1187 todo_wine
1189 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
1190 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
1191 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x009DA8B1, __LINE__);
1192 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, 0x008C99A3, __LINE__);
1194 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
1195 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
1196 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
1199 todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
1201 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1202 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
1204 /* ILD_ROP is ignored when the image has an alpha channel */
1205 todo_wine check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
1206 todo_wine check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
1208 todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
1209 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
1211 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
1212 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
1214 todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
1215 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
1216 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
1218 cleanup:
1220 if(hbmOld)
1221 SelectObject(hdcDst, hbmOld);
1222 if(hbmDst)
1223 DeleteObject(hbmDst);
1225 if(hdcDst)
1226 DeleteDC(hdcDst);
1228 if(hbmMask)
1229 DeleteObject(hbmMask);
1230 if(hbmInverseMask)
1231 DeleteObject(hbmInverseMask);
1233 if(hbmImage)
1234 DeleteObject(hbmImage);
1235 if(hbmAlphaImage)
1236 DeleteObject(hbmAlphaImage);
1237 if(hbmTransparentImage)
1238 DeleteObject(hbmTransparentImage);
1240 if(himl)
1242 ret = ImageList_Destroy(himl);
1243 ok(ret, "ImageList_Destroy failed\n");
1247 START_TEST(imagelist)
1249 ULONG_PTR ctx_cookie;
1251 HMODULE hComCtl32 = GetModuleHandle("comctl32.dll");
1252 pImageList_Create = NULL; /* These are not needed for non-v6.0 tests*/
1253 pImageList_Add = NULL;
1254 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1255 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1257 desktopDC=GetDC(NULL);
1258 hinst = GetModuleHandleA(NULL);
1260 InitCommonControls();
1262 testHotspot();
1263 DoTest1();
1264 DoTest2();
1265 DoTest3();
1266 testMerge();
1267 test_imagelist_storage();
1269 FreeLibrary(hComCtl32);
1271 /* Now perform v6 tests */
1273 if (!load_v6_module(&ctx_cookie))
1274 return;
1276 /* Reload comctl32 */
1277 hComCtl32 = LoadLibraryA("comctl32.dll");
1278 pImageList_Create = (void*)GetProcAddress(hComCtl32, "ImageList_Create");
1279 pImageList_Add = (void*)GetProcAddress(hComCtl32, "ImageList_Add");
1280 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1281 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1283 /* Do v6.0 tests */
1284 test_ImageList_DrawIndirect();
1285 test_shell_imagelist();
1287 unload_v6_module(ctx_cookie);