我只是想知道,如果Windows中有一个用于从字节数组(缓冲区)加载HICON
的API?假设我下载了一个*.ico
文件,我将该文件的内容放在某个缓冲区中。我希望能够从该缓冲区创建HICON
。
可以从放置在硬盘驱动器上的HICON
加载*.ico
,所以我想从内存缓冲区应该有一个同样简单的方法吗?
到目前为止,我发现只有2种解决方案,但它们都不适合我。
第一个involved ATL usage and GDI+(我正在使用Rust,我没有任何绑定到GDI +)。
第二个是基于LookupIconIdFromDirectoryEx()
和CreateIconFromResourceEx()
的使用情况。首先,我调用LookupIconIdFromDirectoryEx()
来获取正确图标的偏移量,然后我尝试调用CreateIconFromResourceEx()
(和CreateIconFromResource()
)来获取HICON,但在所有情况下我都收到{{1}结果,NULL
返回GetLastError()
。我对这些函数的使用基于this article(我试图不仅传递0
作为第二个参数,而且传递数组缓冲区的大小,不包括偏移量,但它仍然失败)。 / p>
我唯一想到的解决方案是手动解析0
文件,然后从中提取PNG图像,然后使用here描述的方法从PNG图像创建图标。但它似乎更像是一种解决方法(Qt使用类似的方法,但也许他们无法找到不同的解决方案)。是否有任何更简单的方法(可能是一些WinAPI调用)来完成工作?
UPD。以下是我尝试的一些测试代码(您应该有一个图标以便运行示例而不会崩溃)。
*.ico
答案 0 :(得分:1)
Intent share = new Intent("android.intent.action.SEND"); share.setType("image/jpeg"); share.putExtra("android.intent.extra.STREAM", Uri.parse(this.imgUrl)); startActivity(Intent.createChooser(share, "via"));
第二个参数不应为零。 Windows不知道在不导致缓冲区溢出的情况下可以读取缓冲区的距离。显然Windows在某些情况下确实允许出现此错误,但对于PNG文件来说可能未准备好,当它没有看到CreateIconFromResourceEx((PBYTE)data + offset, 0, ...)
只需提供最大可用缓冲区大小,即可解决PNG文件的问题:
BITMAPINFOHEADER
文档说CreateIconFromResourceEx((PBYTE)data + offset, fsize - offset, ...)
需要资源数据。该API确实适用于图标文件,它返回第一个图标的偏移量。无论哪种方式,它似乎都没有基于文档所说的错误。
最好手动计算偏移量。看来您已经知道如何计算偏移值。您可以根据ICONDIRENTRY
LookupIconIdFromDirectoryEx
WORD icon_count = 0;
fseek(f, 2 * sizeof(WORD), SEEK_SET);
fread(&icon_count, sizeof(WORD), 1, f);
int offset = 3 * sizeof(WORD) + sizeof(ICONDIRENTRY) * icon_count;
为16。图标文件以3个sizeof(ICONDIRENTRY)
值开头,第三个值为WORD
,后跟icon_count
个字节,后跟第一个{ {1}}
答案 1 :(得分:-2)
我找到了解决方案。实际上经过一些研究后发现,我放在样本中的代码确实是正确的。
WinAPI函数LookupIconIdFromDirectoryEx()
中存在错误。我注意到,对于某些图标,我可以获得正确的图标并进行设置,但对于其他图标,它会在后期CreateIconFromResourceEx()
或早期LookupIconIdFromDirectoryEx()
上失败。我注意到,即使图标在文件中,有时功能也无法找到图标。有时,函数会为图标文件中的不同图标返回相同的值。
我做了几轮测试,并根据format definition自行解析每个图标文件的格式。然后我将实际偏移量与LookupIconIdFromDirectoryEx()
返回的值进行了比较。
假设我们有两个图标:A
和B
。
我案例中的A
图标包含5张图片,ICO文件中的条目按以下顺序排列:
B
图标包含7张图片,按以下顺序排列:
每个图标的LookupIconIdFromDirectoryEx()
结果可以在下面找到。
图标A
:
图标B
:
0
)0
)0
)我解析了实际格式,根据definition in wikipedia(下表包含图标条目,每行是一个单独的条目,每列都是此条目的字段),用于两个图标文件。
A
的实际布局是:
W H * * * ** SIZE OFFSET
------------------------------------------------
0 0 0 0 1 32 43253 86
128 128 0 0 1 32 67624 43339
48 48 0 0 1 32 9640 110963
32 32 0 0 1 32 4264 120603
16 16 0 0 1 32 1128 124867
B
的实际布局是:
W H * * * ** SIZE OFFSET
------------------------------------------------
16 16 0 0 0 32 1128 102
32 32 0 0 0 32 4264 1230
48 48 0 0 0 32 9640 5494
64 64 0 0 0 32 16936 15134
128 128 0 0 0 32 67624 32070
0 0 0 0 0 32 270376 99694
所以你可以清楚地看到,在A
的情况下,只有第一张图像的偏移被识别为正确,其他图像的偏移是不正确的并且等于...第三张图像的大小(?? ),也许只是一个巧合。
在第二张图像的情况下,所有偏移都是正确的,直到我们达到128x128图像,甚至没有找到。
这两种情况之间的共同点是,在解析128x128图标后,该函数开始表现得很奇怪,这是一个有趣的事情 - 查看128x128图标的大小,并将其与其他图像的大小进行比较。在这两种情况下,128x128图像的大小都不适合2个字节。解析大小超过2个字节的图标条目后,函数行为未定义。从这些数据来看,我可以假设在代码中的某个地方,他们期望图标的大小不能超过2个字节。如果大小较大,则行为未定义。
我使用ImageMagick重新组装一个新图标,里面没有这样的图像,现在该功能在所有情况下都能正常工作。
所以我可以肯定地说LookupIconIdFromDirectoryEx()
实施中存在一个错误。