@krka92

Как правильно посчитать ширину текста?

Мне нужно вычислять ширину текста таким образом, чтобы ширина всего слова была равна сумме ширин отдельных символов или слов. Это мне нужно для того, чтобы выводить текст по частям. Как форматированный текст, у которого текущий фрагмент отличается по стилю, размеру и т.п. от предыдущего. И нужно знать с какой позиции начинать отрисовку.
Для простоты возьмем двухсимвольный текст: "Ye" (латинская)
Вызываем DrawText с флагом DT_CALCRECT
DrawText(DC, Data, Len, RC, DT_SINGLELINE or DT_CALCRECT);
Width:= RC.Width;

и получаем ширину этого слова: Width = 40.
Окей.
Если я вычислю ширину той же функцией для каждого символа этой строки
Width := 0;
while Data < DataEnd do
  begin
    DrawText(DC, Data^, 1, RC, DT_SINGLELINE or DT_CALCRECT);
    Inc(Width, RS.Width);
    Inc(Data)
  end;

то получу общую ширину: Width = 43;
А именно: для первого символа 23, для второго 20.
Выведу текст на канвас обоими способами и получу такой результат:
spoiler
5d8b4cfd0d1b9060360185.png
Сверху - слово целиком. Снизу - посимвольно.
Дело в том, что когда слово выводится целиком, то второй символ как-бы немного заползает под первый.
---
Идем дальше.
Можно вычислить расстояния у символов: A - Перед глифом, B -ширина глифа, C -после глифа.
Интервал A или C может быть отрицательным, чтобы указать нависающие элементы или выступы.
Вычисляем:
GetCharABCWidths(DC, Ord('Y'), Ord('Y'), ABC[0])
Для "Y" имеем: A = 0; B = 23; C = 0;
GetCharABCWidths(DC, Ord('e'), Ord('e'), ABC[0])
Для "e" имеем: A = 1; B = 18; C = 1;
И отрицательных значений я не вижу от слова совсем! А "нависание" есть.
Вопросов больше, ответов нет. Если кто сталкивался или знает подскажите)
Спасибо)
  • Вопрос задан
  • 267 просмотров
Пригласить эксперта
Ответы на вопрос 1
tsklab
@tsklab
Здесь отвечаю на вопросы.
Можно использовать TRichEdit.

Или используя DrawCellTextOut, выводить в TDBGrid так:5d8b61d20c9f5186777657.png
procedure TAlbumDetailFR.grReleaseDrawColumnCell(Sender: TObject; const Rect: TRect; 
                                       DataCol: Integer; Column: TColumnEh; State: TGridDrawState);
  var iLeft: Integer;
begin
  case DataCol of
    0:  with grRelease.Canvas do begin
          FillRect( Rect );
          iLeft := 2;
          DrawCellTextOut( TDBGridEh(Sender).Canvas, Rect, iLeft, taReleaseYear.Value + ' ' );
          Font.Style := [fsBold];
          DrawCellTextOut( TDBGridEh(Sender).Canvas, Rect, iLeft, taReleaseNumber.Value + ' ' );
          Font.Style := [];
          DrawCellTextOut( TDBGridEh(Sender).Canvas, Rect, iLeft, taReleaseFirmName.Value );
        end;
  end;
end;

Процедура DrawCellTextOut:
procedure DrawCellTextOut( Canvas: TCanvas; const Rect: TRect; var Left: Integer; Text: String );
begin
  with Canvas do begin
    if ( Length( Trim( Text )) > 0 )
                          and (( Rect.Right - Rect.Left - Left ) > ( TextWidth('…') + 1)) then begin
      while (( TextWidth( Text ) + 1 ) > ( Rect.Right - Rect.Left - Left ))
        do Text := Copy( Text, 1, Length( Text ) - 2) + '…';
      TextOut( Rect.Left + Left, Rect.Top + 1, Text );
      Inc( Left, TextWidth( Text ) + 1);
    end;
  end;
end;
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы