![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
GetTextExtentExPoint с учетом табуляций? [Win2k, WinXP]
AlexeyT © (2006-09-30 08:41:00)Используется GetTextExtentExPoint для получения позиций символов в строке. Строка юникодная (сразу предупреждаю), например арабские символы.
Вопрос такой: Как получить позиции символов, если строка печаталась с учетом табуляций: т.е. через TabbedTextOut ? Может, какая отдельная функция есть, или эту как-то использовать с табуляциями можно?
Спасибо.
AlexeyT (2006-10-01 22:04:00) [1]
> , затем для табов сами просчитали позиции согласно жеаемым
> табстопам и через ExtTextOut выводим точно так, как рассчитали
> используя GetTextExtentExPoint.
> Это сложнее чем вышеприведенный код, зато табы можно сделать
> не "длиными пробелами" а "настоящими табами".
Интересно. ExtTextOut оказывается может выводит по заданным позициям?..
Да, для "настоящих табов" так наверное и нужно делать - я пока оставлю свой вариант.
> > там длина промежуточной строки может *превышать* длину
> всей
> > строки. Такое бывает.
>
> Хм. интересно. А как так ?
Вот так, увидел экспериментально. Был поток каких-то юникодных символов, неотображаемых моими шрифтами - квадратики. Так вот когда квадратиков было много (40 подряд, например), это были "короткие квадратики" (шириной 2-3). Когда они переносились на след. строку и их было мало (5-10), рисовались как "полные квадратики", (с шириной=высоте). Это TextOut так выводила.
guav (2006-10-01 18:50:00) [2]> В общем, я пока остановился на втором твоем совете - вывод
> через TextOut с заменой табуляции пробелами и просчет позиций
> через GetTextExtentExPoint.
Заменять табы пробелами не обязательно. Я имел в виду другое.
ExtTextOut принимает массив позиций, похожий на массив, возвращаемый GetTextExtentExPoint.
Т.е. вызвали GetTextExtentExPoint, затем для табов сами просчитали позиции согласно жеаемым табстопам и через ExtTextOut выводим точно так, как рассчитали используя GetTextExtentExPoint.
Это сложнее чем вышеприведенный код, зато табы можно сделать не "длиными пробелами" а "настоящими табами".
> там длина промежуточной строки может *превышать* длину всей
> строки. Такое бывает.
Хм. интересно. А как так ?
AlexeyT (2006-10-01 11:48:00) [3]Вот врапперы, которые я в итоге написал, с учетом табуляций задаваемого размера. Может, еще кому пригодится.
//Win32Platform - это переменная из SysUtils
procedure StringOut(Canvas: TCanvas; const X, Y: integer; const Str: WideString; TabSize: word = 8);
var
S: WideString;
begin
S:= SReplaceTabsW(Str, TabSize);
if Win32Platform=VER_PLATFORM_WIN32_NT
then Windows.TextOutW(Canvas.Handle, X, Y, PWChar(S), Length(S))
else Windows.TextOutA(Canvas.Handle, X, Y, PChar(string(S)), Length(S));
end;
type
TStringExtent = array[0..cMaxTextWidth] of integer;
function StringExtent(Canvas: TCanvas; const Str: WideString; var Ext: TStringExtent; TabSize: word = 8): boolean;
var
S: WideString;
Dx: array[0..cMaxTabSize*cMaxTextWidth] of integer;
Size: TSize;
i, j: integer;
begin
S:= SReplaceTabsW(Str, TabSize);
FillChar(Dx, SizeOf(Dx), 0);
if Win32Platform=VER_PLATFORM_WIN32_NT
then Result:= GetTextExtentExPointW(Canvas.Handle, PWChar(S), Length(S), 0, nil, @Dx[1], Size)
else Result:= GetTextExtentExPointA(Canvas.Handle, PChar(string(S)), Length(S), 0, nil, @Dx[1], Size);
FillChar(Ext, SizeOf(Ext), 0);
if Result then
begin
i:= 0;
j:= 0;
repeat
Inc(i);
Inc(j);
if i>Length(Str) then Break;
if Str[i]=#9 then Inc(j, TabSize-1);
Ext[i]:= Dx[j];
until false;
end;
end;
AlexeyT (2006-10-01 10:54:00) [4]2guav
Ага, спасибо.
В общем, я пока остановился на втором твоем совете - вывод через TextOut с заменой табуляции пробелами и просчет позиций через GetTextExtentExPoint.
Почему не первый способ - потому, что подсчет длин промежуточных строк не годится в случае юникода: там длина промежуточной строки может *превышать* длину всей строки. Такое бывает.
guav (2006-09-30 22:14:00) [5]Могу ещё посоветовать попытаться поотлаживать стандартный edit, узнать какие функции он вызывает. Edit Control решает твою задачу при определении позиции курсора.
в Riched20.dll (библиотеке, реализующей Rich Edit Control в экспорте) используется ExtTextOut и GetCharWidth (это видно по импорту этих и не-импорту аналогов). Т.е. там способ похож на
> отказаться от TabbedTextExtent и вызывать GetTextExtentExPoint,
> самому просчитывать табуляцию и вызывать ExtTextOut.
AlexeyT (2006-09-30 20:15:00) [6]>Понял проблему.
>Тогда не знаю такой функции.
>Видимо, придётся или вызывать GetTabbedTextExtent для каждого nCount от 1 до длины строки.
Этого я и боялся...
guav (2006-09-30 18:23:00) [7]> Не совсем: она не возвращает ширины промежуточных символов,
> только ширину всей строки.
Понял проблему.
Тогда не знаю такой функции.
Видимо, придётся или вызывать GetTabbedTextExtent для каждого nCount от 1 до длины строки.
Другой вариант, отказаться от TabbedTextExtent и вызывать GetTextExtentExPoint, самому просчитывать табуляцию и вызывать ExtTextOut.
AlexeyT (2006-09-30 16:02:00) [8]>Скорее всего, это GetTabbedTextExtent .
Не совсем: она не возвращает ширины промежуточных символов, только ширину всей строки. А нужны ширины символов...
DrawTextEx также не возвращает эти значения...
guav (2006-09-30 15:14:00) [9]Скорее всего, это GetTabbedTextExtent .
Рекомендую использовать DrawTextEx , как самую универсальную из функций вывода текста, она сама себе и есть "аналог GetTextExtentExPoint" http://www.delphimaster.ru/cgi-bin/forum.pl?id=1159471239&n=0