在Vista或更高版本Windows系统中, 获取超大图标的办法

这几天写个小东西, 需要获取系统正在运行的程序图标, 一般来说32*32就足够了, 不过既然Win7能够支持超大图标(256*256), 咱们也需要与时俱进, 说不定什么时候遇到个变态客户就有这要求了

找了下以前的资料, 获取程序图标基本都是用SHGetFileInfo来获取, 这样只能得到最大32*32的

想获取超大的需要用SHGetImageList这个API, 不过很奇怪Delphi里面虽然有这个API, 可是调用出错, 只能从DLL里面重新加载了

网上相关资料很少, 但是还是能找到的, 不过不知道为什么, 找到的都是一样的代码, 相对下面的代码网上的资料都是这样获取图标句柄的

Result := ImageList_GetIcon(nImageList, Pred(ImageList_GetImageCount(nImageList)), ILD_NORMAL);

虽然执行结果一样, 但是很让人费解, 另外, 这样做如果在程序内多次获取多个程序的图标就会出现得到的都是一样的图标的问题(是一个BUG)

解决方法: SHGetFileInfo函数本来就是获取图标索引的, 直接使用得到的结果就行了

Result := ImageList_GetIcon(nImageList, nFileInfo.iIcon, ILD_NORMAL);

完整函数如下

uses
    ShellAPI, CommCtrl;

const
  SHIL_LARGE = 0; {32x32}
  SHIL_SMALL = 1; {16x16}
  SHIL_EXTRALARGE = 2; {48x48}
  SHIL_SYSSMALL = 3; {16x16}
  SHIL_JUMBO = 4; {256x256}

function GetFileIconEX(AFile: string; ASHIL_FLAG: Cardinal): HICON;

  function _X: Boolean; {判断是否符合系统版本}
  begin
    Result := False;
    if Win32MajorVersion < 5 then
      Exit;
    if (Win32MajorVersion = 5) and (Win32MinorVersion < 1) then
      Exit;
    Result := True;
  end;

type
  _SHGetImageList = function (iImageList: Integer; const riid: TGUID;
    var ppvObj: Pointer): HResult; stdcall;
var
  nHandle: THandle;
  nImageList: HIMAGELIST;
  nSHGetImageList: _SHGetImageList;
  nFileInfo: TSHFileInfo;
const
  IID_IImageList: TGUID = '{46EB5926-582E-4017-9FDF-E8998DAA0950}';
begin
  Result := 0;
  nHandle:= LoadLibrary('Shell32.dll');
  nImageList := 0;
  if nHandle <> S_OK then
  try
    nSHGetImageList := GetProcAddress(nHandle, PChar(727));
    if Assigned(nSHGetImageList) and _X then
      nSHGetImageList(ASHIL_FLAG, IID_IImageList, Pointer(nImageList));
  finally
    FreeLibrary(nHandle);
  end;
  if nImageList > 0 then
  begin
    SHGetFileInfo(PChar(AFile), FILE_ATTRIBUTE_NORMAL, nFileInfo, SizeOf(TSHFileInfo),
      SHGFI_SYSICONINDEX);
    Result := ImageList_GetIcon(nImageList, nFileInfo.iIcon, ILD_NORMAL);
  end;
end;
原文地址:https://www.cnblogs.com/lzl_17948876/p/3342304.html