Подсветить символы в RichEdit

Иногда бывает так: есть какой-то текст, с виду обычный, ни чем не примечательный текст. А все буквы в нём заменены на аналоги в русском/английском. Выглядит так же, а для проверки на уникальность или для поисковых систем, скажем, не очень хороший текст.

Итак, поставим простую задачу: выделить цветом все русские (или английские буквы) в RichEdit.

Вспомним ASCII-коды букв: 192-255 для русских, 65-90 и 97-122 для английских.

Теперь нам нужно пройтись циклом по всем буквам, выделяя их и проверяя:

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  i: Integer;
  Selected: Char;
begin
  for i:=0 to Length(RichEdit1.Lines.Text)-1 do begin
    RichEdit1.SelStart:=i;
    RichEdit1.SelLength:=1;
    if Length(RichEdit1.SelText)<>1 then
      Continue;
    Selected:=RichEdit1.SelText[1];
    case ord(Selected) of
      192..255{рус}: RichEdit1.SelAttributes.Color:=clRed;
      else
        RichEdit1.SelAttributes.Color:=clBlack;
    end; // case
  end;
end;

Проверку на длину выделенного символа сделал, так как вылетал access violation error, скорее всего в связи с переходами на новую строку, нашёл это решение на http://www.cyberforum.ru/.

Итак, вся суть в свойствах SelStart, SelLength и SelText. Таким образом можно выделить произвольный фрагмент и получить его содержание. А с помощью SelAttributes присвоить какой-нибудь стиль выделенному фрагменту. Я сделал шрифт красным.

Скачать исходник и готовую программу: подсветка символов в RichEdit

UPD. Читатели напоминают про методы BeginUpdate и EndUpdate, которые целесообразно разместить в начале и конце функции. Особенно разница будет заметна при больших объёмах текста.

Давно у меня не было подробных больших постов. Больше всего люблю их писать, да и интересно получается. Вот например: решение судоку на delphi. Там я полностью описал алгоритм решения, есть исходник и полностью рабочая программа. Люди уже курсовые по ней писали – минимум три человека в аську стучало, совета просили по коду :)

8 ответов к «Подсветить символы в RichEdit»

  1. Крайне неэффективный алгоритм. Система будет тратить кучу времени на прорисовку всех этих селектов, хотя большинство из них и не нужны.

    Вначале нужно узнать длину всего текста и записать в переменную, чтобы не проверять каждый раз.

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

    Вместо селекта нужно напрямую проверять символ в строке — S[i] in SetRus, а то может вообще в тексте нет русских букв, а выделять приходится все.

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

    Перед изменением контрола заблокировать его обновление через BeginUpdate.

  2. Неплохо было бы вызвать методы Rich.BeginUpdate
    Rich.EndUpdate

    чтобы не тратить кучу времени на лишнюю перерисовку, т.к. она занимает о-о-очень много времени(у меня ~10 к 1)

  3. if Length(RichEdit1.SelText)1 then begin
    Continue;
    Selected:=RichEdit1.SelText[1];
    case ord(Selected) of
    192..255{рус}: RichEdit1.SelAttributes.Color:=clRed;
    end
    else
    RichEdit1.SelAttributes.Color:=clBlack;
    end; // case
    end;

    IF в begin — end не надо обрамить? а то при выполнении выполняется только Continue.

  4. Можно провести аналогию с системой проверки орфографии. Только та работает в отдельном потоке, на лету, а это так сказать, один раз запустить) Кстати, кто сможет подсказать, как подчеркнуть слово в TRichEdit волнистой чертой?

Добавить комментарий для robt Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *