![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как определить высоту текста в RichEdit е? Если текст набран [D5, WinME]
Кен © (2002-10-12 06:43:00)разными шрифтами и размерами, то не очень понятно. Подскажите, а? Нужно, чтобы можно было подогнать размеры самого RichEdit"а под размеры текста в нём.
Кен (2002-11-09 02:10:00) [1]2 MBO
Понял.
Вот так вот получилось :
procedure TForm1.Button1Click(Sender: TObject);
Var
fr : TFormatRange;
r : TRect;
b : TBitmap;
begin
b:=TBitmap.create;
r:= rect(0, 0, RichEdit1.Width*screen.Pixelsperinch, RichEdit1.Height*screen.Pixelsperinch);
fr.hdc := b.canvas.handle;
fr.hdctarget:=b.canvas.handle;
fr.rc:=r;
fr.rcpage:=r;
fr.chrg.cpMin:=0;
fr.chrg.cpMax:=-1;
Sendmessage(RichEdit1.handle,EM_FORMATRANGE,1,longint(@fr));
Richedit1.Height:=Trunc(screen.Pixelsperinch*fr.rc.bottom/1440)+8;
Sendmessage(RichEdit1.handle,WM_VSCROLL,SB_TOP,0);
b.Destroy;
end;
Всё работает.
А как это можно теперь оформить в виде отдельного компонента, с такой полезной функцией ? Никогда не делал, поэтому не знаю даже с чего начать.
Посмотрел для примера файл RxRichEd.pas из RxLib, можно было бы прямо туда добавить этот код. Но вот только как и куда там ? Файл занимает 158кб разобраться в нём это наверно с ума можно сойти. Слишком уж много всего.
MBo (2002-11-08 07:47:00) [2]b- переменная TBitmap, которая, естественно, должна быть уже создана, например, в ONCreate формы
Кен (2002-11-08 04:05:00) [3]MBo ©
Дельфи 5 ругается на строчку :
fr.hdc:=b.canvas.handle;
Пишет Project rised exception class ... и какие то большие цифры.
А как можно убрать самую последнюю строчку в RichEdit если она пуста ? Почему то в этом случае вместо неё убирается предпоследняя. А последняя пустая так и остаётся.
MBo (2002-11-07 13:16:00) [4]uses richedit
Alex4444444444 (2002-11-07 01:29:00) [5]> Нет ли какого нибудь универсального списка всего, что можно
> туда добавить ?
dir :)
Кен (2002-11-07 01:19:00) [6]2 Alx2
Я похожим способом воспользовался. Добавляю строку, определяю размер и удаляю строку.
procedure TForm1.Button1Click(Sender: TObject);
var
p:Tpoint;
begin
RxRichEdit1.Lines.Add("!");
Sendmessage(RxRichEdit1.Handle,WM_VSCROLL,SB_TOP,0);
RxRichedit1.Perform(em_posfromchar,Integer(@p),Length(RxRichedit1.Text));
RxRichEdit1.Lines.Delete(RxRichEdit1.Lines.Count-1);
RxRichedit1.Height := p.y;
end;
Sendmessage тут нужен, чтобы провернуть текст вверх, иначе определение размеров глючит. Но тут возникла другая проблема.
Когда делаешь сначала RxRichEdit1.Lines.Add(""); а потом RxRichEdit1.Lines.Delete(RxRichEdit1.Lines.Count-1); то почему то к тексту добавляется пустая строка. И удалить её не получается. Вместо неё удаляется предпоследняя строка. Как от этого иди0тск0г0 глюка избавиться я так и не понял.
MBo
Когда пытаюсь это сделать, то Дельфи ругается на TFormatRange . Я понимаю, что что то надо добавить в Uses, чтобы код заработал, но вот только что не знаю.
Как вообще в таких случаях можно узнавать, что добавить в Uses ? Нет ли какого нибудь универсального списка всего, что можно туда добавить ?
MBo (2002-11-01 14:32:00) [7]b-tbitmap
procedure TForm1.RichEdit1Change(Sender: TObject);
var
fr: TFormatRange;
r: TRect;
begin
r:=rect(0,0,RichEdit1.Width*screen.Pixelsperinch,
RichEdit1.Height*screen.Pixelsperinch);
fr.hdc:=b.canvas.handle;
fr.hdctarget:=b.canvas.handle;
fr.rc:=r;
fr.rcpage:=r;
fr.chrg.cpMin:=0;
fr.chrg.cpMax:=-1;
Sendmessage(RichEdit1.handle,EM_FORMATRANGE,1,longint(@fr));
Richedit1.Height:=Trunc(screen.Pixelsperinch*fr.rc.bottom/1440)+8;
Sendmessage(RichEdit1.handle,WM_VSCROLL,SB_TOP,0);
end;
MBo (2002-11-01 12:19:00) [8]Есть такое - EM_REQUESTRESIZE, оно должно генерировать паренту WM_NOTIFY c EN_REQUESTRESIZE, однако при проверке у меня EN_REQUESTRESIZE не приходило ;(
SETEVENTMASK делал. Может, кто-то копался?
Alex4444444444 (2002-11-01 10:03:00) [9]Po moemu, u TRichEdit est" event, generiruyushijsya, kogda on hochet izmenit" svoj razmer. Mozhet, ego pojmat"? Ili posmotret", kak on realizovan (eto ved" prosto perehvat kakoj-to message; vpolne mozhet byt" i "dvojstvennaya" message). Ne isklyucheno takzhe, chto eto mozhet byt" svyazano s ClientHeight.
Alx2 (2002-11-01 09:14:00) [10]>Кен (01.11.02 08:01)
Недолго думая, предлагаю несколько хулиганское решение по мотивам постов MBo:
procedure TForm1.Button1Click(Sender: TObject);
var p1, p2: tpoint;
correct: integer;
begin
RichEdit.Lines.Add("!");
RichEdit.Lines.Add("!");
Richedit.Perform(em_posfromchar, Integer(@p1), Length(Richedit.Text));
Richedit.Perform(em_posfromchar, Integer(@p2), 0);
if (RichEdit.ScrollBars = ssBoth) or (RichEdit.ScrollBars = ssHorizontal)
then
correct := GetSystemMetrics(SM_CXHSCROLL)
else
correct := 0;
RichEdit.Height := p1.Y - p2.y + correct;
RichEdit.Selstart := 1;
RichEdit.Lines.Delete(RichEdit.Lines.Count - 1);
RichEdit.Lines.Delete(RichEdit.Lines.Count - 1);
end;
PS
Так как, воспользовавшись советом от MBo © (16.10.02 06:38) мы получаем координаты верхушки последней строчки вместо ее "низушки", что не есть требуемое, просто добавим фиктивную строчку (или даже две - не жадные же ведь :)). Тогда ее верхушка будет ниже "низушки" последней строки. Сие уже ближе к цели. На этой "военной хитрости" и построена процеДурка.
PPS
При необходимости вызов повторить :)
PPPS
Но надо бы идти другим путем...
MBo (2002-11-01 08:02:00) [11]находить шрифт наибольшего размера в последней строке - именно по нему рассчитывается отступ
Кен (2002-11-01 08:01:00) [12]2 MBo
А какие метрики ? Ведь шрифт то каждый раз разный. Как это делать ?
MBo (2002-11-01 07:47:00) [13]GetSystemMetrics
Кен (2002-11-01 07:41:00) [14]2 Nick N A
Я в общем сделал подсчёт высоты каждой буквы в строке и вычисление таким образом общей высоты строк по самой высокой букве в них. Но результат не точен. Вычисляется только высота шрифта, а высота промежутка между строками не учитывается. Как её определить ?
Сначала попробовал принять, что она равна двум, но поигравшись обнаружилось, что чем больше высотра шрифта, тем больше промежуток между строками. Причём имперически вычислить его не получается.
Как же быть ? Как вычислить высоту промежутка между строками ?
Nick N A (2002-10-30 05:31:00) [15]У него можна определить высоту побуквенно, или построчно, пробуйте:
Единственный способ получить свойства текста -
выделить его с помощью SelStart, и SelLength=1,
затем SelAttributes содержит в себе подробную инфо о
выделеном фрагменте текста, сомневаюсь, что если выделено более одной буквы - он правильно выдаст инфо.
RichEdit1.SelAttributes.Height-высота.
SelText-выделеный текст
Возможно достаточно измерять высоту каждой строки текста.
удачи
Кен (2002-10-30 03:05:00) [16]2 Separator ©
Так определяется для Form1 , а у RichEdit1 так нельзя.
Такая строка : RichEdit1.Canvas.TextHeight() - не работает.
Так как же ТОЧНО определить высоту текста в RichEdit ? Неужели это такая неразрешимая проблема ?
Separator (2002-10-23 08:17:00) [17]Form1.Canvas.TextHeight()
Кен (2002-10-23 03:39:00) [18]Как бы решить проблему ?
Кен (2002-10-20 01:13:00) [19]2MBo ©
Попробовал. Вроде получается но глючит.
Я поставил этот код на кнопку. В ричедит загружаю из файла текст в rtf формате.
Дальше жму на кнопку и размер окна подравнивается до предпоследней строки. Вместе с ним появляется ещё линейка прокрутки. Так вот стоит эту линейку чуть подвинуть, и сделать пересчёт размеров окна, как результат получается другой. И так каждый раз двигая линейку результаты получаем каждый раз разные. Как это обезглючить ?
Про последнююс строчку я честно сказать не очень понял. Как к ней применить .Canvas.TextHeight(); ? Какое начало у этого кода ?
MBo (2002-10-16 06:38:00) [20]var p:Tpoint;
begin
Richedit1.Perform(em_posfromchar,Integer(@p),Length(Richedit1.Text));
caption:=inttostr(p.x)+" "+inttostr(p.y);
Это верхняя точка последнего символа, так что к p.y надо еще прибавить высоту последней строки, вычисленную указанным Song способом