Rtf теги и подсветка синтаксиса в richedit


Подсветка текста в Richedit

Доброго времени суток!

Пишу проект на C++ и WinAPI. В проекте мне нужна такая фича: подсветка текста в Richedit . Основа реализации подсветки — функция Highlight в классе CColoredRichTextBox

Каким образом можно это сделать (т. е. что мне нужно написать в тело функции Highlight )?

2 ответа 2

А я бы сделал так, сохранить позицию, задать позицию разцветки, разкрасить, восстановить позицию:

Ну и для разнообразия, подсветка SQL наброски (borland)

подсветка текста определенным образом в Richedit’e

vital

вобсчем нуна разукрасить текст примерно в таком формате
текст [цвет$ текст] текст (почти как в форуме )

причем сообщение идет с сокета, но это уже мелочи..

Я пробовал делать примерно так

Barmutik

Я подсвечивал вот так:

vital

Barmutik

Zakus

для стандартного РичЭдита, из 7ой дельфи.

//выделяете текст который нужно «подсветить»
RichEdit1.SelStart := 2; //начало выделения
RichEdit1.SelLength := 3; //длинна выдиления

RichEdit1.SelAttributes.Color := clRed; //устанавливаете для выделенного текста цвет

можете покопаться в RichEdit1.SelAttributes, может кроме цвета что интересное для себя найдёте.

Для: vital
стоп, сейчас прочитал. и увидел что вы юзаете всё что я описал, так в чём вопрос. ваш код не работает? или что?

Zakus

Для: vital
о как всё запущено.

ща код ваш розгребу. сделаю рабочим

но, вы вкурсе что у stringa первая буква не тут msg[0] а тут msg[1] =)))

Rtf теги и подсветка синтаксиса в richedit

Есть ричедит. в нем длинная одна строка текста.например:

один два 00 00 99 99 88 7 6 55 55 55 55 55 55 55 55

как при таких исходных даных получить тескт вида

один два 00 00 99 99 88 7 6 55 55 55 55 55 55 55 55

один два 00 00 99 99 88 7 6 55 55 55 55 55 55 55 55

один два 00 00 99 99 88 7 6 55 55 55 55 55 55 55 55

Смысл в том что лексемы текста различные но повторяющийся. причем каждая лексема текста имеет разный размер и привязана к определенной структуре даных. так вот мне нужно выделить связанный со структурой даных текст в ричедите.

Вообщем вопрос — есть ли что-то типа тегов для ричедита что-бы во время формирования строки в текст вставлять эти теги делающие определенный кусок жирным шрифтом ?

Код для написания собственного редактора с подсветкой синтаксиса (RichEdit)

ArtistTo

Новичок

Если вы школьник 12-14 лет или дядя-хикка, решили возвысить свое ЧСВ, написать свой нубо-язык программирования из 1-3 команд, с нубо парсером, не умеющем распарсивать строку из 2 и более команд; при этом падающем чуть реже, чем всегда — то вам нужен собственный редактор, с подсветкой вашего ‘синтаксиса’ не так ли? ;D Ну это все шутки. К делу.

Вот единственный адекватный код для подсветки синтаксиса в инвалидном RichEdit’e на языке AuIT от ‘Δαηy Δαηy’.
Код отрабатывает на ура, ничего не мигает и не трясется, т.к. прорисовка RichEdit приостанавливается на время очередной проверки, при этом возможность ввода не блокируется.

Пояснение (что код делает): на ходу раскрашивает все вводимые слова ‘процедура, кпроц, main, возврат’ в красный и слово ‘include’ в зеленый; при этом, если слово было нарушено (удалением символа например), то оно будет обращено в стандартный цвет (черный). Копируйте код и пробуйте.

Единственный недочет, вы должны найти код для нахождения позиции в RE и ее установки; это написано в комментариях к коду, иначе редактирование текста/кода где-то в середине, будет невыполнимой задачей, каретка будет устанавливаться в конец текста, при каждом нажатии клавиши.

И да, код неидеальный, но вполне адекватный. Если у вас есть свой код подсветки синтаксиса — делитесь.

Интересно узнать мнение old форумчан, модераторов, админов, любых людей с адекватной критикой.

Rtf теги и подсветка синтаксиса в richedit

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, StdCtrls, ComCtrls;

type
TForm1 = class (TForm)
RichEdit1: TRichEdit;
Button1: TButton;
OpenDialog1: TOpenDialog;
Button2: TButton;
procedure RichEdit1KeyUp(Sender: TObject ; var Key: Word ;
Shift: TShiftState);
procedure HighLight;
function CheckList(InString: string ): boolean ;
procedure Button1Click(Sender: TObject );
procedure Button2Click(Sender: TObject );
private
< Private declarations >
public
< Public declarations >
end ;

var
Form1: TForm1;

function TForm1.CheckList(InString: string ): boolean ;
const TheList: array [ 1 .. 13 ] of string = ( ‘begin’ , ‘or’ , ‘end’ , ‘end.’ ,
‘end;’ , ‘then’ , ‘var’ , ‘for’ , ‘do’ , ‘if’ , ‘to’ , ‘string’ , ‘while’ );
var X: integer ;
begin
Result := false ;
X := 1 ;
InString := StringReplace (InString, ‘ ‘ , » ,[rfReplaceAll]);
InString := StringReplace (InString, # $A , » ,[rfReplaceAll]);
InString := StringReplace (InString, # $D , » ,[rfReplaceAll]);
while X High (TheList) + 1 do
if TheList[X] = lowercase (InString) then
begin
Result := true ;
X := High (TheList) + 1 ;
end
else inc (X);
end ;

Илон Маск рекомендует:  IntToStr - Функция Delphi

procedure TForm1.RichEdit1KeyUp(Sender: TObject ; var Key: Word ;
Shift: TShiftState);
var WEnd, WStart, BCount: integer ;
Mark: string ;
begin
if (ssCtrl in Shift) and (Key = ord ( ‘V’ )) then Button2Click( Self );
if (Key = VK_Return ) or (Key = VK_Back ) or (Key = VK_Space ) then
begin
if RichEdit1.SelStart > 1 then
begin
WStart := 0 ;
WEnd := RichEdit1.SelStart;
BCount := WEnd — 1 ;
while BCount <> 0 do
begin
Mark := copy (RichEdit1.Text, BCount, 1 );
if (Mark = ‘ ‘ ) or (Mark = # $A ) then
begin
WStart := BCount;
BCount := 1 ;
end ;
dec (BCount);
end ;
RichEdit1.SelStart := WEnd — (WEnd — WStart);
RichEdit1.SelLength := WEnd — WStart;
if CheckList(RichEdit1.SelText) then
RichEdit1.SelAttributes.Style := [fsBold]
else RichEdit1.SelAttributes.Style := [];
RichEdit1.SelStart := WEnd;
RichEdit1.SelAttributes.Style := [];
end ;
end ;
end ;

function SearchFor(WorkSpace, Search: string ; Start: integer ): integer ;
var Temp: string ;
begin
Temp := copy (WorkSpace, Start, length (WorkSpace));
Result := pos (Search, Temp);
end ;

procedure TForm1.HighLight;
var WStart, WEnd, WEnd2: integer ;
WorkSpace, SWord: string ;
begin
WStart := 1 ;
WEnd := 1 ;
with RichEdit1 do
begin
WorkSpace := Text + ‘ ‘ + # $D # $A ;
while WEnd > 0 do
begin
WEnd := SearchFor(WorkSpace, ‘ ‘ , WStart);
WEnd2 := SearchFor(WorkSpace, # $A , WStart);
if WEnd2 then WEnd := WEnd2;
SWord := copy (WorkSpace, WStart, WEnd — 1 );
if (SWord <> ‘ ‘ ) and (SWord <> » ) then
if CheckList(SWord) then
begin
SelStart := WStart — 1 ;
SelLength := length (SWord);
SelAttributes.Style := [fsBOLD];
SelStart := WStart + length (SWord) + 1 ;
SelAttributes.Style := [];
end ;
WStart := WStart + WEnd;
end ;
SelStart := length (Text);
SetFocus;
end ;
end ;

procedure TForm1.Button1Click(Sender: TObject );
begin
if OpenDialog1.Execute then
begin
RichEdit1.Lines.LoadFromFile(OpenDialog1.FileName);
HighLight;
end ;
end ;

procedure TForm1.Button2Click(Sender: TObject );
begin
RichEdit1.PasteFromClipboard;
HighLight;
end ;

Примечание Vit: Все способы подкраски синтаксиса реализованные через RichEdit грешат одним существенным недостатком — они реализованы через изменение атрибутов текста.

И чем это грозит?

А представьте себе что вы загрузили файл Дельфи, большой такой на пару мегабайт, например интерфейс от какого-то ActiveX от MS Word. и решили написать комментарий в начале файла, открываете скобку «(*» и . ждёте секунд 10, а то и минуту пока изменятся атрибуты у всего файла, затем закрываете скобку «*)» и ждёте следующие пол минуты. Если же текст побольше, например вы загрузили какой-нибудь XML мегабайт на 50, то тогда после каждого нажатия клавиши у вас будет время выпить пивка и пройти уровень в Quake (желательно на другой машине, чтоб не тормозила).

И что же делать?

А то что сам метод порочен по своей сути! Зачем вам подкрашивать 50 мегабайтов текста при нажатии на клавишу если реально надо подсветить только то что вы видите не экране! А это всего-лишь максимум 10 Kb текста, но обычно и вовсе 1-2 Kb. Кроме того, зачем менять аттрибуты? Ведь Вам же не надо ничего специального делать с зелёными словами, причём так чтобы это не коснулось синих слов. Измение атрибутов в RichEdit мероприятие само по себе очень долгое, ведь по сути дела меняется сам поток данных! В данном случае достаточно только изменить прорисовку текста, т.е. как этот текст рисуется на экране, не меняя сам текст и его атрибуты совершенно! Фактически всё что вам надо сделать — это поменять процедуру прорисовки текста компонента, но это в теории, на практике всё гораздо сложнее. Но логика та же. Именно так работают и все редакторы с подсветкой синтаксиса — и от Борланда, и от MS, и от сторонних производителей.

Чтоб не тратить время на изобретение велосипеда предлагаю применять компонент SynEdit — самый совершенный на сегодняшний день аналог Memo с подсветкой синтаксиса. См. Подсветку в Мемо

Qt/C++ — Урок 058. Подсветка синтаксиса HTML кода в QTextEdit

Некоторое время назад я занимался изучением подсветки синтаксиса в QTextEdit и практиковался на подсветке для HTML кода. В результате удалось сделать довольно неплохой вариант подсветки синтаксиса HTML кода, но в связи с тем, что есть вероятность того, что этот код не будет мною применён где-нибудь, я решил выложить данный пример программного кода.

Подсветка синтаксиса HTML в QTextEdit будет выглядеть следующим образом:

Структура проекта


Проект состоит из следующих файлов:

  • HTMLExample.pro — профайл проекта;
  • main.cpp — стартовый файл проекта;
  • mainwindow.h — заголовочный файл окна приложения;
  • mainwindow.cpp — файл исходных кодов окна приложения;
  • mainwindow.ui — файл интерфейса;
  • HTMLHighLighter.h — заголовочный файл класса для подсветки HTML кода;
  • HTMLHighLighter.cpp — файл исходных кодов класса для подсветка HTML кода;

main.cpp, HTMLExample.pro — создаются по умолчанию, в mainwindow.ui добавляем только QTextEdit .

Илон Маск рекомендует:  AssignPrn - Процедура Delphi

mainwindow.h

Здесь подключаем заголовочный файл HTMLHighLighter и объявляем его объект.

mainwindow.cpp

А в данном файле просто устанавливаем объект HTMLHighLighter в документ объекта QTextEdit .

HTMLHighLighter.h

Особенность подсветки синтаксиса кода или просто текста в QTextEdit заключается в том, что класс QSyntaxtHighLighter перебирает все текстовые блоки, на которые разделён текст (разбит с помощью символа перевода строки) и определяет, как подсвечивать текущий блок с самого начала в зависимости от состояния подсветки предыдущего текстового блока.

Естественно это необходимо реализовать. В конструкторе класса будут инициализированы правила подсветки различных частей кода и шаблоны, по которым будут определяться эти части кода. А в методе highlightBlock(const QString &text), будет реализована логика обработки текста.

Синтаксис RichEdit Highligh

мне нужна ваша помощь! Итак, я создаю RichEdit с подсветкой синтаксиса, я делаю так:

Но я вижу, что в больших файлах с большим преимуществом он становится лагги, у вас есть лучший способ сделать это? Я проверил сборку Iczelion, но этот код беспорядок, он, кажется, рисует подсветку перед текстом, но так что выбор не работает, правильно? Если да, можете ли вы дать мне несколько советов о том, как это сделать? Спасибо!

Самый быстрый способ, который я нашел, — создать необработанный RTF-документ, а затем передать его в элемент управления через сообщение EM_STREAMIN.

Еще одна вещь, которую следует иметь в виду, — это то, что используемый вами RTF-контроль имеет серьезные последствия для производительности. Когда я это сделал, я обнаружил, что элемент управления по умолчанию (предоставляемый Windows XP) был ужасно медленным, но RICHED20.DLL, предоставленный Microsoft Office, был на порядок быстрее. Вы должны попробовать версии, к которым у вас есть доступ, и выполнить некоторые сравнения производительности.

Ваше использование MainRich.GetText() и избыточные вызовы std::string::find() являются узкими местами. Не извлекайте текст вообще. CRichEditCtrl::FindText() используйте CRichEditCtrl::FindText() .

Не восстанавливайте исходный формат исходного выделения в конце. Что делать, если выделенное ключевое слово было выбрано до того, как вы применили выделение? Вы отмените выделение для него.

Еще одна оптимизация, которую вы можете сделать для ускорения работы RichEdit, — это использовать CRichEditCtrl::SetEventMask() чтобы отключать события (например, EN_SELCHANGE ) при внесении изменений в текст, а затем восстанавливать их по завершении.

RichEdit Синтаксис Highligh

Мне нужна ваша помощь! Итак, я создаю RichEdit с подсветкой синтаксиса, я делаю так:

Но я вижу, что в больших файлах с большим количеством выделения это становится запаздывающим, у вас есть лучший способ сделать это? Я проверил Ассамблея Ичелиона но этот код беспорядок, он, кажется, рисует выделение перед текстом, но таким образом выделение не работает, верно? Если да, можете ли вы дать мне несколько советов, как это сделать? Спасибо!

Решение

Самый быстрый способ, который я нашел, — это создать необработанный RTF-документ и затем передать его элементу управления через EM_STREAMIN сообщение.

Следует также помнить, что используемый вами элемент управления RTF серьезно влияет на производительность. Когда я это сделал, я обнаружил, что элемент управления по умолчанию (предоставляемый Windows XP) был ужасно медленным, но RICHED20.DLL, предоставляемый Microsoft Office, был на несколько порядков быстрее. Вы должны попробовать версии, к которым у вас есть доступ, и провести некоторые сравнения производительности.

Другие решения

Ваше использование MainRich.GetText() и избыточные звонки std::string::find() узкие места. Не извлекайте текст вообще. использование CRichEditCtrl::FindText() вместо.

Не восстанавливайте исходный формат исходного выделения в конце. Что, если выделенное ключевое слово было выбрано до того, как вы применили выделение? Вы бы отменили выделение для этого.

Другая оптимизация, которую вы можете сделать, чтобы ускорить RichEdit, заключается в использовании CRichEditCtrl::SetEventMask() отключить события (например, EN_SELCHANGE ) внося изменения в текст, а затем восстанавливайте их, когда закончите.

Окончательный подход к перфекту заключается в подключении API к TextOut.

Указать 100% правильно.

riched32.dll (richedit v1.0) импортирует из riched20.dll.

riched20.dll (richedit v2.0) использует: ExtTextOutA а также ExtTextOutW

Rtf теги и подсветка синтаксиса в richedit

К омпонент TRichEdit представляет собой многострочный редактор, работающий с расширенным текстовым форматом RTF. Текст формата RTF хранит дополнительную служебную информацию, управляющую свойствами каждого абзаца и сменой шрифта по ходу текста.

Рис. 18.23. Окно демонстрационной программы DEMOS | RICHEDIT | RICHED1T.EXE

Н а рис. 18.23 показан пример использования возможностей компонента. Полный текст программы, с помощью которой создан рисунок, приводится в папке demos | RICHEDIT | RICHEDIT.DPR, котораянаходится в каталоге размещения Delphi.

К омпонент использует вспомогательные объекты класса TTextAt-tributes для хранения атрибутов шрифта. Эти атрибуты распространяются на весь текст через свойство редактора DefAttributes или на выделенную часть текста — через его свойство SeiAttributes.

П омимо обычных шрифтовых свойств CharSet, Color, Height, Name, Pitch, Size И Style (см. класс TFont) объект TTextAttributes содержит также свойства consistentAttributes и protected. Первое доступно только для чтения и содержит набор текстовых характеристик, общих как для всего текста, так и для его выделенной части. Свойство protected защищает весь текст или его части от редактирования. Попытка изменить текст, имеющий атрибут protected, вызывает обработчик события OnProtectChange, который может разрешить или запретить изменения. По умолчанию изменения запрещены.

Илон Маск рекомендует:  Шлейф за курсором (IE)

Д ля каждого текстового абзаца создается объект класса трага-Attributes, в котором сохраняются атрибуты абзаца. Эти атрибуты доступны через следующие свойства класса TparaAttributes:

property Alignment: TAlignment; Определяет горизонтальное выравнивание текста абзаца относительно границ компонента
property Firstlndent: Longint; Указывает отступ текста абзаца в пикселях от предыдущего абзаца
property Leftlndent: Longint; Указывает отступ текста абзаца
в пикселях от левого края компонента
TNumberingStyle = (nsNone, nsBullet) ;
property Numbering: TNumberingStyle;
Указывает, надо ли вставлять слева от абзаца символы списка. Если содержит nsBullet, символы списка вставляются
property Rightlndent: Longint; Указывает отступ текста абзаца в пикселях от правого края компонента
property Tab[Index: Byte] : Longing; Для табулостопа с индексом index содержит его позицию в пикселях от левого края компонента
property TabCount: Irteger; Определяет количество табулостопов в строке абзаца

Свойства класса TRichEdit

property DefAttributes: TTextAttributes; Определяет шрифтовые атрибуты всего текста
TConversion >property DefaultConverter: TConversionClass; Свойство указывает класс конвертора, использующегося для преобразования текстовых форматов причтении или записи текста. По умолчанию нет преобразования
property HideScroliBars: Boolean; Определяет, будет ли редактор автоматически вставлять полосы прокрутки, если текст отсекается границами компонента. Игнорируется, если scrollBars содержит ssNone
property HideSelection: Boolean; Указывает, будет ли убираться выделение текста, если компонент потеряет фокус ввода
property Lines: TStrings; Содержит набор строк текста. С помощью его методов LoadFromFile и SaveToFile компонент может читать текст из файла или записывать в него текст
property PageRect: TRect; Указывает размеры страницы при печати на принтере
property Paragraph: TParaAttributes; Содержит атрибуты текущего абзаца, т. е. абзаца с выделением или с текстовым курсором. Программа не может изменить свойство paragraph, но может изменить свойства связанного с ним абзаца
property PlainText: Boolean; Запрещает/разрешает записывать в файл или читать из него служебную информацию формата RTF (True -запрещает)
property SelAttributes: TTextAttributes; Определяет шрифтовые атрибуты выделенного текста
property SelLength: Integer; Задает длину в символах выделенной части текста
property SelStart: Integer; Определяет номер первого символа выделенной части текста от начала текста (нумерация символов начинается
с 0). Если нет выделения, указывает символ, перед которым располагается текстовый курсор
property SelText: String; Содержит выделенный текст. Установка нового значения SelText заменяет выделенный текст на новый,
а если нет выделения — вставляет его в позицию курсора

Методы компонента:

procedure Clear; Удаляет весь текст
TSearchType = (stWholeWord,stMatchCase) ; TSearchTypes = set of TSearchType ; Ищет в тексте строку SearchStr и возвращает индекс первого ее символа при удачном поиске: StartPos — начало поиска:
function FindText(const SearchStr: String; StartPos, Length: Integer; Options: TSearchTypes) :Integer; Ищет в тексте строку SearchStr и возвращает индекс первого ее символа при удачном поиске: StartPos — начало поиска: Length-длина строки, options
указывает, будет ли поиск идти по целым словам и надо ли учитывать высоту букв
function GetSelTextBuf(Buffer: PChar; BufSize: Integer): Integer; Копирует не более BufSize символов выделенного текста в буфер Buffer и возвращает количество скопированных символов
procedure Print(const Caption: String) ; Форматирует текст по границам листа бумаги и печатает его на умалчиваемом принтере, caption определяет заголовок печати
TConversion >String; AConversionClass: TConversionClass) ; Устанавливает соответствие между расширением файла AExtension и конвертором текста

Д ля компонента определены такие события:

Rtf теги и подсветка синтаксиса в richedit

Профиль
Группа: Участник
Сообщений: 26
Регистрация: 29.1.2010

Репутация: нет
Всего: нет

Код
procedure TFormMain.PrintMessage(const Msg: string; Err: boolean);
begin
RichEdit1.SelLength:=0;
if Err then //цвет ошибок — красный
begin
RichEdit1.SelAttributes.Color:=clRed;
end
else //остального текста — черный
begin
RichEdit1.SelAttributes.Color:=clWindowText;
end;
RichEdit1.Lines.Append(Msg);
RichEdit1.Perform(EM_SCROLLCARET, 0, 0); //прокрутить скроллбар на последнюю строку
end;

Профиль
Группа: Модератор
Сообщений: 11360
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 483

Snowy
Дата 27.7.2010, 11:45 (ссылка) | (нет голосов) Загрузка .
Код
uses RichEdit;

procedure AddRtf(RichEdit: TRichEdit; Rtf: string);
function AddRtfCallback(dwCookie: Longint; pbBuff: PByte; cb: Longint; var pcb: Longint): Longint; stdcall;
var Stream: TStream;
begin
Stream := TStream(dwCookie);
Result := 0;
with Stream do
begin
if (Size = position) then pcb := 0
else if (Size — Position)

Профиль
Группа: Участник
Сообщений: 26
Регистрация: 29.1.2010

Репутация: нет
Всего: нет

PalychXX
Дата 27.7.2010, 13:27 (ссылка) | (нет голосов) Загрузка .
Google
Дата 12.11.2020, 17:12 (ссылка)

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) — крупнейшем в рунете сборнике материалов по Дельфи

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL
Правила форума «Delphi: Общие вопросы»