Delphi and 48x48 (or bigger) imagelists - is there a workaround?
I'm getting the system imagelist (with SHGetFileInfo and SHGFI_LARGEICON), adding two of my own icons and attaching it to a TListView.
The problem is that if the user's icon size isn't set to 32x32 (like it's set to 48x48 for example) the Delphi7 TImageList fails with an "Invalid image size" error.
Does anyone know if a workaround is ava开发者_如何转开发ilable? I've tried using TPngImageList but it leads to other issues.
Also, please note that I'd like to preserve the Alpha channel of the icons. Normal 1-bit transparency is not enough, as icons tend to look ugly that way.
Thanks!
I'm not aware of any limitation on the size of images that TImageList
can hold. It sounds to me that your problem is that you have icons of different sizes and you can't hold icons of different sizes in the same image list.
If you are working with icons of different sizes then you are going to need to grow the smaller ones in size. You'll have to build it up in code, using a bitmap. You fill the bitmap with pure transparent alpha channel and then blt the smaller icon onto the centre of the bitmap.
Another option would be to maintain two separate image lists but if you need to draw the icons into the same list view then I think that won't get the job done. My guess is that you'll need to grow the small icons.
For alpha, you're going to need to create the image list handle yourself because the ColorDepth property doesn't exist in D7. Because of this, a vanilla D7 TImageList
simply cannot support icons with alpha channels.
You work around this limitation by calling ImageList_Create
, passing ILC_COLOR32
and assigning the result to ImageList.Handle
. Do this before you add any images. You'll have to populate the list at run time rather than design time, but it sounds like you are already doing that.
Here's a screen shot of a 48x48 tool button with a 32bpp icon with alpha transparency:
It's true that I made this in D2010, but my above workaround will work for D7 – I used that mechanism until quite recently with D6. I'm just showing this to prove that the image list can hold 48px icons. Since TImageList
is just a wrapper around the system image list component, I believe what you are attempting should be perfectly feasible.
Just when I was about to give up this page led me to the solution: http://delphihaven.wordpress.com/2010/09/06/custom-drawing-on-glass-2/
Apparently, if you try to add an icon that is bigger than 32x32 to a timagelist in Delphi7, the VCL will give you an "Invalid image size" error while it could simply call the himagelist API - which can easily handle it.
Here is the complete solution:
unit ImageListFix;
interface
uses CommCtrl, Graphics, ImgList;
type
TImageListFixer = class(TCustomImageList)
public
function AddIcon(Image: TIcon): Integer;
end;
implementation
function TImageListFixer.AddIcon(Image: TIcon): Integer;
begin
if Image = nil then
Result := Add(nil, nil)
else
begin
Result := ImageList_AddIcon(Handle, Image.Handle);
Change;
end;
end;
end.
And the code for adding icons to the system imagelist:
DocumentImgList:=TImageListFixer(GetSystemLargeIconsList);
IconToAdd:=TIcon.Create;
try
IconToAdd.Handle := LoadImage(0, 'c:\Ico1.ico', IMAGE_ICON, DocumentImgList.Width, DocumentImgList.Height, LR_LOADFROMFILE);
DocumentImgList.AddIcon(IconToAdd);
IconToAdd.Handle := LoadImage(0, 'c:\Ico2.ico', IMAGE_ICON, DocumentImgList.Width, DocumentImgList.Height, LR_LOADFROMFILE);
DocumentImgList.AddIcon(IconToAdd);
finally
IconToAdd.Free;
end;
TImageList raises an "Invalid image size" error under only 2 conditions:
1) The TImageList's Height or Width property is less than 1, or the Height property is greater than 32768, when the TImageList is initially created via the CreateSize() constructor (there are no such limitations imposed by the Height and Width property setters).
2) you try to add/insert a new TBitmap or TIcon whose dimensions do not fit within TImageList's internal image.
精彩评论