8

我创建并初始化TImageList...

ImageList:=TImageList.Create(self);
ImageList.ShareImages:=true;

我得到了小图标(16x16)的系统 ImageList 句柄......

ImageList.Handle:=SHGetFileInfo('',0,FileInfo,SizeOf(FileInfo),SHGFI_SYSICONINDEX or SHGFI_SMALLICON);

现在我想在缩放到 50x50 像素的控制画布上绘制图标。我该怎么做?

4

3 回答 3

10

升级小图标从来都不是好主意。16X16 图标太小,无法按原样以任何其他方式使用它。

首先,您可以使用获取更大的 shell 图像

ImageList.Handle:=SHGetFileInfo('',0,FileInfo,SizeOf(FileInfo),SHGFI_SYSICONINDEX or SHGFI_ICON);

这些图像通常为 32x32 像素,但为了安全起见(如果 Windows 以高 DPI 模式运行),您可以从系统获得正确的尺寸

uses
  Winapi.Windows;

var
  IconWidth, IconHeight: integer;

  IconWidth := GetSystemMetrics(SM_CXICON);
  IconHeight := GetSystemMetrics(SM_CYICON);

您还可以使用http://msdn.microsoft.com/en-us/library/windows/desktop/bb762185%28v=vs.85%29.aspx获得更大的 shell 图像SHGetImageList

要从 ImageList 中检索图标(如果 ImageList 包含图标,并且在您的情况下包含图标),您可以使用:

ImageList.GetIcon(Index: Integer; Image: TIcon);

对于缩放图标,同时保持透明度,自定义尺寸,您可以使用以下代码:

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;
于 2014-11-25T20:48:38.693 回答
9

由于无法使用 StretchDraw 拉伸提取的图标,并且提取的位图会失去透明度,因此一种方法可能是提取图标并使用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;

使用 250 作为所需大小的示例: 在此处输入图像描述

于 2014-11-25T20:21:17.007 回答
3

TImageList不支持绘制缩放图像,它按原样绘制图像。它提供的唯一选项是让您指定应在目标 Canvas 上绘制图像的 X/Y 坐标。

要缩放图像,您必须先将所需图像提取到临时图像TBitmap并调用其Draw()方法,该方法允许您在目标 Canvas 上指定所需的矩形。然后,位图将根据需要拉伸/缩放其绘图以填充该矩形。

于 2014-11-25T20:05:12.617 回答