如何通过ShellExecuteEx打开字体文件?

Han*_*lin 1 delphi windows-shell

我得到一个字体文件的绝对PIDL命名 FontPIDL

我用这段代码打开它:var ShExeInfo:SHELLEXECUTEINFO;

begin
    ZeroMemory(@ShExeInfo, SizeOf(ShExeInfo));

    ShExeInfo.cbSize := SizeOf(ShExeInfo);
    ShExeInfo.lpVerb := 'Open';
    ShExeInfo.lpIDList := FontPIDL;
    ShExeInfo.nShow := SW_SHOWNORMAL;
    ShExeInfo.fMask := SEE_MASK_IDLIST;
end;    
Run Code Online (Sandbox Code Playgroud)

得到一个错误: The parameter is incorrect

我想知道如何解决它?是我想念的一些参数?

更新:

我如何得到字体文件绝对PIDL:

var
  psfDeskTop : IShellFolder;
  psfFont : IShellFolder;
  pEnumList : IEnumIdList;
  pidFont : PItemIdList;
  pidChild : PItemIdList;
  pidAbFont : PItemIdList; 
  FontPath : array[0..MAX_PATH - 1] of Char;
  pchEaten, dwAttributes, ItemsFetched : ULONG;

begin
  FillChar(FontPath, sizeof(FontPath), #0);
  SHGetSpecialFolderPath(0, FontPath, CSIDL_FONTS, False);
  SHGetDesktopFolder(psfDeskTop);
  psfDeskTop.ParseDisplayName(0, nil, FontPath, pchEaten, pidFont,
    dwAttributes);
  psfDeskTop.BindToObject(pidFont, nil, IID_IShellFolder, psfFont);
  psfFont.EnumObjects(0, SHCONTF_FOLDERS or SHCONTF_NONFOLDERS or
    SHCONTF_INCLUDEHIDDEN, pEnumList);
  ItemsFetched := 0;
  while pEnumList.Next(1, pidChild, ItemsFetched) = NO_ERROR do
  begin
    pidAbFont := ILCombine(pidFont , pidChild);
    ///... do something
  end;

end;
Run Code Online (Sandbox Code Playgroud)

Han*_*lin 5

省略lpVerb赋值使代码工作:

begin
    ZeroMemory(@ShExeInfo, SizeOf(ShExeInfo));
    ShExeInfo.cbSize := SizeOf(ShExeInfo);
    // ShExeInfo.lpVerb := 'Open'; will be fail . 
    // use ShExeInfo.lpVerb := '' or ZeroMemory(@ShExeInfo, SizeOf(ShExeInfo)); before
    ShExeInfo.lpIDList := FontPIDL;
    ShExeInfo.nShow := SW_SHOWNORMAL;
    ShExeInfo.fMask := SEE_MASK_IDLIST;
end;    
Run Code Online (Sandbox Code Playgroud)


Rem*_*eau 5

删除ShExeInfo.lpVerb := 'Open';声明有效,但没有其他人说它为什么有效.原因是因为"Open"默认情况下字体文件没有注册动词.通过将lpVerb设置保留为nil,您可以ShellExecuteEx()执行文件类型的实际默认动词,无论它是什么.根据文件:

lpVerb

类型:LPCTSTR

一个字符串,称为动词,指定要执行的操作.可用动词集取决于特定文件或文件夹.通常,对象快捷菜单中的可用动作是可用动词.此参数可以为NULL,在这种情况下,如果可用,则使用默认动词.如果不是,则使用"开放"动词.如果两个动词都不可用,则系统使用注册表中列出的第一个动词.