如何正确调用 SHGetImageList?是否可以用它检索 HIMAGELIST?

How do I invoke SHGetImageList properly? Is it possible to retrieve HIMAGELIST with it?

我正在尝试检查 shell 的共享图像列表,遵循看似简单(但实际上不是很清楚)PSDK documentation 包括 我可以自由评论的内容在 HIMAGELISTIImageList 类型之间进行转换 (我后来发现的第一件事很可疑)。所以,我写了下面的代码:

procedure TForm1.FormCreate(Sender: TObject);
const
  IID_IImageList: TGUID = '{46EB5926-582E-4017-9FDF-E8998DAA0950}';
  IID_IImageList2: TGUID = '{192B9D83-50FC-457B-90A0-2B82A8B5DAE1}';
var
  himl: HIMAGELIST;
begin
  CoInitialize(nil);

  OleCheck(SHGetImageList(SHIL_LARGE, IID_IImageList, Pointer(himl)));
  ImageList1.Handle := himl;
end;

但效果很差:API 调用 returns HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER) 然后因多次访问冲突而崩溃,这表明应用程序和库之间存在一些二进制不一致。但是,我使用的 Delphi 函数导入看起来是正确的:

function SHGetImageList(iImageList: Integer; const riid: TGUID; 
  var ppvObj: Pointer): HResult;
function SHGetImageList; external shell32 name 'SHGetImageList' delayed;

我在文档中发现的第二个令人困惑的是 riid 参数描述仅列出一个可能的值 - IID_IImageList这可能与我检索句柄类型的意图不符。

那么,如何正确调用 SHGetImageList? 是否可以用它检索 HIMAGELIST

So, how do I invoke SHGetImageList properly?

函数输出是一个接口,所以需要声明一个接口变量:

procedure TForm1.FormCreate(Sender: TObject);
var
  iml: IImageList;
begin
  CoInitialize(nil);
  OleCheck(SHGetImageList(SHIL_LARGE, IImageList, Pointer(iml)));
end;

And is it possible to retrieve HIMAGELIST with it?

根据 documentation:

The IImageList pointer type, such as that returned in the ppv parameter, can be cast as an HIMAGELIST as needed; for example, for use in a list view. Conversely, an HIMAGELIST can be cast as a pointer to an IImageList.

procedure TForm1.FormCreate(Sender: TObject);
var
  iml: IImageList;
begin
  CoInitialize(nil);
  OleCheck(SHGetImageList(SHIL_LARGE, IImageList, Pointer(iml)));
  ImageList1.Handle := HIMAGELIST(iml); // or HIMAGELIST(Pointer(iml));
end;

问题出在 Delphi 在 ShellAPI 单元中的库存申报。它缺少 stdcall 调用约定。要解决此问题,您可以在自己的代码中手动声明函数:

function SHGetImageList(iImageList: Integer; const riid: TGUID;
  var ppvObj: Pointer): HResult; stdcall; external shell32;

procedure TTestForm.Button1Click(Sender: TObject);
const
  IID_IImageList: TGUID = '{46EB5926-582E-4017-9FDF-E8998DAA0950}';
var
  himl: HIMAGELIST;
begin
  //CoInitialize(nil);
  OleCheck(SHGetImageList(SHIL_LARGE, IID_IImageList, Pointer(himl)));
  ImageList1.Handle := himl;
end;

注意:如果您不删除项目源中的 Application.Initialize 调用,VCL 应用程序已经调用 CoInitialize