I create and initialize the TImageList
...
ImageList:=TImageList.Create(self);
ImageList.ShareImages:=true;
I get the system ImageList handle for small icons (16x16)...
ImageList.Handle:=SHGetFileInfo('',0,FileInfo,SizeOf(FileInfo),SHGFI_SYSICONINDEX or SHGFI_SMALLICON);
And now I want to draw the icons on my control canvas scaled to 50x50 pixels. How I do this ?
Upscaling small icons is never good idea. 16X16 icon is too small to use it in any other way other as-is.
For start you can get larger shell images using
ImageList.Handle:=SHGetFileInfo('',0,FileInfo,SizeOf(FileInfo),SHGFI_SYSICONINDEX or SHGFI_ICON);
Those images will be generally 32x32 pix, but to be on safe side (if Windows are running in high DPI mode) you can get correct size from system
uses
Winapi.Windows;
var
IconWidth, IconHeight: integer;
IconWidth := GetSystemMetrics(SM_CXICON);
IconHeight := GetSystemMetrics(SM_CYICON);
You can also get even larger shell images with SHGetImageList
http://msdn.microsoft.com/en-us/library/windows/desktop/bb762185%28v=vs.85%29.aspx
To retrieve icon from you ImageList (if ImageList contains icons, and in your case it does) you can use:
ImageList.GetIcon(Index: Integer; Image: TIcon);
For scaling icons, while preserving transparency, to custom dimension you can use following code:
procedure StretchDrawIcon(Canvas: TCanvas; Dest: TRect; Icon: TIcon);
begin
DrawIconEx(Canvas.Handle, Dest.Left, Dest.Top, Icon.Handle, Dest.Right - Dest.Left, Dest.Bottom - Dest.Top, 0, 0, DI_NORMAL);
end;
Since an extracted Icon can not be stretched with StretchDraw and a extracted Bitmap would lose the transparency one way might be to extract the Icons and manipulate the destination canvas using SetWorldTransform:
uses Shellapi, Math;
Procedure SetCanvasZoomAndRotation(ACanvas:TCanvas;Zoom:Double;Angle:Double;CenterpointX,CenterpointY:Double);
var
form : tagXFORM;
Winkel:Double;
begin
Winkel := DegToRad(Angle);
SetGraphicsMode(ACanvas.Handle, GM_ADVANCED);
SetMapMode(ACanvas.Handle,MM_ANISOTROPIC);
form.eM11 := Zoom * cos( Winkel);
form.eM12 := Zoom *Sin( Winkel) ;
form.eM21 := Zoom * (-sin( Winkel));
form.eM22 := Zoom * cos( Winkel) ;
form.eDx := CenterpointX;
form.eDy := CenterpointY;
SetWorldTransform(ACanvas.Handle,form);
end;
Procedure ResetCanvas(ACanvas:TCanvas);
begin
SetCanvasZoomAndRotation(ACanvas , 1, 0, 0,0);
end;
procedure TDemoForm.Button1Click(Sender: TObject);
var
FileInfo:_SHFileINfoW;
ico:TIcon;
ImageList:TImageList;
i,x,y:Integer;
zoom:double;
begin
ImageList:=TImageList.Create(self);
ImageList.ShareImages:=true;
ImageList.Handle:=SHGetFileInfo('',0,FileInfo,SizeOf(FileInfo),SHGFI_SYSICONINDEX or SHGFI_SMALLICON);
ico:=TIcon.Create;
try
x := 0;
y := 0;
zoom := 50 / Imagelist.Width;
SetCanvasZoomAndRotation(Canvas,zoom,0,0 ,0);
for I := 0 to ImageList.Count-1 do
begin
ImageList.GetIcon(i,ico);
Canvas.Draw(x,y,ico);
inc(x,Imagelist.Width);
if (x + Imagelist.Width) * zoom > width then
begin
x := 0;
inc(y,Imagelist.Height);
end;
end;
finally
ico.Free;
ResetCanvas(Canvas);
ImageList.Free;
end;
end;
An example using 250 as desired size:
TImageList
does not support drawing a scaled image, it draws the image as-is. The only option it provides is to let you specify the X/Y coordinates where the image should be drawn on the destination Canvas.
To scale an image, you will have to extract the desired image to a temporary TBitmap
first and call its Draw()
method, which allows you to specify the desired rectangle on the destination Canvas. The bitmap will then stretch/scale its drawing to fill that rectangle as needed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With