diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec index 7e7bfbfea0b..f9d47d9ac17 100644 --- a/dlls/gdiplus/gdiplus.spec +++ b/dlls/gdiplus/gdiplus.spec @@ -76,7 +76,7 @@ @ stdcall GdipCreateBitmapFromGdiDib(ptr ptr ptr) @ stdcall GdipCreateBitmapFromGraphics(long long ptr ptr) @ stdcall GdipCreateBitmapFromHBITMAP(long long ptr) -@ stub GdipCreateBitmapFromHICON +@ stdcall GdipCreateBitmapFromHICON(long ptr) @ stdcall GdipCreateBitmapFromResource(long wstr ptr) @ stdcall GdipCreateBitmapFromScan0(long long long long ptr ptr) @ stdcall GdipCreateBitmapFromStream(ptr ptr) diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c index 02f8f5a5655..9944322b371 100644 --- a/dlls/gdiplus/image.c +++ b/dlls/gdiplus/image.c @@ -18,6 +18,8 @@ #include +#define NONAMELESSUNION + #include "windef.h" #include "winbase.h" #include "winuser.h" @@ -429,6 +431,50 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromGraphics(INT width, INT height, return ret; } +GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON hicon, GpBitmap** bitmap) +{ + HICON icon_copy; + ICONINFO iinfo; + PICTDESC desc; + + TRACE("%p, %p\n", hicon, bitmap); + + if(!bitmap || !GetIconInfo(hicon, &iinfo)) + return InvalidParameter; + + *bitmap = GdipAlloc(sizeof(GpBitmap)); + if(!*bitmap) return OutOfMemory; + + icon_copy = CreateIconIndirect(&iinfo); + + if(!icon_copy){ + GdipFree(*bitmap); + return InvalidParameter; + } + + desc.cbSizeofstruct = sizeof(PICTDESC); + desc.picType = PICTYPE_ICON; + desc.u.icon.hicon = icon_copy; + + if(OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, + (LPVOID*) &((*bitmap)->image.picture)) != S_OK){ + DestroyIcon(icon_copy); + GdipFree(*bitmap); + return GenericError; + } + + (*bitmap)->format = PixelFormat32bppARGB; + (*bitmap)->image.type = ImageTypeBitmap; + (*bitmap)->image.flags = ImageFlagsNone; + (*bitmap)->width = ipicture_pixel_width((*bitmap)->image.picture); + (*bitmap)->height = ipicture_pixel_height((*bitmap)->image.picture); + + DeleteObject(iinfo.hbmColor); + DeleteObject(iinfo.hbmMask); + + return Ok; +} + GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride, PixelFormat format, BYTE* scan0, GpBitmap** bitmap) { diff --git a/dlls/gdiplus/tests/Makefile.in b/dlls/gdiplus/tests/Makefile.in index 7dba3daaaa7..ac5589d2e0d 100644 --- a/dlls/gdiplus/tests/Makefile.in +++ b/dlls/gdiplus/tests/Makefile.in @@ -3,7 +3,7 @@ TOPOBJDIR = ../../.. SRCDIR = @srcdir@ VPATH = @srcdir@ TESTDLL = gdiplus.dll -IMPORTS = gdiplus user32 gdi32 kernel32 +IMPORTS = gdiplus ole32 user32 gdi32 kernel32 CTESTS = \ brush.c \ diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c index 19f050061d5..661975925ae 100644 --- a/dlls/gdiplus/tests/image.c +++ b/dlls/gdiplus/tests/image.c @@ -18,11 +18,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include + +#include "initguid.h" #include "windows.h" #include "gdiplus.h" #include "wine/test.h" -#include -#include "wingdi.h" #define expect(expected, got) ok(((UINT)got) == ((UINT)expected), "Expected %.8x, got %.8x\n", (UINT)expected, (UINT)got) @@ -530,6 +531,111 @@ static void test_testcontrol(void) ok(param != 0, "Build number expected, got %u\n", param); } +static void test_fromhicon(void) +{ + static const BYTE bmp_bits[1024]; + HBITMAP hbmMask, hbmColor; + ICONINFO info; + HICON hIcon; + GpStatus stat; + GpBitmap *bitmap = NULL; + UINT dim; + ImageType type; + PixelFormat format; + GUID raw; + WCHAR bufferW[39]; + char buffer[39]; + char buffer2[39]; + + /* NULL */ + stat = GdipCreateBitmapFromHICON(NULL, NULL); + expect(InvalidParameter, stat); + stat = GdipCreateBitmapFromHICON(NULL, &bitmap); + expect(InvalidParameter, stat); + + /* color icon 1 bit */ + hbmMask = CreateBitmap(16, 16, 1, 1, bmp_bits); + ok(hbmMask != 0, "CreateBitmap failed\n"); + hbmColor = CreateBitmap(16, 16, 1, 1, bmp_bits); + ok(hbmColor != 0, "CreateBitmap failed\n"); + info.fIcon = TRUE; + info.xHotspot = 8; + info.yHotspot = 8; + info.hbmMask = hbmMask; + info.hbmColor = hbmColor; + hIcon = CreateIconIndirect(&info); + ok(hIcon != 0, "CreateIconIndirect failed\n"); + DeleteObject(hbmMask); + DeleteObject(hbmColor); + + stat = GdipCreateBitmapFromHICON(hIcon, &bitmap); + expect(Ok, stat); + if(stat == Ok){ + /* check attributes */ + stat = GdipGetImageHeight((GpImage*)bitmap, &dim); + expect(Ok, stat); + expect(16, dim); + stat = GdipGetImageWidth((GpImage*)bitmap, &dim); + expect(Ok, stat); + expect(16, dim); + stat = GdipGetImageType((GpImage*)bitmap, &type); + expect(Ok, stat); + expect(ImageTypeBitmap, type); + stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format); + expect(PixelFormat32bppARGB, format); + /* raw format */ + stat = GdipGetImageRawFormat((GpImage*)bitmap, &raw); + StringFromGUID2(&raw, bufferW, sizeof(bufferW)/sizeof(bufferW[0])); + WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL); + StringFromGUID2(&ImageFormatMemoryBMP, bufferW, sizeof(bufferW)/sizeof(bufferW[0])); + WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer2, sizeof(buffer2), NULL, NULL); + todo_wine ok(IsEqualGUID(&raw, &ImageFormatMemoryBMP), "Expected format %s, got %s\n", buffer2, buffer); + GdipDisposeImage((GpImage*)bitmap); + } + DestroyIcon(hIcon); + + /* color icon 8 bpp */ + hbmMask = CreateBitmap(16, 16, 1, 8, bmp_bits); + ok(hbmMask != 0, "CreateBitmap failed\n"); + hbmColor = CreateBitmap(16, 16, 1, 8, bmp_bits); + ok(hbmColor != 0, "CreateBitmap failed\n"); + info.fIcon = TRUE; + info.xHotspot = 8; + info.yHotspot = 8; + info.hbmMask = hbmMask; + info.hbmColor = hbmColor; + hIcon = CreateIconIndirect(&info); + ok(hIcon != 0, "CreateIconIndirect failed\n"); + DeleteObject(hbmMask); + DeleteObject(hbmColor); + + stat = GdipCreateBitmapFromHICON(hIcon, &bitmap); + expect(Ok, stat); + if(stat == Ok){ + /* check attributes */ + stat = GdipGetImageHeight((GpImage*)bitmap, &dim); + expect(Ok, stat); + expect(16, dim); + stat = GdipGetImageWidth((GpImage*)bitmap, &dim); + expect(Ok, stat); + expect(16, dim); + stat = GdipGetImageType((GpImage*)bitmap, &type); + expect(Ok, stat); + expect(ImageTypeBitmap, type); + stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format); + expect(PixelFormat32bppARGB, format); + /* raw format */ + stat = GdipGetImageRawFormat((GpImage*)bitmap, &raw); + StringFromGUID2(&raw, bufferW, sizeof(bufferW)/sizeof(bufferW[0])); + WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL); + StringFromGUID2(&ImageFormatMemoryBMP, bufferW, sizeof(bufferW)/sizeof(bufferW[0])); + WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer2, sizeof(buffer2), NULL, NULL); + todo_wine ok(IsEqualGUID(&raw, &ImageFormatMemoryBMP), "Expected format %s, got %s\n", buffer2, buffer); + GdipDisposeImage((GpImage*)bitmap); + } + DestroyIcon(hIcon); +} + START_TEST(image) { struct GdiplusStartupInput gdiplusStartupInput; @@ -553,6 +659,7 @@ START_TEST(image) test_GdipGetImageFlags(); test_GdipCloneImage(); test_testcontrol(); + test_fromhicon(); GdiplusShutdown(gdiplusToken); } diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h index cb53ea4f93a..dd01d1b358e 100644 --- a/include/gdiplusflat.h +++ b/include/gdiplusflat.h @@ -49,6 +49,7 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromFileICM(GDIPCONST WCHAR*,GpBitmap**); GpStatus WINGDIPAPI GdipCreateBitmapFromGdiDib(GDIPCONST BITMAPINFO*,VOID*,GpBitmap**); GpStatus WINGDIPAPI GdipCreateBitmapFromGraphics(INT,INT,GpGraphics*,GpBitmap**); GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP, HPALETTE, GpBitmap**); +GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON, GpBitmap**); GpStatus WINGDIPAPI GdipCreateBitmapFromResource(HINSTANCE,GDIPCONST WCHAR*,GpBitmap**); GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT,INT,INT,PixelFormat,BYTE*, GpBitmap**);