Faq как прокрутить текст в tmemo или в trichedit


Faq как прокрутить текст в tmemo или в trichedit

В следующем примере создается процедура разбиения слов при переносах для TMemo. Заметьте, что реализованная процедура просто всегда разрешает перенос. Для дополнительной информации см.таже документацию к сообщению EM_SETWORDBREAKPROC.

delphi
var
OriginalWordBreakProc : pointer ;
NewWordBreakProc : pointer ;

function MyWordBreakProc(LPTSTR : pchar ;
ichCurrent : integer ;
cch : integer ;
code : integer ) : integer
<$IFDEF WIN32>stdcall ; <$ELSE>; export; <$ENDIF>
begin
result := 0 ;
end ;

procedure TForm1.FormCreate(Sender: TObject );
begin
OriginalWordBreakProc := Pointer (
SendMessage(Memo1.Handle,
EM_GETWORDBREAKPROC ,
0 ,
0 ));
<$IFDEF WIN32>
NewWordBreakProc := @MyWordBreakProc;
<$ELSE>
NewWordBreakProc := MakeProcInstance(@MyWordBreakProc,
hInstance);
<$ENDIF>
SendMessage(Memo1.Handle,
EM_SETWORDBREAKPROC ,
0 ,
longint (NewWordBreakProc));

TMemo и Scrollbar. Как сделать выделение i строки?

01.11.2015, 23:24

TMemo: выделение выбранной строки цветом
Как сделать, что бы в TMemo выбрана строка была выделена цветом?

Выделение текста в TMemo
как сделать так,чтобы при удачном поиске слова в Memo (компонента) это найденное слово выделилось.

TMemo, как сделать не редактируемой часть поля.
Программа читает содержимое памяти и выводит в полн Мемо в HEX виде. Хочу добавить возможность.

Как зафиксировать две строки в TMemo?
У меня есть цикл. И в нём постоянно в memo заносится новая строка. Вот так они заносятся, заносятся.

Как на cellclick сделать выделение только строки, а выделение столбца отменить
Здравствуйте, проблема такая, программа работает отлично, но я занимаюсь сопровождением ПО. И при.

02.11.2015, 00:03 2
02.11.2015, 23:18 [ТС] 3

02.11.2015, 23:41 4
02.11.2015, 23:41
04.11.2015, 02:01 [ТС] 5

Memo1->SelStart = 0; не работает. Я пробовал и CaretPos и Cursor и другие свойства. Единственное, что меняет индекс первой отрисовываемой строки это функция ScrollBy. Еще я пробовал делать Clear() и рисовать все заного, но это ужасно.

Указатель на TScrollbar нужен чтобы задавать шаг прогрутки и допл. настройки (SmallChange, Min, Max). Главная цель уменьшить количество действий с TMemo. Когда я читаю текст или занимаюсь редактированием, то кнопками на скроле(вверх и вниз на строку) я почти не пользуюсь, листаю сразу по слайдеру. Если перевести SmallChange с единицы на собственную величину, например, на 15% от всего, то большие тексты я смогу пролистывать быстрее и попадать, например, в середину документа сразу без прицеливания. Еще можно использовать клавишу ScrollDown как пролистывание всех видимых строк (те в мемо нарисовано с 0 по 20 строк, я нажал один раз ScrollDown и мемо нарисовал строки с 20 по 40).
Я рассматривал вариант где можно создать дополнительный скрол и через него все подкрутить. Но такое решение вызывает у меня проектировочную печаль.

TMemo

Как создание нестандартную процедуру разбиения слов при переносах для TEdit, TMemo или TRichEdit?

В следующем примере создается процедура разбиения слов при переносах для TMemo. Заметьте, что реализованная процедура просто всегда разрешает перенос. Для дополнительной информации см.таже документацию к сообщению EM_SETWORDBREAKPROC.

function MyWordBreakProc(LPTSTR : pchar;

code : integer) : integer

procedure TForm1.FormCreate(Sender: TObject);

Faq как прокрутить текст в tmemo или в trichedit

Здравствуйте!
Решил задать вопрос в эту тему, чтобы не создавать новую.
Подскажите, пожалуйста!
Этим кодом я прокручиваю скролл у RichEdit1.
(код конечно демонстрационный, но принцип отражает)

with RichEdit1 do
begin
// указываем позицию курсора на нужную строку
selstart:=perform(EM_LineIndex, 1, 0);
sellength:=1; // выделяем
perform(EM_ScrollCaret,0,0); // прокручиваем скролл
SetFocus; // фокус
end;


Всё работает нормально.
Но если я добавляю в uses модуль RichEdit (uses RichEdit), то сообщение:

перестаёт работать, т.е. скролл не прокручивается.
Позиция ставится, строка выделяется, но скролл не прокручивается!
Как только убираю модуль RichEdit из uses, всё работает.

Дело в том, что, этот модуль мне нужен для увеличения количества
символов вводимых в RichEdit, с помощью сообщения:

SendMessage(RichEdit1.Handle, EM_EXLIMITTEXT, 0, $7FFFFFF0);

Если кто сталкивался с этим явлением, подскажите, пожалуйста, в чём
причина?
Заранее спасибо!

Faq как прокрутить текст в tmemo или в trichedit

При добавлении текста в TRichEdit ScrollBar не опускается в самый низ как в TMemo.
Нашел такой выход из ситуации на этом сайте:

SendMessage(RichEdit1.Handle, EM_LINESCROLL, 0, RichEdit1.Lines.Count-1);

Но тут случается такая беда: при первом же добавлении текста, который выходит за пределы RichEdit, остается только этот текст, а остальной уходит из зоны видимости. Как решить?

>AVK (04.06.04 13:14)
Что значит уходит из области видимости? Всмысле остается много пустого места?

Да. Появляется только последняя строка и она находится в самом верху RichEdit`a. Если «кликнуть» по ScrollBar`y, то положение текста становится таким, как надо и после этого наш SendMessage не вызывает такого эффекта.

Если шрифт в RichEdit одной высоты, то

procedure UpDateScrollRange;

function GetVisibleLines: Integer;
var
R: TRect;
LineHeight: Integer;
begin
R := RichEdit1.ClientRect;
LineHeight := RichEdit1.Canvas.TextHeight(«Wq»);
if LineHeight <> 0
then
Result := (R.Bottom — R.Top) div LineHeight
else
Result := 1;
end;

var
LinesCount: Integer;
VisibleLines, Pos, LinesToScroll: Integer;
begin
VisibleLines := GetVisibleLines;
LinesCount := SendMessage(RichEdit1.Handle, EM_GETLINECOUNT, 0, 0);
Pos := SendMessage(RichEdit1.Handle, EM_GETFIRSTVISIBLELINE, 0, 0);
LinesToScroll := (LinesCount — Pos) — VisibleLines;
SendMessage(RichEdit1.Handle, EM_LINESCROLL, 0, LinesToScroll);
end;

Большое спасибо! Все работает как надо.
Только у RichEdit`a Canvas`a не нашлось и я заменил на Form1.Canvas

>AVK (04.06.04 15:27) [4]
Не, тогда так:

function GetVisibleLines: Integer;
var
R: TRect;
C: TCanvas;
DC: HDC;
LineHeight: Integer;
begin
C := TCanvas.Create;
C.Font.Assign(RichEdit1.Font);
DC := GetDC(0);
C.Handle := DC;
R := RichEdit1.ClientRect;
LineHeight := C.TextHeight(«Wq»);
if LineHeight <> 0
then
Result := (R.Bottom — R.Top) div LineHeight
else
Result := 1;
ReleaseDC(0, DC);
C.Free;
end;


Переделал.
А теперь немного разобраться.
В этом варианте SendMessage(RichEdit1.Handle, EM_LINESCROLL, 0, RichEdit1.Lines.Count-1);
мы посылали сообщение в котором вторым параметром является номер последней строки.
А в сообщении SendMessage(RichEdit1.Handle, EM_LINESCROLL, 0, LinesToScroll);
вторым параметром является что?
LinesToScroll = «количество всех строк» — «номер первой видимой строки. » — «количество видимых строк».

>AVK (04.06.04 16:12) [6]
EM_LINESCROLL — прокручивает указанное в lParam колиличество строк вертикально. В RichEdit у тебя может быть 100 строк но все 100 не помещаются в видимой части.
EM_GETFIRSTVISIBLELINE — возвращает номер первой видимой строки. Также ты вычисляешь количество видимых строк. Теперь, тебе надо прокрутить общее количиство строк — (первая видимая + количество в видимой области).

Прокрутка двух TMemo или TRichEdit

Подскажите, как в Delphi мне сделать такое:есть два поля TMemo одинакового размера с вертикальной прокруткой.нужно сделать так, чтобы когда прокручиваешь мышкой или тянешь бегунок в одном из полей, во втором прокручивалось бы все так же?

Нужно породить наследника от TMemo у и него перекрыть два сообщения procedure WMVScroll(var Msg :TMessage); message WM_VSCROLL; procedure WMHScroll(var Msg :TMessage); message WM_HSCROLL;Эти сообщения отвечают за скрол контрола. по ним Вы сможете отслеживать скрол своего контрола и далее скролить второй TMemo

Faq как прокрутить текст в tmemo или в trichedit

В следующем примере создается процедура разбиения слов при переносах для TMemo. Заметьте, что реализованная процедура просто всегда разрешает перенос. Для дополнительной информации см.таже документацию к сообщению EM_SETWORDBREAKPROC.

delphi
var
OriginalWordBreakProc : pointer ;
NewWordBreakProc : pointer ;

function MyWordBreakProc(LPTSTR : pchar ;
ichCurrent : integer ;
cch : integer ;
code : integer ) : integer
<$IFDEF WIN32>stdcall ; <$ELSE>; export; <$ENDIF>
begin
result := 0 ;
end ;

procedure TForm1.FormCreate(Sender: TObject );
begin
OriginalWordBreakProc := Pointer (
SendMessage(Memo1.Handle,
EM_GETWORDBREAKPROC ,
0 ,
0 ));
<$IFDEF WIN32>
NewWordBreakProc := @MyWordBreakProc;
<$ELSE>
NewWordBreakProc := MakeProcInstance(@MyWordBreakProc,
hInstance);
<$ENDIF>
SendMessage(Memo1.Handle,
EM_SETWORDBREAKPROC ,
0 ,
longint (NewWordBreakProc));

C++Builder

Вопросы программирования => Общие вопросы программирования в C++Builder => Тема начата: khan от 23 Май 2007, 20:40:31

Название: Номер строки в TMemo & RichEdit
Отправлено: khan от 23 Май 2007, 20:40:31

int y0 = SendMessage(Mem_Record_ExtendInfo->Handle, EM_GETFIRSTVISIBLELINE, 0, 0);
Так узнаем номер первой видимой строки.
По координатам мыша и высоте строки рассчитываем номер строки над которой завис курсор ну и что то со всем этим делаем.
Имейте ввиду — перемещение мыша внутри Memo не активизирует новый показ хинта.


Возможно, но только у всего компонента.

PS.
Memo это не последовательность горизонтальных компонентов (а почему только горизонтальных?) а единый компонент, со всеми вытекающими.
Хороший подопытный — стандартный блокнот, все что можно в нем можно и в мемо (и наоборот).

TMemo не катит совершенно
TRichEdit — возможно. По крайней мере на его базе.
Для нумерации строк я: или делаю колонку слева или подписываю внизу номер строки.

Для ваших целей, думаю, можно приспособить какой-нибудь «умный» редактор с подсветкой синтаксиса. Поищите на старом форуме — ссылки давались.

Faq как прокрутить текст в tmemo или в trichedit

Почему не помогает? Показывай, как пробовал.

И вообще, для того чтобы забить гвоздь, необязательно использовать паровой молот с лазерным наведением. Для окна лога вполне сойдёт ListBox, например.

Пока без проверки на то, в фокусе RichEdit или нет. Подразумеваем что он всегда в фокусе.
И, в итоге, при таком коде сначала фокус переходит на Edit, потом после добавления сторки на RichEdit. Но все равно курсор при этом будет на последней добавлненной строке. Вне зависимости от того где он был раньше. Не знаю почему так, поидее должно было все работать.

По поводу использования другого компонента. Если была бы возможность, то использовал бы. Дело в том, что у меня каждая строка лога имеет определенный цвет в зависимости от события. А такая работа с текстом есть только в RichEdit. В остальных компонентах он просто всегда весь одного цвета. Так что об использовании другого компонента речь не идет.

BlackStrip-форум

Ультрабыстрая подсветка синтаксиса в Delphi TRichEdit

Ультрабыстрая подсветка синтаксиса в Delphi TRichEdit

Сообщение blackstrip » Вс дек 15, 2013 3:01 pm

Думаю, многим, кто хотел бы использовать подсветку синтаксиса в своих программах на Delphi, не используя при этом компоненты сторонних авторов типа synedit и т.д., будет полезна эта статья.


Когда я писал Scriptaint в PaintCAD 4Windows, то пришлось сделать подсветку скриптов. За несколько недель я выискал в интернете ряд исходников, но все они не подошли. Пришлось собрать из них своего франкенштейна.

Задача подсветки была такая:
1) Все многострочные комментарии между » » пометить зеленым
2) Все однострочные комментарии типа «// текст» пометить зеленым
3) Все многострочные комментарии между «/*» и «*/» пометить зеленым
4) Все многострочные тексты между двойными кавычками пометить синим
5) Все многострочные тексты между одинарными кавычками пометить фиолетовым
6) Все зарезервированные слова языка java script выделить жирным.

Когда я написал эту процедуру, то на подсветку небольшого скрипта размером в 200 строк Windows XP тратил примерно полсекунды. Поэтому после каждого нажатия клавиши или после изменения скрипта нельзя было тут же вызывать подсветку. Я сделал таймер, который обновлялся каждый раз при изменении текста TRichEdit и если в течении 2 секунд никто не менял текст — то запускалась подсветка.

Когда я начал тестировать это в Windows 8 — то увидел, что вместо полсекунды на подсветку того же скрипта стало уходить 5-6 секунд (видимо в win8 что-то намудрили с бедным richeditом)! И нельзя было вообще ничего редактировать, с ужасом ожидая что вот запустится подсветка и все залипнет на пять секунд.

Оказалось, что долго работает trichedit, который лежит на форме, и очень быстро работает trichedit в памяти. Видимо windows 8 делает что-то страшное при каждой перерисовке. И даже после моих блокировок отрисовки компоненты richedit кучей функций WinAPI, понадерганых из чужих исходников подсветки, лежащий на форме richedit все равно продолжал работать очень долго.

Поэтому новая процедура копировала содержимое richedit в невидимый richedit в памяти, в нем делала все обработки и перекидывала полученное содержимое назад, восстанавливая после этого старое положение полос прокрутки и положение курсора.

Но после тестов в Windows 98 оказалось, что вертикальная полоса прокрутки не слушается установки в старое положение. Пришлось добавить посылку сообщения EN_LINESCROLL на richedit и восстанавливать таки его положение в win 98 тоже.

Вот она, процедура подсветки ричедита RichEdit1 и сопутствующие процедуры, работающие мгновенно (наверное 0.1-0.2 сек), хотя на толстых текстах могут и они тормозить (тогда вам придется писать подсветку в пределах показываемого в richedit фрагмента текста, а это уже другая история):

delim — строка символов, которые могут быть с боков зарезервированных слов. Алгоритм их отлавливает по бокам от найденного слова, поэтому «,function,» выделится, а «efunction» — нет.

Reswords — массив слов, которые будут жирными в тексте, если с боков от них символы из delim.

procedure TForm37.Podsvet();
var
i:integer;
longcomm:boolean;
ls:integer;
insidestr1:boolean;
is1:integer;
insidestr2:boolean;
is2:integer;
htmlcomm:boolean;
ema,hs:integer;
s:string;
cwork,work:string;
wl,ss,sl:integer;
n:integer;
nd:boolean;
ri:TRichEdit;
ms: TMemoryStream;
tsih:tagSCROLLINFO;
tsiv:tagSCROLLINFO;
st,en:integer;
begin
//запоминаем что было выделено до этого
ss:=RichEdit1.SelStart;
sl:=RichEdit1.SelLength;
//флажки, когда один включается, то остальные не включатся, чтоб не находить в комментариях зарезервированные слова и т.д.
longcomm:=false;
ins > ins > htmlcomm:=false;
//запоминаем для win98 какой была первая видимая линия
en:=SendMessage(RichEdit1.Handle,EM_GETFIRSTVISIBLELINE,0,0);
//включаем блокировку перерисовки
RichEdit1.DoubleBuffered:=true;
SendMessage(RichEdit1.Handle,WM_SETREDRAW,0,0);
ema:=SendMessage(RichEdit1.Handle,WM_USER+69,0,0);
//создаем TRichEdit в памяти
ri:=TRichEdit.CreateParented(Form37.Handle);
//копируем из нашего видимого TRichEdit все содержимое в созданный TRichEdit
ms := TMemoryStream.Create;
RichEdit1.PlainText:=true;
ri.PlainText:=true;
try
RichEdit1.Lines.SaveToStream(ms) ;
ms.Seek(0, soFromBeginning) ;
ri.Lines.LoadFromStream(ms) ;
finally
ms.Free;
end;
//готовим две структуры tagScrollInfo для сохранения положения полос прокрутки RichEdit
FillChar(tsiv,sizeof(tsiv),0);
tsiv.cbSize := SizeOf(tsiv);
tsiv.fMask := SIF_POS;

FillChar(tsih,sizeof(tsih),0);
tsih.cbSize := SizeOf(tsih);
tsih.fMask := SIF_POS;
//запоминаем в них положения полос прокрутки
GetScrollInfo(RichEdit1.Handle,SB_VERT,tsiv);
GetScrollInfo(RichEdit1.Handle,SB_HORZ,tsih);

//начинаем городить подсветку в невидимом TRichEdit
try
//чистим всю предыдущую подсветку
ri.SelStart:=0;
ri.SelLength:=length(ri.Text);
ri.SelAttributes:=RichEdit1.DefAttributes;
ri.SelAttributes.Color:=clBlack;
ri.SelAttributes.Style:=[];

i:=0;
//весь текст скидываем в переменную work, добавляя в конце символ разделитель, чтоб искать зарезервированные слова и в конце текста тоже
work:=ri.Text+#$D#$A;
wl:=length(work);
while (i continue;
end;


//нашли двойную кавычку и до этого нашли еще одну (флажок insidestr2 установлен) — красим от первой кавычки до найденной все в синий
if ins ) then
begin
ri.SelStart:=is2;
ri.SelLength:=i-is2;
ri.SelAttributes.Color:=RGB(0,0,128);
ins > continue;
end;

//если это не последний символ и он со следующим образует */, и до этого находили /* (флажок longcomm установлен) — то красим это все в зеленый
if i , и до этого находили открывающий ‘) then
begin
ri.SelStart:=hs;
ri.SelLength:=i-hs+2;
ri.SelAttributes.Color:=clGreen;
i:=i+2;
htmlcomm:=false;
continue;
end;

//если бежим по тексту и мы не внутри ни одного из выделений — то можно искать начальные символы этих выделений и зарезервированные слова
if (not htmlcomm) and (not longcomm) and (not insidestr1) and (not insidestr2) then
begin
//одинарная кавычка — запоминаем где была и ставим флажок начала покраски
if work=»» then
begin
ins > is1:=i-1;
continue;
end;

//двойная кавычка — запоминаем где была и ставим флажок начала покраски
if work='»‘ then
begin
ins > is2:=i-1;
continue;
end;

//java-коммент — запоминаем где был и ставим флажок начала покраски
if i 1) then if Pos(work[i-1],delim)>0 then nd:=true;
//итак, если нужно, то
if nd then
//бежим по всем резервным словам в массиве
for n:=0 to length(Reswords)-1 do
begin
//если нашли слово
if (Pos(Reswords[n],cwork)=1) and (length(cwork)>length(Reswords[n])) then
//и если за ним идет разделитель
if Pos(cwork[length(Reswords[n])+1],delim)>0 then
begin
//то делаем его жирным
ri.SelStart:=i-1;
ri.SelLength:=length(Reswords[n]);
ri.SelAttributes.Style:=[fsBold];
i:=i+length(Reswords[n]);
Continue;
end;
end;

//закончили пробег по тексту

//смотрим есть ли рваные выделения (неоконченные) — тогда просто красим текст до самого конца

i:=wl-1;
if insidestr1 then
begin
ri.SelStart:=is1;
ri.SelLength:=i-is1;
ri.SelAttributes.Color:=clPurple;
ins > end;

if insidestr2 then
begin
ri.SelStart:=is2;
ri.SelLength:=i-is2;
ri.SelAttributes.Color:=RGB(0,0,128);
ins > end;

if longcomm then
begin
ri.SelStart:=ls;
ri.SelLength:=i-ls;
ri.SelAttributes.Color:=clGreen;
longcomm:=false;
end;

if htmlcomm then
begin
ri.SelStart:=hs;
ri.SelLength:=i-hs;
ri.SelAttributes.Color:=clGreen;
htmlcomm:=false;
end;

//все покрасили, копируем обратно
ms := TMemoryStream.Create;
ri.PlainText:=false;
RichEdit1.PlainText:=false;
try
ri.Lines.SaveToStream(ms) ;
ms.Seek(0, soFromBeginning) ;
RichEdit1.Lines.LoadFromStream(ms) ;
finally
ms.Free;
end;

//восстанавливаем позиции скроллов
RichEdit1.Perform(WM_VSCROLL,SB_THUMBPOSITION+tsiv.nPos*65536,0);
RichEdit1.Perform(WM_HSCROLL,SB_THUMBPOSITION+tsih.nPos*65536,0);

//для win98 и других случаев — смотрим, если по вертикали скролл не туда попал, то заставляем скроллить туда куда надо
st:=SendMessage(RichEdit1.Handle,EM_GETFIRSTVISIBLELINE,0,0);
if st<>en then SendMessage(RichEdit1.Handle,EM_LINESCROLL,0,en-st);


//richedit в памяти отслужил свое, сносим его
ri.Free;

//ставим курсор и выделение куда надо
RichEdit1.SelStart:=ss;
RichEdit1.SelLength:=sl;

//включаем отключенную перерисовку обратно и перерисовываем компоненту
SendMessage(RichEdit1.Handle,WM_SETREDRAW,1,0);
InvalidateRect(RichEdit1.Handle,0,true);
SendMessage(RichEdit1.Handle,WM_USER+69,0,ema);
RichEdit1.DoubleBuffered:=false;
RichEdit1.Repaint;

//подсветка выполнена
end;

Вызов процедуры подсветки по таймеру

Кидаем на форму таймер, 2000 мс, Enabled=false. В событие OnTimer вписываем проверку, если 2 секунды никто не нажимал ничего и данный момент Shift не нажат (т.е. никто не пытался выделить часть текста, а то посередине этого процесса при зажатом Shift свойства ричэдита SelStart и SelLength дают неправильные координаты и после подсветки выделение сведется к нулевому) — тогда можно остановить таймер и вызвать подсветку. Иначе просто еще 2 сек подождем, пока shift не отпустят и не прекратят процесс выделения текста.

procedure TForm37.Timer1Timer(Sender: TObject);
begin
if not ((Word(GetAsyncKeyState(VK_SHIFT)) and $8000)<>0) then
begin
Timer1.Enabled:=false;
Podsvet();
end;
end;

В сам RichEdit1 на событие OnChange назначаем эту процедуру, чтоб обновить таймер и всегда ждать с момента последнего изменения текста до вызова подсветки ровно 2 секунды:

procedure TForm37.RichEdit1Change(Sender: TObject);
begin
Timer1.Enabled:=false;
Timer1.Enabled:=true;
end;

Вот и все. Получается быстрая подсветка RichEdit через 2 секунды после последнего изменения текста.

Увеличение объема текста в RichEdit

У RichEdit есть свойство MaxLength, которое по умолчанию равно нулю. И тогда максимальное количество символов в RichEdit становится равным 65536.

Как советуют в инете, увеличить это значение можно, если в программу добавить строчку:
RichEdit1.MaxLength:= System.MaxInt-2;

Или прямо на форме при разработке выделить RichEdit и записать в свойство MaxLength число 2147483645 .

Илон Маск рекомендует:  Что такое код ord
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL