diff --git a/dlls/comctl32/imagelist.c b/dlls/comctl32/imagelist.c index 03c359f197c..76d57093265 100644 --- a/dlls/comctl32/imagelist.c +++ b/dlls/comctl32/imagelist.c @@ -2082,6 +2082,7 @@ ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2, INT cxDst, cyDst; INT xOff1, yOff1, xOff2, yOff2; POINT pt1, pt2; + INT newFlags; TRACE("(himl1=%p i1=%d himl2=%p i2=%d dx=%d dy=%d)\n", himl1, i1, himl2, i2, dx, dy); @@ -2121,7 +2122,10 @@ ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2, yOff2 = 0; } - himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1); + newFlags = (himl1->flags > himl2->flags ? himl1->flags : himl2->flags) & ILC_COLORDDB; + if (newFlags == ILC_COLORDDB && (himl1->flags & ILC_COLORDDB) == ILC_COLOR16) + newFlags = ILC_COLOR16; /* this is what native (at least v5) does, don't know why */ + himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | newFlags, 1, 1); if (himlDst) { diff --git a/dlls/comctl32/tests/imagelist.c b/dlls/comctl32/tests/imagelist.c index 19d24379517..58a7e702ee3 100644 --- a/dlls/comctl32/tests/imagelist.c +++ b/dlls/comctl32/tests/imagelist.c @@ -492,6 +492,70 @@ static void test_DrawIndirect(void) DestroyWindow(hwndfortest); } +static int get_color_format(HBITMAP bmp) +{ + BITMAPINFO bmi; + HDC hdc = CreateCompatibleDC(0); + HBITMAP hOldBmp = SelectObject(hdc, bmp); + int ret; + + memset(&bmi, 0, sizeof(bmi)); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + ret = GetDIBits(hdc, bmp, 0, 0, 0, &bmi, DIB_RGB_COLORS); + ok(ret, "GetDIBits failed\n"); + + SelectObject(hdc, hOldBmp); + DeleteDC(hdc); + return bmi.bmiHeader.biBitCount; +} + +static void test_merge_colors(void) +{ + HIMAGELIST himl[8], hmerge; + int sizes[] = { ILC_COLOR, ILC_COLOR | ILC_MASK, ILC_COLOR4, ILC_COLOR8, ILC_COLOR16, ILC_COLOR24, ILC_COLOR32, ILC_COLORDDB }; + HICON hicon1; + IMAGEINFO info; + int bpp, i, j; + + hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits); + ok(hicon1 != NULL, "failed to create hicon1\n"); + + for (i = 0; i < 8; i++) + { + himl[i] = ImageList_Create(32, 32, sizes[i], 0, 3); + ok(himl[i] != NULL, "failed to create himl[%d]\n", i); + ok(0 == ImageList_AddIcon(himl[i], hicon1), "add icon1 to himl[%d] failed\n", i); + if (i == 0 || i == 1 || i == 7) + { + ImageList_GetImageInfo(himl[i], 0, &info); + sizes[i] = get_color_format(info.hbmImage); + } + } + DestroyIcon(hicon1); + for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) + { + hmerge = ImageList_Merge(himl[i], 0, himl[j], 0, 0, 0); + ok(hmerge != NULL, "merge himl[%d], himl[%d] failed\n", i, j); + + ImageList_GetImageInfo(hmerge, 0, &info); + bpp = get_color_format(info.hbmImage); + /* ILC_COLOR[X] is defined as [X] */ + if (i == 4 && j == 7) + ok(bpp == 16, /* merging ILC_COLOR16 with ILC_COLORDDB seems to be a special case */ + "wrong biBitCount %d when merging lists %d (%d) and %d (%d)\n", bpp, i, sizes[i], j, sizes[j]); + else + ok(bpp == (i > j ? sizes[i] : sizes[j]), + "wrong biBitCount %d when merging lists %d (%d) and %d (%d)\n", bpp, i, sizes[i], j, sizes[j]); + ok(info.hbmMask != 0, "Imagelist merged from %d and %d had no mask\n", i, j); + + if (hmerge) ImageList_Destroy(hmerge); + } + + for (i = 0; i < 8; i++) + ImageList_Destroy(himl[i]); +} + static void test_merge(void) { HIMAGELIST himl1, himl2, hmerge; @@ -2017,6 +2081,7 @@ START_TEST(imagelist) test_imagecount(); test_DrawIndirect(); test_merge(); + test_merge_colors(); test_imagelist_storage(); test_iconsize();