Введение
Мой вопрос исходит из довольно интересной проблемы, с которой я имел дело в течение последних нескольких дней. Я недавно задал вопрос о Написание персонализированного инспектора свойств - Как обрабатывать фокус редактора inplace при проверке значений?
С тех пор я немного улучшил свой контроль, например, добавив разделитель посередине для разделения между строками Name и Value, и, что важно, разделитель может использоваться для изменения размера двух столбцов.
Вот где начались мои проблемы, поскольку видимый редактор inplace пока изменял размер разделителя, что немного снизило мой контроль. Поэтому я еще больше изменил код, чтобы отображать только редактор inplace, если разделитель не был изменен. Поэтому, по существу, я использовал Canvas.TextOut
для рисования моих значений в виде строк, если выбрана строка, тогда редактор Inplace показан выше. Редактор inplace становится скрытым, если размер разделителя был изменен, после завершения операции изменения размера редактор inplace снова становится видимым.
В то время как это решило проблему небольшого замедления, о которой я упоминал, мне пришлось столкнуться с новой проблемой в том, что текст из редактора inplace (который в основном представляет собой TEdit) немного отличался от текста, который я рисовал, используя Canvas.TextOut
Пример 1
Разница довольно тонкая, но если вы посмотрите достаточно близко, вы можете просто увидеть ее:
fig.1 Canvas.TextOut
fig.2 DrawText
Вам может потребоваться использовать экранную лупу, чтобы выглядеть ближе, но с рядом SomeText более заметно, что расстояние между Some
и Text
, а также между T
и e
в Text
немного отличается.
Пример 2
Немного лучший пример - это сравнение между Canvas.TextOut
и DrawText
с текстом редактора inplace (TEdit):
fig.3 Сравнение
Как вы можете видеть, разница здесь гораздо более заметна. Строка True
наглядно показывает гораздо большее расстояние между текстовыми символами при использовании Canvas.TextOut
, где в качестве текста текста DrawText
и inplace editor
точно совпадают.
Когда я использовал Canvas.TextOut
, я получал всевозможные ужасные текстовые несоответствия между изменением размера моего делителя-инспектора и показом и скрытием редактора inplace. Если бы я не экспериментировал и не пытался использовать альтернативные методы рисования текста, я не думаю, что когда-либо бы понял разницу и нашел решение. Важно знать, что я использовал точные настройки шрифта при рисовании моего текста на холсте в качестве шрифта, который я определил для редактора inplace.
Теперь, когда я использую DrawText
вместо Canvas.TextOut
, все работает в унисон с редактором inplace и точно, как я хочу.
Вопрос
Мой вопрос заключается в том, что делает Canvas.TextOut
визуализировать текст так иначе, как DrawText
? Из моего примера и решения моей текущей проблемы ясно, что Canvas.TextOut
не отображает текст так же, как TEdit с теми же настройками шрифта, но DrawText
делает текст, казалось бы, правильным способом.
Это заставляет меня сомневаться в использовании Canvas.TextOut
, если он не отображает текст правильно, должен ли я всегда использовать DrawText
вместо этого?
Демо-версия
Вы можете проверить это для себя следующим кодом:
type
TForm1 = class(TForm)
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormPaint(Sender: TObject);
private
FFont: TFont;
FRect: TRect;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
FFont := TFont.Create;
FFont.Color := clNavy;
FFont.Name := 'Segoe UI';
FFont.Size := 9;
FFont.Style := [];
FRect := Rect(10, 30, 100, 100);
Canvas.Font.Assign(FFont);
Edit1.Font.Assign(FFont);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FFont.Free;
end;
procedure TForm1.FormPaint(Sender: TObject);
begin
Canvas.TextOut(10, 10, 'Canvas.TextOut: [True]');
DrawText(Canvas.Handle, PChar('DrawText: [True]'), Length('DrawText: [True]'), FRect, DT_LEFT);
end;
С приведенным выше запуском в совершенно новом проекте VCL результат, который я получаю, выглядит следующим образом:
fig.4 Test Demo
Снова обратите внимание на интервал в строке True
при использовании Canvas.TextOut
, с моего конца он явно отличается от DrawText
и способ, которым TEdit
рисует свой текст.
Ниже показано то же изображение, что и на рисунке 4, но увеличено на 400%
fig.5 Test Demo увеличено на 400%
Заметные различия наблюдаются между T
и e
в Text
, а также T
и r
в True
.
fig.6 Слово "Текст" увеличено на 400% с рекомендациями
Вы можете видеть, что кернинг между T
и e
ближе к пикселю с DrawText
, чем к Canvas.TextOut
(который использует ExtTextOut
.)
fig.7 Слово True
увеличилось на 700% с рекомендациями
Вы можете видеть, что кернинг между T
и r
находится на один пиксель ближе к DrawText
и редактору Inplace (TEdit), чем к Canvas.TextOut
(который использует ExtTextOut
.)
Я тестировал несколько разных шрифтов, и вот мои выводы:
Хорошо:
Arial, Cambria, Candara, Comic Sans MS, Consolas, Courier, Courier New, Fixedsys, Грузия, Lucida Console, Lucida Sans Unicode, Microsoft Sans Сериф, Тахома, Терминал и Times New Roman.
Плохо:
Calibri, Corbel, Myriad Pro, Segoe UI, Trebuchet MS и Verdana.
Хорошие шрифты - это те, которые, как представляется, отображают текст так же, как DrawText
, а элементы управления пространственным редактором (TEdit) используют Canvas.TextOut
. Плохие показывают, что Canvas.TextOut
делает текст немного отличающимся от других методов.
Здесь может быть какая-то подсказка, хотя я не слишком уверен, но я все равно добавляю ее на всякий случай.