1

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

我用这段代码打开它: var SheExeInfo : 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;    

得到一个错误: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;
4

3 回答 3

5

Remove the ShExeInfo.lpVerb := 'Open'; statement works, but nobody else has said why it works. The reason is because font files do not have an "Open" verb registered by default. By leaving the lpVerb set to nil, you allow ShellExecuteEx() to execute the actual default verb for the file type, whatever it happens to be. According to the documentation:

lpVerb

Type: LPCTSTR

A string, referred to as a verb, that specifies the action to be performed. The set of available verbs depends on the particular file or folder. Generally, the actions available from an object's shortcut menu are available verbs. This parameter can be NULL, in which case the default verb is used if available. If not, the "open" verb is used. If neither verb is available, the system uses the first verb listed in the registry.

于 2012-11-28T19:34:04.703 回答
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;    
于 2012-11-28T09:11:07.927 回答
1

我给你做了一个样品:

var
    ShExeInfo: TShellExecuteInfo;
    ExecuteFile: string;
begin
    ZeroMemory(@ShExeInfo, SizeOf(ShExeInfo));
    ExecuteFile:='D:\SoftWare\font\BDavat.ttf';
    FillChar(ShExeInfo, SizeOf(ShExeInfo), 0) ;
    ShExeInfo.cbSize := SizeOf(TShellExecuteInfo) ;
    with ShExeInfo do
    begin
      //lpVerb := 'Open';
      fMask := SEE_MASK_NOCLOSEPROCESS;
      Wnd := Application.Handle;
      lpFile := PWideChar(ExecuteFile) ;
      nShow := SW_SHOWNORMAL;
    end;
    ShellExecuteEx(@ShExeInfo) ;
end;

获取它们的路径的功能:

uses
  ShlObj, ActiveX;

const
  CSIDL_FLAG_CREATE = $8000;
  CSIDL_ADMINTOOLS = $0030;
  CSIDL_ALTSTARTUP = $001D;
  CSIDL_APPDATA = $001A;
  CSIDL_BITBUCKET = $000A;
  CSIDL_CDBURN_AREA = $003B;
  CSIDL_COMMON_ADMINTOOLS = $002F;
  CSIDL_COMMON_ALTSTARTUP = $001E;
  CSIDL_COMMON_APPDATA = $0023;
  CSIDL_COMMON_DESKTOPDIRECTORY = $0019;
  CSIDL_COMMON_DOCUMENTS = $002E;
  CSIDL_COMMON_FAVORITES = $001F;
  CSIDL_COMMON_MUSIC = $0035;
  CSIDL_COMMON_PICTURES = $0036;
  CSIDL_COMMON_PROGRAMS = $0017;
  CSIDL_COMMON_STARTMENU = $0016;
  CSIDL_COMMON_STARTUP = $0018;
  CSIDL_COMMON_TEMPLATES = $002D;
  CSIDL_COMMON_VIDEO = $0037;
  CSIDL_CONTROLS = $0003;
  CSIDL_COOKIES = $0021;
  CSIDL_DESKTOP = $0000;
  CSIDL_DESKTOPDIRECTORY = $0010;
  CSIDL_DRIVES = $0011;
  CSIDL_FAVORITES = $0006;
  CSIDL_FONTS  = $0014;
  CSIDL_HISTORY = $0022;
  CSIDL_INTERNET = $0001;
  CSIDL_INTERNET_CACHE = $0020;
  CSIDL_LOCAL_APPDATA = $001C;
  CSIDL_MYDOCUMENTS = $000C;
  CSIDL_MYMUSIC = $000D;
  CSIDL_MYPICTURES = $0027;
  CSIDL_MYVIDEO = $000E;
  CSIDL_NETHOOD = $0013;
  CSIDL_NETWORK = $0012;
  CSIDL_PERSONAL = $0005;
  CSIDL_PRINTERS = $0004;
  CSIDL_PRINTHOOD = $001B;
  CSIDL_PROFILE = $0028;
  CSIDL_PROFILES = $003E;
  CSIDL_PROGRAM_FILES = $0026;
  CSIDL_PROGRAM_FILES_COMMON = $002B;
  CSIDL_PROGRAMS = $0002;
  CSIDL_RECENT = $0008;
  CSIDL_SENDTO = $0009;
  CSIDL_STARTMENU = $000B;
  CSIDL_STARTUP = $0007;
  CSIDL_SYSTEM = $0025;
  CSIDL_TEMPLATES = $0015;
  CSIDL_WINDOWS = $0024;

function GetShellFolder(CSIDL: integer): string;
var
  pidl                   : PItemIdList;
  FolderPath             : string;
  SystemFolder           : Integer;
  Malloc                 : IMalloc;
begin
  Malloc := nil;
  FolderPath := '';
  SHGetMalloc(Malloc);
  if Malloc = nil then
  begin
    Result := FolderPath;
    Exit;
  end;
  try
    SystemFolder := CSIDL;
    if SUCCEEDED(SHGetSpecialFolderLocation(0, SystemFolder, pidl)) then
    begin
      SetLength(FolderPath, max_path);
      if SHGetPathFromIDList(pidl, PChar(FolderPath)) then
      begin
        SetLength(FolderPath, length(PChar(FolderPath)));
      end;
    end;
    Result := FolderPath;
  finally
    Malloc.Free(pidl);
  end;
end;

如何使用:

ShowMessage(GetShellFolder(CSIDL_FONTS));

测试一下,希望对你有帮助...

于 2012-11-28T07:37:36.083 回答