Search code examples
windowsdelphifonts

How do I get the font name from a font file?


I want to enumerate all the file in the C:\Windows\Fonts\

First I use FindFirst&FindNext to get all the file

Code:

Path := 'C:\Windows\Fonts';
  if FindFirst(Path + '\*', faNormal, FileRec) = 0 then
    repeat

      Memo1.Lines.Add(FileRec.Name);

    until FindNext(FileRec) <> 0;
  FindClose(FileRec);

it get some name like this tahoma.ttf which display Tahoma regular in windows font folder .

but how can I get that ?

second I why can't enumerate files in C:\Windows\Fonts\ by shell

Code :

var
  psfDeskTop : IShellFolder;
  psfFont : IShellFolder;
  pidFont : PITEMIDLIST;
  pidChild : PITEMIDLIST;
  pidAbsolute : PItemIdList;
  FileInfo : SHFILEINFOW;
  pEnumList : IEnumIDList;
  celtFetched : ULONG;
begin
  OleCheck(SHGetDesktopFolder(psfDeskTop));
  //Font folder path
  OleCheck(SHGetSpecialFolderLocation(0, CSIDL_FONTS, pidFont));
  OleCheck(psfDeskTop.BindToObject(pidFont, nil, IID_IShellFolder, psfFont));
  OleCheck(psfFont.EnumObjects(0, SHCONTF_NONFOLDERS or SHCONTF_INCLUDEHIDDEN
    or SHCONTF_FOLDERS, pEnumList));
  while pEnumList.Next(0, pidChild, celtFetched ) = 0 do
  begin
   //break in here
    pidAbsolute := ILCombine(pidFont, pidChild);
    SHGetFileInfo(LPCTSTR(pidAbsolute), 0, FileInfo, SizeOf(FileInfo),
    SHGFI_PIDL or SHGFI_DISPLAYNAME );
    Memo1.Lines.Add(FileInfo.szDisplayName);
  end;
end;

and I know use Screen.Fonts can get font list but it display different from C:\Windows\Fonts\;


Solution

  • The GetFontResourceInfo undocumented function can get the name of the font from a font file.

    Try this sample

    {$APPTYPE CONSOLE}
    
    {$R *.res}
    
    uses
      Windows,
      SysUtils;
    
    
    function GetFontResourceInfo(lpszFilename: PChar; var cbBuffer: DWORD; lpBuffer: PChar; dwQueryType: DWORD): DWORD; stdcall; external 'gdi32.dll' name 'GetFontResourceInfoW';
    
    procedure ListFonts;
    const
      QFR_DESCRIPTION  =1;
    var
      FileRec : TSearchRec;
      cbBuffer : DWORD;
      lpBuffer: array[0..MAX_PATH-1] of Char;
    begin
      if FindFirst('C:\Windows\Fonts\*.*', faNormal, FileRec) = 0 then
      try
        repeat
          cbBuffer:=SizeOf(lpBuffer);
          GetFontResourceInfo(PWideChar('C:\Windows\Fonts\'+FileRec.Name), cbBuffer, lpBuffer, QFR_DESCRIPTION);
          Writeln(Format('%s - %s',[FileRec.Name ,lpBuffer]));
        until FindNext(FileRec) <> 0;
      finally
        FindClose(FileRec);
      end;
    end;
    
    
    begin
      try
       ListFonts;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
      Readln;
    end. 
    

    About your second question replace this line

      while pEnumList.Next(0, pidChild, b) = 0 do 
    

    with

      while pEnumList.Next(0, pidChild, celtFetched) = 0 do