Skip to content

Commit 3c15540

Browse files
authored
Merge pull request #1977 from aybe/fix-icon-overlay
Fix spurious folder icon overlay
2 parents 1d573ef + 79de997 commit 3c15540

File tree

1 file changed

+76
-20
lines changed

1 file changed

+76
-20
lines changed

third_party/ImFileDialog/ImFileDialog.cpp

Lines changed: 76 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@
1717

1818
#ifdef _WIN32
1919
#include <windows.h>
20+
#include <commctrl.h>
21+
#include <commoncontrols.h>
2022
#include <shellapi.h>
2123
#include <lmcons.h>
24+
#pragma comment(lib, "Comctl32.lib")
2225
#pragma comment(lib, "Shell32.lib")
2326
#else
2427
#include <unistd.h>
@@ -33,6 +36,74 @@
3336
static std::string u8StringToString(const std::u8string& str) {
3437
return reinterpret_cast<const char*>(str.c_str());
3538
}
39+
40+
namespace
41+
{
42+
struct Image
43+
{
44+
std::vector<uint8_t> Pixels;
45+
int Width, Height;
46+
};
47+
48+
#ifdef _WIN32
49+
std::optional<Image> GetFileIconWin32(const SHFILEINFOW& sfi)
50+
{
51+
auto list = static_cast<HIMAGELIST>(nullptr);
52+
53+
if (FAILED(SHGetImageList(SHIL_LARGE, IID_IImageList, reinterpret_cast<void**>(&list))))
54+
{
55+
return std::nullopt;
56+
}
57+
58+
const auto icon = ImageList_GetIcon(list, sfi.iIcon, ILD_NORMAL);
59+
60+
if (icon == nullptr)
61+
{
62+
return std::nullopt;
63+
}
64+
65+
std::optional<Image> image;
66+
67+
ICONINFO info = {};
68+
69+
if (GetIconInfo(icon, &info))
70+
{
71+
if (info.hbmColor != nullptr)
72+
{
73+
DIBSECTION ds = {};
74+
75+
if (GetObject(info.hbmColor, sizeof(ds), &ds))
76+
{
77+
const auto bm = ds.dsBm;
78+
const auto bw = bm.bmWidth;
79+
const auto bh = bm.bmHeight;
80+
81+
if (const auto size = bw * bh * (bm.bmBitsPixel / 8); size > 0)
82+
{
83+
auto bits = std::vector<uint8_t>();
84+
85+
bits.resize(size);
86+
87+
if (GetBitmapBits(info.hbmColor, size, bits.data()))
88+
{
89+
image = Image{.Pixels = bits, .Width = bw, .Height = bh};
90+
}
91+
}
92+
}
93+
}
94+
95+
DeleteObject(info.hbmColor);
96+
97+
DeleteObject(info.hbmMask);
98+
}
99+
100+
DestroyIcon(icon);
101+
102+
return image;
103+
}
104+
#endif
105+
}
106+
36107
namespace ifd {
37108
static const char* GetDefaultFolderIcon();
38109
static const char* GetDefaultFileIcon();
@@ -748,27 +819,12 @@ namespace ifd {
748819
m_iconIndices.push_back(fileInfo.iIcon);
749820
m_iconFilepaths.push_back(pathU8);
750821

751-
ICONINFO iconInfo = { 0 };
752-
GetIconInfo(fileInfo.hIcon, &iconInfo);
753-
754-
if (iconInfo.hbmColor == nullptr)
755-
return nullptr;
756-
757-
DIBSECTION ds;
758-
GetObject(iconInfo.hbmColor, sizeof(ds), &ds);
759-
int byteSize = ds.dsBm.bmWidth * ds.dsBm.bmHeight * (ds.dsBm.bmBitsPixel / 8);
760-
761-
if (byteSize == 0)
762-
return nullptr;
763-
764-
uint8_t* data = (uint8_t*)malloc(byteSize);
765-
GetBitmapBits(iconInfo.hbmColor, byteSize, data);
766-
767-
m_icons[pathU8] = this->CreateTexture(data, ds.dsBm.bmWidth, ds.dsBm.bmHeight, 0);
768-
769-
free(data);
822+
if (auto image = GetFileIconWin32(fileInfo); image.has_value())
823+
{
824+
return m_icons[pathU8] = this->CreateTexture(image->Pixels.data(), image->Width, image->Height, 0);
825+
}
770826

771-
return m_icons[pathU8];
827+
return nullptr;
772828
#else
773829
if (m_icons.count(u8StringToString(path.u8string())) > 0)
774830
return m_icons[u8StringToString(path.u8string())];

0 commit comments

Comments
 (0)