如何向TImageList添加不重复的Icon?
问题原因分析
哈希值全部相同的核心原因
你当前代码里的关键问题是保存位图到流之后,没有把流的指针重置到起始位置。bm.SaveToStream(stream)执行完成后,流的Position属性会停在流的末尾,此时调用THashMD5.GetHashString(stream)相当于对空内容计算哈希,所有结果自然完全一致。
位图对比失效的补充说明
之前你对比位图发现有细微差异,大概率是因为SHGetFileInfo返回的图标可能带有不同尺寸(比如同一文件类型的图标可能有16x16、32x32等不同规格),或者TBitmap在转换图标时,默认的像素格式、调色板处理存在差异,导致看似相同的图标转成位图后出现微小差别。
修正后的代码示例
把流的Position设为0再计算哈希,就能得到正确的结果:
Icon := TIcon.Create; try SHGetFileInfo(PChar(filename), 0, FileInfo, SizeOf(FileInfo), SHGFI_ICON); icon.Handle := FileInfo.hIcon; bm := TBitmap.Create; try icon.AssignTo(bm); stream := TMemoryStream.Create; try bm.SaveToStream(stream); stream.Position := 0; // 关键:重置流指针到开头 hash := System.hash.THashMD5.GetHashString(stream); finally stream.Free; end; finally bm.Free; end; imageid := iconhashlist.IndexOf(hash); if imageid = -1 then begin imageid := imagelist.AddIcon(icon); iconhashlist.Add(hash); end; DestroyIcon(FileInfo.hIcon); finally Icon.Free; end;
更可靠的优化方案
如果想更精准地判断图标是否重复,还可以:
- 调用
SHGetFileInfo时指定固定尺寸的图标(比如加上SHGFI_SMALLICON或SHGFI_LARGEICON参数),避免同一图标不同尺寸被误判为不同项 - 直接对图标的原始数据计算哈希,而不是转成位图:可以通过
GetIconInfo获取图标信息,再读取对应的位图数据进行哈希计算
内容的提问来源于stack exchange,提问作者natraj
相关产品推荐
相关产品推荐

