0

在运行时,我想在特定的 MenuItem 中加载并显示特定 .EXE 文件的主图标。如果此特定 .EXE 文件无法执行此操作(例如,由于访问限制或类似原因),则应将 MenuItem 图标设置为特定 ImageList 中的特定图标(例如 MyMenuItem.ImageIndex := 7)。如何才能做到这一点?

4

2 回答 2

2

我认为最简单的解决方案是使用ExtractIconEx. 这是一个非常简单的例子:

type
  PHICON = ^HICON;

function ExtractIconEx(lpszFile: LPCWSTR; nIconIndex: Integer;
  phiconLarge, phiconSmall: PHICON; nIcons: UINT): UINT; stdcall; external 'shell32.dll' name 'ExtractIconExW';

function GetSmallIconFromExecutableFile(const FileName: string): TIcon;
var
  Icon: HICON;
  ExtractedIconCount: UINT;
begin
  Result := nil;
  try
    ExtractedIconCount := ExtractIconEx(
      PChar(FileName),
      0,
      nil,
      @Icon,
      1
    );
    Win32Check(ExtractedIconCount=1);
    Result := TIcon.Create;
    Result.Handle := Icon;
  except
    Result.Free;
    raise;
  end;
end;
于 2013-05-20T19:09:58.310 回答
2

与可执行文件关联的图标是模块中的第一个图标。所以你可以像这样提取它:

function EnumResNameProc(hModule: HMODULE; lpszType: LPCTSTR; lpszName: LPTSTR; lParam: LONG_PTR): BOOL; stdcall;
begin
  HICON(Pointer(lParam)^) := LoadImage(
    hModule,
    lpszName,
    IMAGE_ICON,
    GetSystemMetrics(SM_CXSMICON),
    GetSystemMetrics(SM_CYSMICON),
    0
  );
  Result := False;
end;

function GetFirstSmallIcon(hmod: HMODULE): HICON;
begin
  Result := 0;
  EnumResourceNames(hmod, RT_GROUP_ICON, @EnumResNameProc, NativeInt(@Result));
end;

function GetSmallIconFromExecutableFile(const FileName: string): TIcon;
const
  LOAD_LIBRARY_AS_IMAGE_RESOURCE = $00000020;
var
  hmod: HMODULE;
  Icon: HICON;
begin
  Result := nil;
  try
    hmod := LoadLibraryEx(PChar(FileName), 0, LOAD_LIBRARY_AS_IMAGE_RESOURCE or LOAD_LIBRARY_AS_DATAFILE);
    Win32Check(hmod<>0);
    try
      Icon := GetFirstSmallIcon(hmod);
      if Icon<>0 then begin
        Result := TIcon.Create;
        Result.Handle := Icon;
      end;
    finally
      FreeLibrary(hmod);
    end;
  except
    Result.Free;
    raise;
  end;
end;
于 2013-05-20T19:55:34.173 回答