I'm just wondering, if there an API in Windows for loading the HICON
from the byte array (buffer)? Let's say that I downloaded an *.ico
file and I have the content of this file in some buffer. I want to be able to create the HICON
from that buffer.
It is possible to load HICON
from the *.ico
which is placed on the hard drive, so I guess that there should be an equally simple way to do it from the memory buffer?
So far I found only 2 solutions but none of them is suitable for me.
The first one involved ATL usage and GDI+ (I'm using Rust and I don't have any bindings to GDI+).
The second one was based on usage of LookupIconIdFromDirectoryEx()
and CreateIconFromResourceEx()
. First I called LookupIconIdFromDirectoryEx()
to get the offset for the correct icon and then I tried to call CreateIconFromResourceEx()
(and CreateIconFromResource()
) to get the HICON, but in all cases I receive a NULL
value as a result, GetLastError()
returns 0
though. My usage of those functions was based on this article (I tried to pass not only 0
as a second parameter, but also the size of the array buffer, excluding the offset, but it still fails).
The only remaining solution which I have in mind is to parse the *.ico
file manually and then extract PNG images from it, then use the approach described here to create an icon from the PNG image. But it seems to be more like a workaround (Qt uses the similar approach though, maybe they were not able to find a different solution). Are there any simplier methods (maybe some WinAPI call) to get the things done?
UPD. Here is some test code which I tried (you should have an icon in order to run the example without crashes).
#include <cstdio>
#include <cstdlib>
#include <Windows.h>
#pragma comment(lib, "User32.lib")
int main()
{
// Read the icon into the memory
FILE* f = fopen("icon.ico", "rb");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
char* data = (char*)malloc(fsize + 1);
fread(data, fsize, 1, f);
fclose(f);
static const int icon_size = 32;
int offset = LookupIconIdFromDirectoryEx((PBYTE)data, TRUE, icon_size, icon_size, LR_DEFAULTCOLOR);
if (offset != 0) {
HICON hicon = CreateIconFromResourceEx((PBYTE)data + offset, 0, TRUE, 0x30000, icon_size, icon_size, LR_DEFAULTCOLOR);
if (hicon != NULL) {
printf("SUCCESS");
return 0;
}
}
printf("FAIL %d", GetLastError());
return 1;
}