Reputation: 2101
I'm adding icons to my project via Resources and Images dialog, and decided to walk away from TIcon.LoadFromResourceName
because it does not perform any error checking. I wrote seemingly equivalent code but does not work as expected.
Here is a testcase which fails for me:
procedure TForm1.FormCreate(Sender: TObject);
const
ResName = 'Icon_1';
var
Stream: TResourceStream;
begin
OutputDebugString(PChar(Format('RTLVersion = %f', [RTLVersion])));
Assert(Assigned(Image1), 'Image1 comes from the designer, should be instantiated already');
Stream := TResourceStream.Create(HInstance, ResName, RT_GROUP_ICON);
try
Image1.Picture.Icon.LoadFromStream(Stream); // AV here
finally
Stream.Free;
end;
end;
A/V occurs deeply inside library at write of address 0x00000008, which suggest some uninitialized object instance.
I'm doing anything wrong or it is a library bug? Library version is 23.0, Delphi XE2
Upvotes: 2
Views: 889
Reputation: 2101
I was confusing RT_GROUP_ICON
and RT_ICON
. RT_GROUP_ICON
contains only icon header and directory (GRPICONDIR
and GRPICONDIRENTRY
respectively), but actual images and masks are stored separately as RT_ICON
resources. Additionally, icon file headers and icon group headers have exactly same layout and magic values, making detection of invalid data stream impossible. Therefore, it is absolutely not possible to use TIcon.LoadFromStream
with RT_GROUP_ICON
resource, this method has been designed for disk files only.
Thanks to bummi for shedding a light onto this nuance.
Additional reading: LookupIconIdFromDirectoryEx
function reference and the corresponding example code.
Upvotes: 3
Reputation: 598134
I do not know if you can load an RT_GROUP_ICON
resource into a TIcon
using LoadFromStream()
, but there are alternate solutions:
Image1.Picture.Icon.Handle := LoadIcon(HInstance, ResName);
Or:
Image1.Picture.Icon.Handle := LoadImage(HInstance, ResName, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
Or:
Image1.Picture.Icon.Handle := CreateIconFromResourceEx(PByte(Stream.Memory), Stream.Size, TRUE, $00030000, 0, 0, LR_DEFAULTSIZE);
Upvotes: 1