|
17 | 17 |
|
18 | 18 | #ifdef _WIN32 |
19 | 19 | #include <windows.h> |
| 20 | +#include <commctrl.h> |
| 21 | +#include <commoncontrols.h> |
20 | 22 | #include <shellapi.h> |
21 | 23 | #include <lmcons.h> |
| 24 | +#pragma comment(lib, "Comctl32.lib") |
22 | 25 | #pragma comment(lib, "Shell32.lib") |
23 | 26 | #else |
24 | 27 | #include <unistd.h> |
|
33 | 36 | static std::string u8StringToString(const std::u8string& str) { |
34 | 37 | return reinterpret_cast<const char*>(str.c_str()); |
35 | 38 | } |
| 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 | + |
36 | 107 | namespace ifd { |
37 | 108 | static const char* GetDefaultFolderIcon(); |
38 | 109 | static const char* GetDefaultFileIcon(); |
@@ -748,27 +819,12 @@ namespace ifd { |
748 | 819 | m_iconIndices.push_back(fileInfo.iIcon); |
749 | 820 | m_iconFilepaths.push_back(pathU8); |
750 | 821 |
|
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 | + } |
770 | 826 |
|
771 | | - return m_icons[pathU8]; |
| 827 | + return nullptr; |
772 | 828 | #else |
773 | 829 | if (m_icons.count(u8StringToString(path.u8string())) > 0) |
774 | 830 | return m_icons[u8StringToString(path.u8string())]; |
|
0 commit comments