1

フォントファイルの絶対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;    

エラーが発生します: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

割り当てを省略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 に答える
5

ステートメントを削除するShExeInfo.lpVerb := 'Open';と機能しますが、なぜ機能するのかは誰も言っていません。"Open"これは、フォントファイルにはデフォルトで動詞が登録されていないためです。lpVerbに設定したままにしておくと、ファイルタイプの実際のデフォルトの動詞を、それが何であれ、実行nilできるようになります。ドキュメントShellExecuteEx()によると:

lpVerb

タイプ:LPCTSTR

実行するアクションを指定する、動詞と呼ばれる文字列。使用可能な動詞のセットは、特定のファイルまたはフォルダーによって異なります。通常、オブジェクトのショートカットメニューから使用できるアクションは、使用可能な動詞です。このパラメーターはNULLにすることができます。その場合、使用可能な場合はデフォルトの動詞が使用されます。そうでない場合は、「open」動詞が使用されます。どちらの動詞も使用できない場合、システムはレジストリにリストされている最初の動詞を使用します。

于 2012-11-28T19:34:04.703 に答える
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 に答える