Unable to display an Icon on a Menu added at run time to a Virtual Image List

Viewed 448

I cannot get an icon to appear on a menu item added at run time. I am adding a menu item to the main menu whose images property are linked to a TVirtualImageList which is linked to a TImageCollection. All the fixed images are held in the Virtual Image list and at run time I add additional menu items adding each image as an Icon to the Virtual Image List. The main menu has a dummy menu item to which the additional menus are attached.

function LoadIconFromFile(FileName: String; Var Icon: TIcon): Integer;  overload;
var SHInfo: TSHFileInfo;
begin
  Result := -1;
  if not FileExists(FileName) then exit;
  SHGetFileInfo(PChar(FileName), 0, SHInfo, SizeOf(SHInfo), SHGFI_ICON OR SHIL_LARGE);
  Icon.Handle := SHInfo.hIcon;
  Icon.Transparent := true;
  result := $1000;
end;    

TmpIcon := TIcon.Create;
LoadIconFromFile(FileName, TmpIcon);
MenuItem.ImageIndex := vilMenues.AddIcon(TmpIcon);
image1.Picture.Graphic := TmpIcon;
TmpIcon.Free;
MainMenu.BaseMenuItem.Add(MenuItem);

Just to ensure I was actually picking up the icon correctly I also display in a TImage. The additional menu item gets added and the Icon appears in the TImage control but never appears on the menu. I know the image gets added to the image list because the Image Count increases. I have tried detaching the image list from the mainmenu before updating and reattaching after but that has made no difference. I am beginning to wonder whether TVirtualImageList is capable of handling mixed sources of images?

Can anyone advise me what I might do to solve this issue?

2 Answers

TImageCollection doesn't support icons.

When you use the AddIcon method, TCustomImageList.AddIcon calls the overridden method TVirtualImageList.DoChange which updates the entire virtual image list from the image collection.

So if you have 3 images in the virtual image list and call AddIcon, it'll return a new image index of 3 and there are now 4 images in the list. But then the virtual image list is recreated and its Count is back to 3.

I got it to work with the following code:

TmpIcon := TIcon.Create;
Strm := TMemoryStream.Create;
LoadIconFromFile(FileName, TmpIcon);// get icon from file
tmpIcon.SaveToStream(Strm);
s := 'X'+IntToStr(idx);  // Add a name for new item
ImageCollection1.Add(s, strm);  // Add to collection
idy:= ImageCollection1.Count -1;  // Get the index for it
vilMenues.Add(s,idy);  // Add it to virtual image list
MenuItem.ImageIndex := vilMenues.Count -1;
Strm.Free;
TmpIcon.Free;

Rather clumsy I feel there must be a better way...

Related