2015-02-23 2 views
3

Я использую tyring для расчета максимального размера шрифта для того, чтобы текст Text вписывался в ClientRect TCxLabel. Но я не могу заставить его работать. (Смотрите рисунок)Calculate Max Размер шрифта

enter image description here

FontSize является большим и thxt не обращал corrent места.

Вот как воспроизвести:

Поместите tcxLabel на пустой форме, и Allign ярлык для клиента

Добавить FormCreate и событие FormResize:

procedure TForm48.FormCreate(Sender: TObject); 
begin 
    CalculateNewFontSize; 
end; 

procedure TForm48.FormResize(Sender: TObject); 
begin 
    CalculateNewFontSize; 
end; 

и наконец реализовать CalculateNewFontSize :

Math;

procedure TForm48.CalculateNewFontSize; 
var 
    ClientSize, TextSize: TSize; 
begin 

    ClientSize.cx := cxLabel1.Width; 
    ClientSize.cy := cxLabel1.Height; 

    cxLabel1.Style.Font.Size := 10; 
    TextSize := cxLabel1.Canvas.TextExtent(Text); 

    if TextSize.cx * TextSize.cx = 0 then 
    exit; 

    cxLabel1.Style.Font.Size := cxLabel1.Style.Font.Size * Trunc(Min(ClientSize.cx/TextSize.cx, ClientSize.cy/TextSize.cy) + 0.5); 
end; 

Кто-нибудь знает, как рассчитать размер шрифта и ho, чтобы правильно разместить текст?

+1

'cxLabel1.Style.Font.Size: = cxLabel1.Style.Font.Size * n' где' n' - целое число, означающее, что вы не полностью закрываете пространство шрифта. –

+0

Поскольку Font.Size является целым числом, мне нужно, чтобы n было целым числом!?! –

+0

Итак, если вы начинаете с размера 12, вы считаете, что следующее большее значение равно 24? Используйте MulDiv. –

ответ

4

Я хотел бы использовать что-то вдоль этих линий:

function LargestFontSizeToFitWidth(Canvas: TCanvas; Text: string; 
    Width: Integer): Integer; 
var 
    Font: TFont; 
    FontRecall: TFontRecall; 
    InitialTextWidth: Integer; 
begin 
    Font := Canvas.Font; 
    FontRecall := TFontRecall.Create(Font); 
    try 
    InitialTextWidth := Canvas.TextWidth(Text); 
    Font.Size := MulDiv(Font.Size, Width, InitialTextWidth); 

    if InitialTextWidth < Width then 
    begin 
     while True do 
     begin 
     Font.Size := Font.Size + 1; 
     if Canvas.TextWidth(Text) > Width then 
     begin 
      Result := Font.Size - 1; 
      exit; 
     end; 
     end; 
    end; 

    if InitialTextWidth > Width then 
    begin 
     while True do 
     begin 
     Font.Size := Font.Size - 1; 
     if Canvas.TextWidth(Text) <= Width then 
     begin 
      Result := Font.Size; 
      exit; 
     end; 
     end; 
    end; 
    finally 
    FontRecall.Free; 
    end; 
end; 

Сделайте первоначальную оценку, а затем тонкую настройку, изменив размер с шагом по одному за раз. Это легко понять и проверить на правильность, а также достаточно эффективно. При типичном использовании код будет вызывать TextWidth только несколько раз.

+0

Спасибо за помощь Дэвид, я сделал свой компонент на основе вашего кода. Я просто хочу поделиться с вами и остальным миром: D http://pastebin.com/aK6nZNZk –

3

Размер шрифта не зависит линейно от размера шрифта. Таким образом, вы бы лучше, чтобы увеличить или размер шрифта декремента один и рассчитать размер текста, или найти нужный размер с бинарным поиском (предпочтительнее, если размер значительно отличается)

+0

Да, это было мое первое решение, но я получил его в чистой математике. –

+1

Эта проблема не разрешима (для немоноширинных шрифтов) с чистой математикой, так как размер разных элементов шрифта (элементы букв, межсимвольные пространства и т. Д.) Изменяется в сложным образом. Например, лигатура (пример-связанная ff) может существовать для некоторого размера шрифта и выводиться для другого размера. – MBo