【问题标题】:How to load an icon from resources to a TImage?如何将资源中的图标加载到 TImage?
【发布时间】:2020-12-09 14:00:00
【问题描述】:

我尝试了以下代码,但它不起作用...LoadIconWithScaleDown 返回一个否定的错误代码。

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls,
  Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    procedure FormCreate(Sender: TObject);
    procedure LoadResToImg(RID: String; const Img: TImage);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
{$R UserResources.res}

uses Winapi.CommCtrl;

procedure TForm1.LoadResToImg(RID: String; const Img: TImage);
var Ico: TIcon;
    hI: HICON;
    HR: HResult;
begin
 Ico:= TIcon.Create;
 HR:= LoadIconWithScaleDown(HInstance, PChar(RID), Img.Width, Img.Height, hI);
 Ico.Handle:= hI;
 Img.Picture.Bitmap.Assign(Ico);
 Ico.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 LoadResToImg('OFFLINE', Image1);
end;

end.

UserResources.rc

OFFLINE      ICON    "gray_button.ico"
ONLINE       ICON    "green_button.ico" 

【问题讨论】:

  • 图片上有const,但字符串上没有。它“应该”是相反的!
  • 所以像TImage 这样的对象即使没有const 也是通过引用传递的?
  • 是的,对象总是通过引用传递。字符串使用 COW 语义,使用 const 编译器不需要更新引用计数。

标签: image delphi resources delphi-10.3-rio


【解决方案1】:

这可能是因为这个 Win32 函数的 VCL 包装器(Winapi.CommCtrl.pas)有问题,或者至少不能立即使用。

所以改为自己声明:

function LoadIconWithScaleDown(hinst: HINST; pszName: LPCWSTR; cx: Integer;
    cy: Integer; var phico: HICON): HResult; stdcall; external 'ComCtl32';

但请注意,此功能仅存在于 Windows Vista+ (IIRC) 上。

【讨论】:

  • 确实如此!现在可以使用...谢谢!这让我发疯了大约 4 个小时......
  • 或者,您可以在使用LoadIconWithScaleDown 之前调用InitCommonControlsEx,但从Win32 的角度来看,我认为这没有必要。
  • "但请注意,此函数仅存在于 Windows Vista+ (IIRC) 上。" - 在这种情况下,您应该在函数声明中包含 delayed keyword,并且然后根本不在 Vista 之前的系统上运行时调用该函数
  • @RemyLebeau:或者老派:LoadLibrary + GetProcAddress。如果您使用的是旧版本的 Delphi,则必须这样做。
  • @AndreasRejbrand 确实是旧版本,因为 delayed 是在 D2010 中引入的。
【解决方案2】:

如 cmets 中所述,您也可以使用 InitCommonControlsEx 执行相同的操作。 我认为 Andreas 回答中的方法更简单,但如果有人更喜欢使用 InitCommonControlsEx,这里是代码:

uses
  Winapi.Windows, Winapi.CommCtrl;

...

var
  IconHandle : HICON;
  ICC: TInitCommonControlsEx;
begin
  ICC.dwSize := SizeOf(TInitCommonControlsEx);
  ICC.dwICC := ICC_BAR_CLASSES;

  if(not InitCommonControlsEx(ICC)) then
    raise Exception.Create('InitCommonControlsEx error');

  if(LoadIconWithScaleDown(0, MAKEINTRESOURCE(<your res id>), 32, 32, IconHandle) <> S_OK) then
    raise Exception.Create('LoadIconWithScaleDown error');

  <here you can use IconHandle as you need>
end;

注意:我测试过它通过IDI_INFORMATION&lt;your res id&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-25
    • 1970-01-01
    • 2018-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-11
    相关资源
    最近更新 更多