Сглаживание шрифтов в Delphi

У меня была причина, по которой мне понадобилась метка с крупным шрифтом на форме Delphi, и я заметил, что ее кривые все еще были слегка неровными. Я сравнил это с тем же размером и шрифтом в MSWord, который был намного более плавным. После исследования я нашел код, который позволил мне сгладить мои шрифты, но он беспорядочный, и мне было интересно, есть ли лучший способ? Глядя в исходный код VCL, TFont кажется привязанным к NONANTIALIASED_QUALITY, что довольно неприятно...

Спасибо Бри

procedure TForm1.SetFontSmoothing(AFont: TFont);
var
  tagLOGFONT: TLogFont;
begin
  GetObject(
    AFont.Handle,
    SizeOf(TLogFont),
    @tagLOGFONT);
  tagLOGFONT.lfQuality  := ANTIALIASED_QUALITY;
  AFont.Handle := CreateFontIndirect(tagLOGFONT);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  I : integer;
begin
  For I :=0 to ComponentCount-1 do
    If Components[I] is TLabel then
      SetFontSmoothing( TLabel( Components[I] ).Font );
end;

person Brian Frost    schedule 28.05.2009    source источник
comment
Так работает ли этот код (и вы просто хотите его почистить и найти какой-нибудь простой способ) или он все еще недостаточно гладок или не работает?   -  person schnaader    schedule 28.05.2009
comment
Какую часть этого кода вы считаете грязной?   -  person Rob Kennedy    schedule 29.05.2009
comment
Кажется расточительным, что я должен тыкать каждый шрифт на каждой этикетке, когда VCL уже сделал это. Я искал что-то, что я мог бы переопределить или создать подкласс, но безуспешно. Думаю, это единственный способ добиться того, чего я хочу. Бри   -  person Brian Frost    schedule 11.08.2009


Ответы (4)


Вы можете обманом заставить VCL создать свой собственный класс, который наследуется от TLabel. Это код для проверки концепции, протестированный с Delphi 4, который поможет вам начать работу.

Создайте новый модуль для своего класса TLabel:

unit AntiAliasedLabel;

interface

uses
  Windows, Messages, SysUtils, Controls, StdCtrls, Graphics;

type
  TLabel = class(StdCtrls.TLabel)
  private
    fFontChanged: boolean;
  public
    procedure Paint; override;
  end;

implementation

procedure TLabel.Paint;
var
  LF: TLogFont;
begin
  if not fFontChanged then begin
    Win32Check(GetObject(Font.Handle, SizeOf(TLogFont), @LF) <> 0);
    LF.lfQuality := ANTIALIASED_QUALITY;
    Font.Handle := CreateFontIndirect(LF);
    fFontChanged := TRUE;
  end;
  inherited;
end;

end.

Теперь измените блок формы, содержащий метку, добавив блок AntiAliasedLabel после StdCtrls. Это приводит к тому, что ваш собственный класс AntiAliasedLabel.TLabel создается там, где обычно создается StdCtrls.TLabel.

person mghie    schedule 28.05.2009

ИМХО, VCL должен проверять сглаживание системного шрифта по умолчанию и применять его по умолчанию во время выполнения. Если нет, по крайней мере, по умолчанию должно быть более разумное сглаживание. В этом случае можно утверждать, что ClearType будет лучше по умолчанию, учитывая, что > 50% мониторов в наши дни являются ЖК-мониторами (и более 50% машин работают под управлением XP или выше).

Это общепризнанный прием (и, как упоминает Кен Уайт, не лучший подход, если есть альтернативы), но мне нужен был способ исправить это глобально для форм, содержащих буквально сотни сторонних типов компонентов (что делает наследование компонентов нереалистичным).

Я изменил качество шрифта по умолчанию в Graphics.pas, TFont.GetHandle следующим образом:

// lfQuality := DEFAULT_QUALITY;

lfКачество := 5; // (HACK) CLEARTYPE_QUALITY, принудительно очищает тип

person tikinoa    schedule 28.05.2009

Источник: http://objectmix.com/delphi/725245-tlabel-antialiasing-possibile-3.html

«простое использование шрифта, который поддерживает сглаживание шрифта, должно исправить это. Delphi использует (или, по крайней мере, использовал для использования) MS Sans Serif по умолчанию, который не поддерживает сглаживание (ClearType или что-то другое). если вы установите шрифт Tahoma (лучше всего для XP) или Segoe UI (лучше всего для Vista), вы автоматически получите сглаживание шрифта в соответствии с системными настройками в вашем приложении Delphi».

Подтверждено, что он прекрасно работает с Delphi XE и Win7. Занят сейчас сменой всех своих шрифтов ;-)

person Maya    schedule 21.10.2011

Самый простой способ — создать собственный компонент на основе TLabel, например TSmoothLabel или TAntiAliasedLabel, и добавить в него свой код сглаживания. Затем вы используете свой компонент вместо стандартного TLabel.

person Ken White    schedule 28.05.2009
comment
Верно, но я загружаю существующий DFM, в котором указан класс TLabel, поэтому ваше предложение может сработать, если есть способ перерегистрации TLAbel. Бри - person Brian Frost; 28.05.2009
comment
Есть способ, но он требует замены записи TLabel.NewInstance VMT собственным методом во время выполнения. В JCL (библиотеке кода JEDI) есть функции для этого. - person Andreas Hausladen; 28.05.2009
comment
@Brian: Почему вы не можете просто исправить файлы DFM и PAS (из-за пределов IDE), чтобы использовать ваш новый класс? Альтернатива: если вы используете версию Delphi, которая их поддерживает, вы можете использовать помощник класса для TLabel. (Укажите, какой Delphi будет использоваться в будущем.) Я не рекомендую вспомогательный маршрут класса, если есть какой-либо другой способ, потому что он повлияет на любой TLabel, который находится в его области. - person Ken White; 28.05.2009
comment
@Andreas: это неправильный подход. Это влияет на каждый отдельный TLabel повсюду и зависит от того, что в будущих версиях VCL все будет в одном и том же месте. НИКОГДА не делайте то, что является хаком, если есть другие способы сделать это, но это не так. - person Ken White; 28.05.2009