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

前端 未结 3 1160
终归单人心
终归单人心 2021-01-14 15:52

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

First I use FindFirst&FindNext to get all the file

Code:



        
相关标签:
3条回答
  • 2021-01-14 16:38

    Here's an adaptation of RRUZ's answer with the benefit that you can enumerate and find the names of fonts in any directory, not necessarily only the installed fonts in C:\Windows. The trick is to call AddFontResource before (and RemoveFontResource after) processing it with GetFontResourceInfoW for each font file:

    program font_enum;
    
    {$APPTYPE CONSOLE}
    {$R *.res}
    
    uses
      Windows,
      System.SysUtils;
    
    const
      QFR_DESCRIPTION = 1;
    
    var
      p: String;
      F: TSearchRec;
      cbBuffer: DWORD;
      lpBuffer: array [0 .. MAX_PATH - 1] of Char;
    
    function GetFontResourceInfo(lpszFilename: PChar; var cbBuffer: DWORD; lpBuffer: PChar; dwQueryType: DWORD): DWORD;
      stdcall; external 'gdi32.dll' name 'GetFontResourceInfoW';
    
    begin
      try
        { TODO -oUser -cConsole Main : Insert code here }
    
        p := ParamStr(1);
    
        if (p = EmptyStr) then
          p := ExtractFilePath(ParamStr(0))
        else if (not DirectoryExists(p)) then
        begin
          Writeln('Directory specified is not valid.');
          Exit;
        end;
    
        p := IncludeTrailingPathDelimiter(p);
    
        if (FindFirst(p + '*.ttf', faAnyFile - faDirectory, F) = 0) then
        begin
    
          repeat
            AddFontResource(PWideChar(p + F.Name));
    
            cbBuffer := SizeOf(lpBuffer);
            GetFontResourceInfo(PWideChar(p + F.Name), cbBuffer, lpBuffer, QFR_DESCRIPTION);
            Writeln(Format('%s = %s', [F.Name, lpBuffer]));
    
            RemoveFontResource(PWideChar(p + F.Name));
    
          until (FindNext(F) <> 0);
    
        end;
    
        FindClose(F);
    
        if (FindFirst(p + '*.fon', faAnyFile - faDirectory, F) = 0) then
        begin
    
          repeat
            AddFontResource(PWideChar(p + F.Name));
    
            cbBuffer := SizeOf(lpBuffer);
            GetFontResourceInfo(PWideChar(p + F.Name), cbBuffer, lpBuffer, QFR_DESCRIPTION);
            Writeln(Format('%s = %s', [F.Name, lpBuffer]));
    
            RemoveFontResource(PWideChar(p + F.Name));
    
          until (FindNext(F) <> 0);
    
        end;
    
        FindClose(F);
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
    
    end.
    
    0 讨论(0)
  • 2021-01-14 16:51

    I got this from a German Delphi forum. It works on Delphi 7 Enterprise.

    function GetFontNameFromFile(FontFile: WideString): string;
    type
      TGetFontResourceInfoW = function(Name: PWideChar; var BufSize: Cardinal;
        Buffer: Pointer; InfoType: Cardinal): LongBool; stdcall;
    var
      GFRI: TGetFontResourceInfoW;
      AddFontRes, I: Integer;
      LogFont: array of TLogFontW;
      lfsz: Cardinal;
      hFnt: HFONT;
    begin
      GFRI := GetProcAddress(GetModuleHandle('gdi32.dll'), 'GetFontResourceInfoW');
      if @GFRI = nil then
        raise Exception.Create('GetFontResourceInfoW in gdi32.dll not found.');
    
      if LowerCase(ExtractFileExt(FontFile)) = '.pfm' then
        FontFile := FontFile + '|' + ChangeFileExt(FontFile, '.pfb');
    
      AddFontRes := AddFontResourceW(PWideChar(FontFile));
      try
        if AddFontRes > 0 then
          begin
            SetLength(LogFont, AddFontRes);
            lfsz := AddFontRes * SizeOf(TLogFontW);
            if not GFRI(PWideChar(FontFile), lfsz, @LogFont[0], 2) then
              raise Exception.Create('GetFontResourceInfoW failed.');
    
            AddFontRes := lfsz div SizeOf(TLogFont);
            for I := 0 to AddFontRes - 1 do
              begin
                hFnt := CreateFontIndirectW(LogFont[I]);
                try
                  Result := LogFont[I].lfFaceName;
                finally
                  DeleteObject(hFnt);
                end;
              end; // for I := 0 to AddFontRes - 1
          end; // if AddFontRes > 0
      finally
        RemoveFontResourceW(PWideChar(FontFile));
      end;
    end;
    
    procedure TMainForm.btnFontInfoClick(Sender: TObject);
    begin
      if OpenDialog1.Execute then
        MessageDlg(Format('The font name of %s is'#13#10'%s.', [OpenDialog1.FileName,
          GetFontNameFromFile(OpenDialog1.FileName)]), mtInformation, [mbOK], 0);
    end;
    
    0 讨论(0)
  • 2021-01-14 16:52

    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
    
    0 讨论(0)
提交回复
热议问题