Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

Как приложению воспользоваться своими шрифтами?

01.01.2007

Может ли кто-нибудь подсказать или решить такую проблему: мне нужно убедиться, что мое приложение использует доступные, а не ближайшие шрифты, установленные пользователем в системе? Я пробовал копировать файл #.ttf в директорию пользователя windows\system, но мое приложение так и не смогло их увидеть и выбрать для дальнейшего использования.

Ниже приведен код для Delphi, который динамически устанавливает шрифты, загружаемые только во время работы приложения. Вы можете расположить файл(ы) шрифтов в каталоге приложения. Они будут инсталлированы при загрузке формы и выгружены при ее разрушении. Вам возможно придется модифицировать код для работы с Delphi 2, поскольку он использует вызовы Windows API, которые могут как измениться, так и нет. Если в коде вы видите "...", то значит в этом месте может располагаться какой-либо код, не относящийся к существу вопроса.

Ну и, конечно, вы должны заменить "MYFONT" на реальное имя файла вашего шрифта.

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    ...
    private
    { Private declarations }
    bLoadedFont: boolean;
  public
    { Public declarations }
  end;
 
procedure TForm1.FormCreate(Sender: TObject);
var
  sAppDir: string;
  sFontRes: string;
begin
  sAppDir := Application.ExeName;
  sAppDir := copy(sAppDir, 1, rpos('\', sAppDir));
 
  sFontRes := sAppDir + 'MYFONT.FOT';
  if not FileExists(sFontRes) then
  begin
    sFontRes := sFontRes + #0;
    sFont := sAppDir + 'MYFONT.TTF' + #0;
    CreateScalableFontResource(0, @sFontRes[1], @sFont[1], nil);
  end;
 
  sFontRes := sAppDir + 'MYFONT.FOT';
  if FileExists(sFontRes) then
  begin
    sFontRes := sFontRes + #0;
    if AddFontResource(@sFontRes[1]) = 0 then
      bLoadedFont := false
    else
    begin
      bLoadedFont := true;
      SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
    end;
  end;
  ...
end;
 
procedure TForm1.FormDestroy(Sender: TObject);
var
  sFontRes: string;
begin
  if bLoadedFont then
  begin
    sFontRes := sAppDir + 'MYFONT.FOT' + #0;
    RemoveFontResource(@sFontRes[1]);
    SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
  end;
end;

Я поработал с данным кодом и внес некоторые поправки для корректной работы на Delphi 2.0. На Delphi 3.0 не испытано.

Электронная справка по продукту InstallShield показывает, что в системах Win95 и WinNT FOT-файл не нужен. Вам нужен только TTF-файл.

В результате процедура FormCreate стала выглядеть так:

var
  sAppDir, sFontRes: string;
begin
  {...другой код...}
  sAppDir := extractfilepath(Application.ExeName);
 
  sFontRes := sAppDir + 'MYFONT.TTF';
  if FileExists(sFontRes) then
  begin
    sFontRes := sFontRes + #0;
    if AddFontResource(@sFontRes[1]) = 0 then
      bLoadedFont := false
    else
    begin
      bLoadedFont := true;
      SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
    end;
  end;
  {...}
end; {FormCreate}

А FormDestroy так:

var
  sFontRes, sAppDir: string;
begin
  {...другой код...}
 
  if bLoadedFont then
  begin
    sAppDir := extractfilepath(Application.ExeName);
    sFontRes := sAppDir + 'MYFONT.TTF' + #0;
    RemoveFontResource(@sFontRes[1]);
    SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
  end;
 
  {...другой код...}
end; {FormDestroy}

Для упрощения этого я сделал простую функцию, совмещающую обе этих задачи. Она возвращает логическое значение, говорящая об успехе, или наоборот, о неудаче операции загрузки или выгрузки шрифта.

 
{1998-01-16 Функция загрузки и выгрузки шрифта.}
 
function LoadFont(sFontFileName: string; bLoadIt: boolean): boolean;
var
  sFont, sAppDir, sFontRes: string;
begin
  result := TRUE;
 
  if bLoadIt then
  begin
    {Загрузка шрифта.}
    if FileExists(sFontFileName) then
    begin
      sFontRes := sFontFileName + #0;
      if AddFontResource(@sFontRes[1]) = 0 then
        result := FALSE
      else
        SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
    end;
  end
  else
  begin
    {Выгрузка шрифта.}
    sFontRes := sFontFileName + #0;
    result := RemoveFontResource(@sFontRes[1]);
    SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
  end;
end; {LoadFont}

Взято с https://delphiworld.narod.ru