Форум: "Основная";
Текущий архив: 2004.07.25;
Скачать: [xml.tar.bz2];
ВнизАлгоритм форматирования текста "По ширине" Найти похожие ветки
← →
NailMan © (2004-07-11 23:40) [0]Идея такая:
Пишется аналог листбокса для Direct3D9 приложения, так как в нем нельзя юзать VCL.
Как один из режимов отображения текста в листбоксе необходимо сделать аналог форматирования текста "По ширине"(слочвечко из MS Word), то есть чтобы слова в строке распределялись равномерно в ширине текстового окна. Также надо сделать простой перенос части строки (если он не влез в окно) на строчку(и) ниже.
Что имеется в наличии:
- текст загруженный в TStringList
- ширина окна(в пикселях) в котором текст отображается
- функция вычисления ширины(в пикселях) текста
Бился 2 дня, красивого решения придумать не смог. Хотя бы сделать перенос куска(ов) строки если он не влезает в окно.
Пробовал раскладывать строку на слова(разделение по пробелам) и анализировать суммарную ширину, последовательно складывая их - так пробелы которые в начале строки убиваются, и вообще запутался с циклами перебора.
Помогите алгоритмом(псевдо-кодом или куском кода если есть такой)...плз.
← →
KilkennyCat © (2004-07-12 00:20) [1]а, было и у меня такое... я вначале использовал в 2D привязку канваса, и в нем уже текстоут, который позволял все это... потом отказался и сделал следующее: брал тест пословно, мерял при этом его ширину. Если ширина превышала ширину поверхности - последнее слово переводилось на следующую строку, полученная текущая стандартно позиционировалось вычислением разности ширин див 2.
← →
KilkennyCat © (2004-07-12 00:20) [2]щас, пощу код... старый проект-то...
← →
KilkennyCat © (2004-07-12 00:32) [3]
// Перенос слов для скроллируемого текста
procedure TMain.wordwraps(tt : TMemoryStream);
var
BMP : TBitMap; // Вспомогательный, для определения размера строки
NewText : tmemorystream; // Новый текст
TestString : string; // Тестируемая строка
Bukva : byte; // Байт чтения-записи
l,ll : int64; // Метки, где можно сделать перенос слова
Perenos : boolean; // Можно или нельзя переносить слово
const
BK : word = 3338; // Перевод строки
begin
NewText := tmemorystream.Create; // Создаем поток для нового текста
NewText.SetSize(0); // и очищаем его (на всякий случай)
TestString := ""; // Очищаем строку теста
tt.position := 0; // Устанвливаемся в начало исходного текста
Perenos := false; // Поскольку только начали, какие переносы?
l := 0;
ll := 0;
bmp := tbitmap.Create; //Создаем битмап
bmp.width := 1; // Пусть не жрет память
bmp.height := 1;
........................................
setlength(scrolltext.Smes,tt.Size);
// начали!!!
repeat
tt.ReadBuffer(Bukva,1); // Читаем первый байт
if (Bukva = 13) then begin // А может это перевод строки?
NewText.WriteBuffer(BK,1); // Точно, перевод. Пишем перевод в новый текст
tt.ReadBuffer(Bukva,1); // Так как записали два, а прочитали один, компенсируем...
Perenos := false; // Жизнь с новой строки, однако.
TestString := "";
end else begin // не-а, не перевод... нормальная буква.
TestString := TestString + chr(Bukva);// прибавим к тестовой строке
if bmp.canvas.TextWidth(TestString) < 640 then begin // укладываемся в ширину?
NewText.WriteBuffer(Bukva,1); // ага, уложились, значит добавим этот байтик в новый текст
if pos(chr(Bukva)," ,.-=!?:;+") <> 0 then begin // а нет ли в тестовой строке символа-переноса?
l := NewText.Position; // Ура! есть! запомним это, что он есть, и его позиции в текстах
ll := tt.Position;
Perenos := true;
end
end else begin // в ширину не уложились. Будем делать перенос.
if Perenos then begin //Были ли символы переноса?
NewText.Position := l - 1; // Были. Откатываемся чуть дальше символа переноса
tt.Position := ll - 1;
tt.ReadBuffer(Bukva,1); // Читаем из исходного текста это символ переноса
NewText.WriteBuffer(Bukva,1); // Пишем его в новый текст
NewText.WriteBuffer(BK,1); // Пишем в новый текст перевод строки
end else begin // Не было символа переноса текста. Режем слово.
NewText.WriteBuffer(BK,1); //Пишем перенос строки в новый текст
NewText.WriteBuffer(Bukva,1); //Продолжаем слово в новом тексте
end;
Perenos := false; // Перенос сделали
TestString := ""; // Жизнь с новой строки, однако.
end; // конец процесса переноса (в ширину не уложились. Будем делать перенос)
end; // Конец процесса добавления буквы (не-а, не перевод... нормальная буква)
until tt.Position > tt.Size - 1; // Проверим, не хватит ли начинать? может букв больше нет?
NewText.Position := 0; // Возвращаемся в новом тексте в начало
scrolltext.Text.Clear; // 0чищаем содержимое текста для скроллинга
scrolltext.Text.loadfromstream(NewText); // Загружаем полученный текст
scrolltext.Text.Insert(0," "); //Добавляем пару пустых строк в начало (а то придется извращаться при скроллинге)
scrolltext.Text.Insert(0," ");
scrolltext.Text.Insert(0," "); // Строка-символ начала текста
scrolltext.Text.Insert(0," "); // Пивная! Еще парочку!
scrolltext.Text.Insert(0," ");
scrolltext.Text.add(" "); //Добавляем пару пустых строк в конец
scrolltext.Text.add(" ");
scrolltext.Text.add(" "); // Строка-символ конца текста
scrolltext.Text.add(" "); // комментарии излишни
scrolltext.Text.add(" ");
// определяем высоту строки для основного окна (чего зря шрифту и битмапу пропадать?)
Bhstr := bmp.Canvas.TextHeight("QWERTYUqwertyЯЧСМТЙЦУКЕячсмитьйцукеншщ"); // прочитайте это быстро :)
bmp.Free; // Ресурсам - свободу!
NewText.Free;
end;
во... надо же, чего я налепил тогда :)))
да, на комментарии не обращайте особого внимания - просто при продаже требовали - написал... сейчас смотрю - поражаюсь... можно лучше.
Особенности алгоритма - если есть перевод строки - будет выполнен перевод, даже если строка может еще кучу вместить.
← →
KilkennyCat © (2004-07-12 00:39) [4]да , еще: шрифт использовался боооольшой, поэтому иногда даже одно слово не вмещалось, оно здесь разрезается, без всяких грамм. правил.
← →
GrayFace © (2004-07-12 07:19) [5]"Подробный и понятный комментарий" однако! ;-)
TextWidth может подвести с наклонным шрифтом(вылезет за границы области). Универсальное решение - через GetCharABCWidthsFloat.
← →
NAlexey © (2004-07-12 09:19) [6]Хм... А DrawText с DT_CALCRECT разве не поможет?
← →
NailMan © (2004-07-12 10:41) [7]KilkennyCat ©
Пасиба за код, сегодня попробую применить к совей задаче.
GrayFace ©
> TextWidth может подвести с наклонным шрифтом(вылезет за
> границы области). Универсальное решение - через GetCharABCWidthsFloat.
Дело в том что я использую собственный растровый шрифт(3 разных высот), который всегда прямой, так что думаю с косым шрифтом проблемы нет, а вот эта функция не прокатит.
---
WBR, NailMan aka 2:5020/3337.13
← →
KilkennyCat © (2004-07-12 23:37) [8]
> NailMan © (12.07.04 10:41) [7]
Забавно, я тоже логфонт применил, там где точки - его код и был :)
Мы случайно не одно и тоже делаем? :))
> GrayFace © (12.07.04 07:19) [5]
Да вот, блин, просили комментарий заказчики... это еще что, это в начале основного кода, в конце я уже чуть ли не матом комментировал :)
За GetCharABCWidthsFloat спасибо, не знал.
> NAlexey © (12.07.04 09:19) [6]
К сожалению, в моем случае не помогло. Не помню уже почему, может скорость не понравилась, может еще что-то... В этом варианте получается итемс, что добавило положительного для дальнейшей работы.
← →
NailMan © (2004-07-13 16:03) [9]KilkennyCat ©
Может и одно и тоже, но я написал весь ГУЙ и фактически пришел к системе с формой аля Delphi.
Эта бядяга с выравниванием потребовалась для создания
окошечка с текстом(типа ShowMessage), которое на основе урезанного листбокса(фактически из листбокса можно получить аналог TMemo) делается, а там надо в определенные границы влезть(не больше разрешения экрана).
---
WBR, NailMan aka 2:5020/3337.13
← →
Григорьев Антон © (2004-07-13 16:34) [10]Вот ещё один пример: http://www.delphikingdom.com/asp/viewitem.asp?catalogid=171
В нём, кроме всего прочего, осуществляется перенос русских слов.
← →
Григорьев Антон © (2004-07-13 16:42) [11]Вот ещё один пример: http://www.delphikingdom.com/asp/viewitem.asp?catalogid=171
В нём, кроме всего прочего, осуществляется перенос русских слов.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.07.25;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.033 c