Jinoh Kang (4): include: Add definition for IShellItemImageFactory. shell32/tests: Add tests for IShellItemImageFactory. shell32: Add stub for IShellItemImageFactory. shell32: Partially implement IShellItemImageFactory (icon only, no thumbnail).
dlls/shell32/shellitem.c | 253 +++++++++++++++++++++++++++++++++ dlls/shell32/tests/shlfolder.c | 46 ++++++ include/shobjidl.idl | 30 ++++ 3 files changed, 329 insertions(+)
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com ---
Notes: v1 -> v2: no changes v2 -> v3: use lowercase letters for uuid(<hex>) v3 -> v4: no changes
include/shobjidl.idl | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/include/shobjidl.idl b/include/shobjidl.idl index c1a36ab5e93..b654d78c9cd 100644 --- a/include/shobjidl.idl +++ b/include/shobjidl.idl @@ -471,6 +471,36 @@ interface IShellItem2 : IShellItem [out] BOOL *pf); }
+/***************************************************************************** + * IShellItemImageFactory interface + */ +[ + object, + uuid(bcc18b79-ba16-442f-80c4-8a59c30c463b), + pointer_default(unique) +] +interface IShellItemImageFactory : IUnknown +{ + [v1_enum] enum _SIIGBF { + SIIGBF_RESIZETOFIT = 0x00000000, + SIIGBF_BIGGERSIZEOK = 0x00000001, + SIIGBF_MEMORYONLY = 0x00000002, + SIIGBF_ICONONLY = 0x00000004, + SIIGBF_THUMBNAILONLY = 0x00000008, + SIIGBF_INCACHEONLY = 0x00000010, + SIIGBF_CROPTOSQUARE = 0x00000020, + SIIGBF_WIDETHUMBNAILS = 0x00000040, + SIIGBF_ICONBACKGROUND = 0x00000080, + SIIGBF_SCALEUP = 0x00000100, + }; + typedef DWORD SIIGBF; + + HRESULT GetImage( + [in] SIZE size, + [in] SIIGBF flags, + [out] HBITMAP *phbm); +} + typedef [v1_enum] enum tagNWMF { NWMF_UNLOADING = 0x00000001, NWMF_USERINITED = 0x00000002,
On 4/23/22 20:53, Jinoh Kang wrote:
- [v1_enum] enum _SIIGBF {
SIIGBF_RESIZETOFIT = 0x00000000,
SIIGBF_BIGGERSIZEOK = 0x00000001,
SIIGBF_MEMORYONLY = 0x00000002,
SIIGBF_ICONONLY = 0x00000004,
SIIGBF_THUMBNAILONLY = 0x00000008,
SIIGBF_INCACHEONLY = 0x00000010,
SIIGBF_CROPTOSQUARE = 0x00000020,
SIIGBF_WIDETHUMBNAILS = 0x00000040,
SIIGBF_ICONBACKGROUND = 0x00000080,
SIIGBF_SCALEUP = 0x00000100,
- };
- typedef DWORD SIIGBF;
I see this using int instead of DWORD in 10.0.22000.0, did it change?
Because you have to convert potentially-transparent HICON to HBITMAP with alpha channel, which is quite a complicated feat.
- HICON can take many pixel formats, ranging from 32-bit ARGB and monochrome with mask.
- hbmColor and hbmMask combinations aren't exactly simple to handle.
- Windows always seems to output a 32-bit ARGB bitmap. GDI routines alone aren't particularly suited for the task (GdiAlphaBlend works with PARGB, not ARGB).
Only WIC and GDI+ has functions to handle most of these.
Same SDK claims output could be RGB24, RGB32, or PARGB32, but it can't be trusted of course.
On 4/24/22 22:05, Nikolay Sivov wrote:
On 4/23/22 20:53, Jinoh Kang wrote:
+ [v1_enum] enum _SIIGBF { + SIIGBF_RESIZETOFIT = 0x00000000, + SIIGBF_BIGGERSIZEOK = 0x00000001, + SIIGBF_MEMORYONLY = 0x00000002, + SIIGBF_ICONONLY = 0x00000004, + SIIGBF_THUMBNAILONLY = 0x00000008, + SIIGBF_INCACHEONLY = 0x00000010, + SIIGBF_CROPTOSQUARE = 0x00000020, + SIIGBF_WIDETHUMBNAILS = 0x00000040, + SIIGBF_ICONBACKGROUND = 0x00000080, + SIIGBF_SCALEUP = 0x00000100, + }; + typedef DWORD SIIGBF;
I see this using int instead of DWORD in 10.0.22000.0, did it change?
That's about right. No idea where the DWORD came though...
Because you have to convert potentially-transparent HICON to HBITMAP with alpha channel, which is quite a complicated feat.
- HICON can take many pixel formats, ranging from 32-bit ARGB and monochrome with mask.
- hbmColor and hbmMask combinations aren't exactly simple to handle.
- Windows always seems to output a 32-bit ARGB bitmap. GDI routines alone aren't particularly suited for the task (GdiAlphaBlend works with PARGB, not ARGB).
Only WIC and GDI+ has functions to handle most of these.
Same SDK claims output could be RGB24, RGB32, or PARGB32, but it can't be trusted of course.
There is an API sample from Microsoft: https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/Win7S... Basically it feeds IShellItemImageFactory output directly into a SS_BITMAP static control.
Note that static controls are known to accept ARGB32 bitmaps, which is converted into PARGB32 internally: - https://source.winehq.org/git/wine.git/blob/f4fdafbb5597bde5d2d3433d5c64f5a7...
This is also consistent with Wine behaviour: - https://source.winehq.org/git/wine.git/blob/f4fdafbb5597bde5d2d3433d5c64f5a7...
Ideally it would be nice if we could test the pixel format, but there is no reliable way to detect if a given GDI bitmap is in ARGB32 or PARGB32. (Specifically, a PARGB32 bitmap can always be interpreted as a valid ARGB32 bitmap, but not vice versa.)
At least, the output bitmap was observed to be consistently ARGB32 regardless of which pixel format the source icon used (e.g. 8-bit color, RGB32, or ARGB32).
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com ---
Notes: v1 -> v2: mark test broken on Windows 7 v2 -> v3: remove erroneous todo_wine v3 -> v4: no changes
dlls/shell32/tests/shlfolder.c | 46 ++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index f99045c33d5..6c3d9721ef7 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -4481,6 +4481,51 @@ static void test_GetUIObject(void) Cleanup(); }
+static void test_IShellItemImageFactory(void) +{ + HRESULT ret; + IShellItem *shellitem; + LPITEMIDLIST pidl_desktop = NULL; + + if (!pSHCreateShellItem) + { + win_skip("SHCreateShellItem isn't available\n"); + return; + } + + ret = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl_desktop); + ok(ret == S_OK, "Got 0x%08lx\n", ret); + if (SUCCEEDED(ret)) + { + ret = pSHCreateShellItem(NULL, NULL, pidl_desktop, &shellitem); + ok(SUCCEEDED(ret), "SHCreateShellItem returned %lx\n", ret); + if (SUCCEEDED(ret)) + { + IShellItemImageFactory *siif; + ret = IShellItem_QueryInterface(shellitem, &IID_IShellItemImageFactory, (void **)&siif); + todo_wine ok(ret == S_OK, "QueryInterface returned %lx\n", ret); + if (SUCCEEDED(ret)) + { + HBITMAP hbm = NULL; + SIZE size = {32, 32}; + + ret = IShellItemImageFactory_GetImage(siif, size, SIIGBF_BIGGERSIZEOK, &hbm); + todo_wine ok(ret == S_OK || broken(ret == E_PENDING /* win7 */), "GetImage returned %lx\n", ret); + ok(FAILED(ret) == !hbm, "result = %lx but bitmap = %p\n", ret, hbm); + if (SUCCEEDED(ret) && hbm) + { + DWORD objtype = GetObjectType(hbm); + ok(objtype == OBJ_BITMAP, "Expected type OBJ_BITMAP, got %lu\n", objtype); + DeleteObject(hbm); + } + IShellItemImageFactory_Release(siif); + } + IShellItem_Release(shellitem); + } + ILFree(pidl_desktop); + } +} + static void test_CreateViewObject_contextmenu(void) { IShellFolder *desktop; @@ -5386,6 +5431,7 @@ START_TEST(shlfolder) test_ShellItemArrayEnumItems(); test_desktop_IPersist(); test_GetUIObject(); + test_IShellItemImageFactory(); test_CreateViewObject_contextmenu(); test_SHSimpleIDListFromPath(); test_ParseDisplayNamePBC();
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=113218
Your paranoid android.
=== w1064v1809 (32 bit report) ===
shell32: shlfolder.c:4956: Test failed: RMDIR: expected notification type 10, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 10)
=== w1064_tsign (32 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000) shlfolder.c:4956: Test failed: CREATE: expected notification type 2, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 2)
=== w10pro64 (32 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4956: Test failed: RMDIR: expected notification type 10, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 10)
=== w1064v1809 (64 bit report) ===
shell32: shlfolder.c:4956: Test failed: RMDIR: expected notification type 10, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 10)
=== w1064_2qxl (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4956: Test failed: RMDIR: expected notification type 10, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w1064_tsign (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 2) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4956: Test failed: CREATE: expected notification type 2, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 2) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4956: Test failed: RMDIR: expected notification type 10, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 10) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w10pro64 (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4956: Test failed: RMDIR: expected notification type 10, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 10)
=== w10pro64_ar (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4956: Test failed: CREATE: expected notification type 2, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 2) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4956: Test failed: RMDIR: expected notification type 10, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 10) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w10pro64_ja (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4956: Test failed: MKDIR: expected notification type 8, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4956: Test failed: RMDIR: expected notification type 10, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w10pro64_zh_CN (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4956: Test failed: MKDIR: expected notification type 8, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com ---
Notes: v1 -> v2: no changes v2 -> v3: change iface lpVtbl initialization order to match struct order v3 -> v4: no changes
dlls/shell32/shellitem.c | 50 ++++++++++++++++++++++++++++++++++ dlls/shell32/tests/shlfolder.c | 2 +- 2 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/dlls/shell32/shellitem.c b/dlls/shell32/shellitem.c index 0a3a76cbd6a..1a0bed55c1e 100644 --- a/dlls/shell32/shellitem.c +++ b/dlls/shell32/shellitem.c @@ -39,6 +39,7 @@ typedef struct _ShellItem { LONG ref; LPITEMIDLIST pidl; IPersistIDList IPersistIDList_iface; + IShellItemImageFactory IShellItemImageFactory_iface; } ShellItem;
typedef struct _CustomDestinationList { @@ -56,6 +57,11 @@ static inline ShellItem *impl_from_IPersistIDList( IPersistIDList *iface ) return CONTAINING_RECORD(iface, ShellItem, IPersistIDList_iface); }
+static inline ShellItem *impl_from_IShellItemImageFactory( IShellItemImageFactory *iface ) +{ + return CONTAINING_RECORD(iface, ShellItem, IShellItemImageFactory_iface); +} + static inline CustomDestinationList *impl_from_ICustomDestinationList( ICustomDestinationList *iface ) { return CONTAINING_RECORD(iface, CustomDestinationList, ICustomDestinationList_iface); @@ -79,6 +85,10 @@ static HRESULT WINAPI ShellItem_QueryInterface(IShellItem2 *iface, REFIID riid, { *ppv = &This->IPersistIDList_iface; } + else if (IsEqualIID(&IID_IShellItemImageFactory, riid)) + { + *ppv = &This->IShellItemImageFactory_iface; + } else { FIXME("not implemented for %s\n", shdebugstr_guid(riid)); *ppv = NULL; @@ -536,6 +546,45 @@ static const IPersistIDListVtbl ShellItem_IPersistIDList_Vtbl = { ShellItem_IPersistIDList_GetIDList };
+static HRESULT WINAPI ShellItem_IShellItemImageFactory_QueryInterface(IShellItemImageFactory *iface, + REFIID riid, void **ppv) +{ + ShellItem *This = impl_from_IShellItemImageFactory(iface); + return IShellItem2_QueryInterface(&This->IShellItem2_iface, riid, ppv); +} + +static ULONG WINAPI ShellItem_IShellItemImageFactory_AddRef(IShellItemImageFactory *iface) +{ + ShellItem *This = impl_from_IShellItemImageFactory(iface); + return IShellItem2_AddRef(&This->IShellItem2_iface); +} + +static ULONG WINAPI ShellItem_IShellItemImageFactory_Release(IShellItemImageFactory *iface) +{ + ShellItem *This = impl_from_IShellItemImageFactory(iface); + return IShellItem2_Release(&This->IShellItem2_iface); +} + +static HRESULT WINAPI ShellItem_IShellItemImageFactory_GetImage(IShellItemImageFactory *iface, + SIZE size, SIIGBF flags, HBITMAP *phbm) +{ + ShellItem *This = impl_from_IShellItemImageFactory(iface); + static int once; + + if (!once++) + FIXME("%p ({%lu, %lu} %lu %p): stub\n", This, size.cx, size.cy, flags, phbm); + + *phbm = NULL; + return E_NOTIMPL; +} + +static const IShellItemImageFactoryVtbl ShellItem_IShellItemImageFactory_Vtbl = { + ShellItem_IShellItemImageFactory_QueryInterface, + ShellItem_IShellItemImageFactory_AddRef, + ShellItem_IShellItemImageFactory_Release, + ShellItem_IShellItemImageFactory_GetImage, +}; +
HRESULT WINAPI IShellItem_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv) { @@ -553,6 +602,7 @@ HRESULT WINAPI IShellItem_Constructor(IUnknown *pUnkOuter, REFIID riid, void **p This->ref = 1; This->pidl = NULL; This->IPersistIDList_iface.lpVtbl = &ShellItem_IPersistIDList_Vtbl; + This->IShellItemImageFactory_iface.lpVtbl = &ShellItem_IShellItemImageFactory_Vtbl;
ret = IShellItem2_QueryInterface(&This->IShellItem2_iface, riid, ppv); IShellItem2_Release(&This->IShellItem2_iface); diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index 6c3d9721ef7..900c484d0b9 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -4503,7 +4503,7 @@ static void test_IShellItemImageFactory(void) { IShellItemImageFactory *siif; ret = IShellItem_QueryInterface(shellitem, &IID_IShellItemImageFactory, (void **)&siif); - todo_wine ok(ret == S_OK, "QueryInterface returned %lx\n", ret); + ok(ret == S_OK, "QueryInterface returned %lx\n", ret); if (SUCCEEDED(ret)) { HBITMAP hbm = NULL;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=113219
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 8000)
=== w1064v1809 (32 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000)
=== w1064 (32 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000)
=== w1064_tsign (32 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000) shlfolder.c:4956: Test failed: RMDIR: expected notification type 10, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 10)
=== w10pro64 (32 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4956: Test failed: CREATE: expected notification type 2, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 2) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w1064v1809 (64 bit report) ===
shell32: shlfolder.c:4956: Test failed: CREATE: expected notification type 2, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 2)
=== w1064 (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000)
=== w1064_tsign (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4956: Test failed: CREATE: expected notification type 2, got: 40000 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w10pro64 (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000)
=== w10pro64_ar (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4956: Test failed: MKDIR: expected notification type 8, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w10pro64_he (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4956: Test failed: RMDIR: expected notification type 10, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 10) shlfolder.c:4956: Test failed: CREATE: expected notification type 2, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w10pro64_ja (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4956: Test failed: MKDIR: expected notification type 8, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w10pro64_zh_CN (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4956: Test failed: RMDIR: expected notification type 10, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 10) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4956: Test failed: MKDIR: expected notification type 8, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4956: Test failed: CREATE: expected notification type 2, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4956: Test failed: RMDIR: expected notification type 10, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52673 Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com ---
Notes: v1 -> v2: no changes
v3 -> v4: - Remove patch "shell32: Factor out ShellItem_get_uiobject." - Use IShellItem2_BindToHandler instead of factoring out ShellItem_get_uiobject - Use CreateCompatibleDC(NULL) instead of GetDC(NULL) - Remove new dependency on win32u, use GetIconInfo instead - Remove new dependency on windowcodecs, use gdiplus instead
dlls/shell32/shellitem.c | 209 ++++++++++++++++++++++++++++++++- dlls/shell32/tests/shlfolder.c | 2 +- 2 files changed, 207 insertions(+), 4 deletions(-)
diff --git a/dlls/shell32/shellitem.c b/dlls/shell32/shellitem.c index 1a0bed55c1e..47a1eeb5701 100644 --- a/dlls/shell32/shellitem.c +++ b/dlls/shell32/shellitem.c @@ -31,6 +31,7 @@ #include "pidl.h" #include "shell32_main.h" #include "debughlp.h" +#include "gdiplus.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
@@ -565,17 +566,219 @@ static ULONG WINAPI ShellItem_IShellItemImageFactory_Release(IShellItemImageFact return IShellItem2_Release(&This->IShellItem2_iface); }
+static HRESULT ShellItem_get_icons(ShellItem *This, SIZE size, HICON *big_icon, HICON *small_icon) +{ + HRESULT hr; + IBindCtx *pbc; + IExtractIconW *ei; + WCHAR icon_file[MAX_PATH]; + INT source_index; + UINT gil_in_flags = 0, gil_out_flags; + INT iconsize; + + iconsize = min(size.cx, size.cy); + if (iconsize <= 0 || iconsize > 0x7fff) + iconsize = 0x7fff; + + hr = CreateBindCtx(0, &pbc); + if (FAILED(hr)) goto done; + + hr = IShellItem2_BindToHandler(&This->IShellItem2_iface, pbc, &BHID_SFUIObject, + &IID_IExtractIconW, (void **)&ei); + IBindCtx_Release(pbc); + if (FAILED(hr)) goto done; + + hr = IExtractIconW_GetIconLocation(ei, gil_in_flags, icon_file, MAX_PATH, &source_index, &gil_out_flags); + if (FAILED(hr)) goto free_ei; + + if (!(gil_out_flags & GIL_NOTFILENAME)) + { + UINT ei_res; + + if (source_index == -1) + source_index = 0; /* special case for some control panel applications */ + + FIXME("%s %d\n", debugstr_w(icon_file), source_index); + ei_res = ExtractIconExW(icon_file, source_index, big_icon, small_icon, 1); + if (!ei_res || ei_res == (UINT)-1) + { + WARN("Failed to extract icon.\n"); + hr = E_FAIL; + } + } + else + { + hr = IExtractIconW_Extract(ei, icon_file, source_index, big_icon, small_icon, MAKELONG(iconsize, iconsize)); + } + +free_ei: + IExtractIconW_Release(ei); +done: + return hr; +} + +static HICON choose_best_icon(HICON *icons, UINT count, SIZE size_limit, SIZE *out_size) +{ + HICON best_icon = NULL; + SIZE best_size = {0, 0}; + UINT i; + + for (i = 0; i < count; i++) + { + ICONINFO iinfo; + BITMAP bm; + SIZE size; + BOOL is_color, ret; + + if (!icons[i] || !GetIconInfo(icons[i], &iinfo)) continue; + + is_color = iinfo.hbmColor != NULL; + ret = GetObjectW(is_color ? iinfo.hbmColor : iinfo.hbmMask, sizeof(bm), &bm); + DeleteObject(iinfo.hbmColor); + DeleteObject(iinfo.hbmMask); + if (!ret) continue; + + size.cx = bm.bmWidth; + size.cy = is_color ? abs(bm.bmHeight) : abs(bm.bmHeight) / 2; + + if (!best_icon || (best_size.cx < size.cx && size.cx <= size_limit.cx && + best_size.cy < size.cy && size.cy <= size_limit.cy)) + { + best_icon = icons[i]; + best_size = size; + } + } + + *out_size = best_size; + return best_icon; +} + +static HRESULT gpstatus_to_hresult(GpStatus status) +{ + switch (status) + { + case Ok: + return S_OK; + case InvalidParameter: + return E_INVALIDARG; + case OutOfMemory: + return E_OUTOFMEMORY; + case NotImplemented: + return E_NOTIMPL; + default: + return E_FAIL; + } +} + +static HRESULT ShellItem_get_icon_bitmap(ShellItem *This, SIZE size, SIIGBF flags, GpBitmap **bitmap) +{ + HRESULT hr; + HICON icons[2] = { NULL, NULL }, best_icon; + SIZE best_icon_size; + UINT i; + + *bitmap = NULL; + + hr = ShellItem_get_icons(This, size, &icons[0], &icons[1]); + if (FAILED(hr)) return hr; + + best_icon = choose_best_icon(icons, ARRAY_SIZE(icons), size, &best_icon_size); + for (i = 0; i < ARRAY_SIZE(icons); i++) + if (icons[i] && icons[i] != best_icon) DeleteObject(icons[i]); + + if (!best_icon) return E_FAIL; + + hr = gpstatus_to_hresult(GdipCreateBitmapFromHICON(best_icon, bitmap)); + DeleteObject(best_icon); + return hr; +} + +/************************************************************************* + * create_argb_hbitmap_from_gpbitmap + * + * This is similar to GdipCreateHBITMAPFromBitmap, except that it uses + * PixelFormat32bppARGB instead of PixelFormat32bppPARGB and lacks the + * background parameter. + */ +static HRESULT create_argb_hbitmap_from_gpbitmap(GpBitmap *bitmap, HBITMAP *gdibitmap) +{ + BITMAPINFOHEADER bmi; + HRESULT hr; + UINT width, height; + BitmapData bitmapdata; + HDC dc; + HBITMAP bm; + void *bits; + + *gdibitmap = NULL; + + hr = GdipGetImageWidth((GpImage *)bitmap, &width); + if (FAILED(hr)) return hr; + + hr = GdipGetImageHeight((GpImage *)bitmap, &height); + if (FAILED(hr)) return hr; + + dc = CreateCompatibleDC(NULL); + if (!dc) return E_FAIL; + + memset(&bmi, 0, sizeof(bmi)); + bmi.biSize = sizeof(bmi); + bmi.biWidth = width; + bmi.biHeight = -height; + bmi.biPlanes = 1; + bmi.biBitCount = 32; + bmi.biCompression = BI_RGB; + + bm = CreateDIBSection(dc, (const BITMAPINFO *)&bmi, DIB_RGB_COLORS, &bits, NULL, 0); + DeleteDC(dc); + if (!bm) + { + WARN("Cannot create bitmap.\n"); + return E_FAIL; + } + + memset(&bitmapdata, 0, sizeof(bitmapdata)); + bitmapdata.Width = width; + bitmapdata.Height = height; + bitmapdata.Stride = width * 4; + bitmapdata.PixelFormat = PixelFormat32bppARGB; + bitmapdata.Scan0 = bits; + hr = gpstatus_to_hresult(GdipBitmapLockBits(bitmap, NULL, + ImageLockModeRead | ImageLockModeUserInputBuf, + bitmapdata.PixelFormat, &bitmapdata)); + if (FAILED(hr)) + { + DeleteObject(bm); + return hr; + } + + GdipBitmapUnlockBits(bitmap, &bitmapdata); + + *gdibitmap = bm; + return S_OK; +} + static HRESULT WINAPI ShellItem_IShellItemImageFactory_GetImage(IShellItemImageFactory *iface, SIZE size, SIIGBF flags, HBITMAP *phbm) { ShellItem *This = impl_from_IShellItemImageFactory(iface); + HRESULT hr; + GpBitmap *bitmap = NULL; static int once;
if (!once++) - FIXME("%p ({%lu, %lu} %lu %p): stub\n", This, size.cx, size.cy, flags, phbm); + FIXME("%p ({%lu, %lu} %lu %p): partial stub\n", This, size.cx, size.cy, flags, phbm);
- *phbm = NULL; - return E_NOTIMPL; + if (flags != SIIGBF_BIGGERSIZEOK) return E_NOTIMPL; + + hr = ShellItem_get_icon_bitmap(This, size, flags, &bitmap); + if (SUCCEEDED(hr)) + { + hr = create_argb_hbitmap_from_gpbitmap(bitmap, phbm); + GdipDisposeImage((GpImage *)bitmap); + } + + return hr; }
static const IShellItemImageFactoryVtbl ShellItem_IShellItemImageFactory_Vtbl = { diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index 900c484d0b9..a5f498f8c6d 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -4510,7 +4510,7 @@ static void test_IShellItemImageFactory(void) SIZE size = {32, 32};
ret = IShellItemImageFactory_GetImage(siif, size, SIIGBF_BIGGERSIZEOK, &hbm); - todo_wine ok(ret == S_OK || broken(ret == E_PENDING /* win7 */), "GetImage returned %lx\n", ret); + ok(ret == S_OK || broken(ret == E_PENDING /* win7 */), "GetImage returned %lx\n", ret); ok(FAILED(ret) == !hbm, "result = %lx but bitmap = %p\n", ret, hbm); if (SUCCEEDED(ret) && hbm) {
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=113220
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 8000)
=== w1064v1809 (32 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000)
=== w1064_tsign (32 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000)
=== w10pro64 (32 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000)
=== w1064v1809 (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000)
=== w1064 (64 bit report) ===
shell32: shlfolder.c:4956: Test failed: MKDIR: expected notification type 8, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 8)
=== w1064_tsign (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 10)
=== w10pro64 (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w10pro64_ar (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 40000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4956: Test failed: MKDIR: expected notification type 8, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w10pro64_he (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4956: Test failed: MKDIR: expected notification type 8, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4956: Test failed: CREATE: expected notification type 2, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w10pro64_ja (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4956: Test failed: CREATE: expected notification type 2, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 2) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 4000000) shlfolder.c:4956: Test failed: RMDIR: expected notification type 10, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 10) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
=== w10pro64_zh_CN (64 bit report) ===
shell32: shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4956: Test failed: MKDIR: expected notification type 8, got: 40000 shlfolder.c:4963: Test failed: GetDisplayNameOf failed: 0x80070057 shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3) shlfolder.c:4973: Test failed: Didn't expect a WM_USER_NOTIFY message (event: 3)
On 4/23/22 20:53, Jinoh Kang wrote:
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52673 Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com
Notes: v1 -> v2: no changes
v3 -> v4: - Remove patch "shell32: Factor out ShellItem_get_uiobject." - Use IShellItem2_BindToHandler instead of factoring out ShellItem_get_uiobject - Use CreateCompatibleDC(NULL) instead of GetDC(NULL) - Remove new dependency on win32u, use GetIconInfo instead - Remove new dependency on windowcodecs, use gdiplus instead
I probably missed earlier iterations, but why do you need to use gdiplus at all?
On 4/24/22 06:27, Nikolay Sivov wrote:
On 4/23/22 20:53, Jinoh Kang wrote:
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52673 Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com
Notes: v1 -> v2: no changes v3 -> v4: - Remove patch "shell32: Factor out ShellItem_get_uiobject." - Use IShellItem2_BindToHandler instead of factoring out ShellItem_get_uiobject - Use CreateCompatibleDC(NULL) instead of GetDC(NULL) - Remove new dependency on win32u, use GetIconInfo instead - Remove new dependency on windowcodecs, use gdiplus instead
I probably missed earlier iterations, but why do you need to use gdiplus at all?
Because you have to convert potentially-transparent HICON to HBITMAP with alpha channel, which is quite a complicated feat.
1. HICON can take many pixel formats, ranging from 32-bit ARGB and monochrome with mask. 2. hbmColor and hbmMask combinations aren't exactly simple to handle. 3. Windows always seems to output a 32-bit ARGB bitmap. GDI routines alone aren't particularly suited for the task (GdiAlphaBlend works with PARGB, not ARGB).
Only WIC and GDI+ has functions to handle most of these.
On Sun, Apr 24, 2022, 2:18 PM Jinoh Kang jinoh.kang.kr@gmail.com wrote:
On 4/24/22 06:27, Nikolay Sivov wrote:
On 4/23/22 20:53, Jinoh Kang wrote:
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52673 Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com
Notes: v1 -> v2: no changes v3 -> v4: - Remove patch "shell32: Factor out ShellItem_get_uiobject." - Use IShellItem2_BindToHandler instead of factoring out ShellItem_get_uiobject - Use CreateCompatibleDC(NULL) instead of GetDC(NULL) - Remove new dependency on win32u, use GetIconInfo instead - Remove new dependency on windowcodecs, use gdiplus instead
I probably missed earlier iterations, but why do you need to use gdiplus
at all?
Because you have to convert potentially-transparent HICON to HBITMAP with alpha channel, which is quite a complicated feat.
- HICON can take many pixel formats, ranging from 32-bit ARGB and
monochrome with mask.
s/and/to/
2. hbmColor and hbmMask combinations aren't exactly simple to handle.
- Windows always seems to output a 32-bit ARGB bitmap. GDI routines alone
aren't particularly suited for the task (GdiAlphaBlend works with PARGB, not ARGB).
Only WIC and GDI+ has functions to handle most of these.
have*
Also, shellole.c already imports GDI+ APIs.
-- Sincerely, Jinoh Kang
On 4/24/22 08:47, Jin-oh Kang wrote:
On Sun, Apr 24, 2022, 2:18 PM Jinoh Kang jinoh.kang.kr@gmail.com wrote:
On 4/24/22 06:27, Nikolay Sivov wrote:
On 4/23/22 20:53, Jinoh Kang wrote:
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52673 Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com
Notes: v1 -> v2: no changes v3 -> v4: - Remove patch "shell32: Factor out ShellItem_get_uiobject." - Use IShellItem2_BindToHandler instead of factoring out ShellItem_get_uiobject - Use CreateCompatibleDC(NULL) instead of GetDC(NULL) - Remove new dependency on win32u, use GetIconInfo instead - Remove new dependency on windowcodecs, use gdiplus instead
I probably missed earlier iterations, but why do you need to use gdiplus
at all?
Because you have to convert potentially-transparent HICON to HBITMAP with alpha channel, which is quite a complicated feat.
- HICON can take many pixel formats, ranging from 32-bit ARGB and
monochrome with mask.
s/and/to/
- hbmColor and hbmMask combinations aren't exactly simple to handle.
- Windows always seems to output a 32-bit ARGB bitmap. GDI routines alone
aren't particularly suited for the task (GdiAlphaBlend works with PARGB, not ARGB).
Only WIC and GDI+ has functions to handle most of these.
have*
Also, shellole.c already imports GDI+ APIs.
Ok, I didn't realize we already do.
-- Sincerely, Jinoh Kang