powered by simpleCommunicator - 2.0.36     © 2025 Programmizd 02
Форумы / Delphi [игнор отключен] [закрыт для гостей] / SynEdit и подсветка текущего выделенного слова по документу
22 сообщений из 22, страница 1 из 1
SynEdit и подсветка текущего выделенного слова по документу
    #40108860
DelDelphi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Друзья, кто нибудь делал такое:
http://www.freepascal.ru/forum/viewtopic.php?f=44&t=7746&sid=ef6b81c47b1fe6b001bbc706a42111ac

Только в Delphi? Крайне не хочется портировать lazarus вариант, так как зависимостей там сотни и по простому вряд ли получится. Может кто-то уже делал подобное в Delphi?
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40108862
Фотография Кроик Семён
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На вскидку, начал бы искать в 2-ух направлениях:
- какое-нибудь событие, получающее на вход, скажем, очередное слово из сканируемого документа и возвращающее атрибуты текста
- либо, что лучше, возможность добавить зарезервированное слово, которое есть выделяемый текст
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40108866
DelDelphi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Тут скорее вопрос в том, есть ли что-то уже готовое и отлаженное. Сделать то велосипед можно, но займет немало времени, так как нужно чтобы работал на больших листингах и не тормозил приложение при постоянных щелчках по тексту туда-сюда. При этом адекватно работало обычное выделение. А это не "просто добавить кейворд" к сожалению.
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40108868
Softologic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DelDelphi
Тут скорее вопрос в том, есть ли что-то уже готовое и отлаженное. Сделать то велосипед можно, но займет немало времени, так как нужно чтобы работал на больших листингах и не тормозил приложение при постоянных щелчках по тексту туда-сюда. При этом адекватно работало обычное выделение. А это не "просто добавить кейворд" к сожалению.

Готовое и отлаженное решение, не тормозит: https://delphihtmlcomponents.com/index.html
Покрывает вашу задачу с легкостью на больших листингах, ну и много чего еще "из каропки". В вашем случае достаточно HTML Component Library, который стоит $349.
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40108869
Softologic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Две строчки кода:

Код: pascal
1.
2.
MailView.Doc.HighlightText := AnsiLowerCase(fSearchText);
MailView.Refresh();



Ниже результат - почтовый клиент на базе вышеупомянутого HTML Components (Bundle).
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40108870
Softologic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Точнее хотел сказать, что результат выполнения двух строчек кода представлен желтым выделенным фрагментом на скрине проекта. Вот :)
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40108873
Softologic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Еще есть вариант подешевле - https://www.trichview.ru/features/trichview.html
Не помню досконально, но вероятнее всего там тоже есть функция выделения повторяющегося фрагмента во всем тексте.
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40108874
DelDelphi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Softologic,

К сожалению ваши варианты вообще не к месту, так как в продукте уже реализован SynEdit с кастомно написанными хайлайтерами под разные языки, поддерживаемые нашим продуктом. Плюс море кастомных плюшек типа CodeFolding. Задача стоит добавить подсветку выделенных кейвордов по всему листингу используя именно SynEdit. Смена компонента не рассматривается.
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40108875
Softologic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DelDelphi
Softologic,

К сожалению ваши варианты вообще не к месту, так как в продукте уже реализован SynEdit с кастомно написанными хайлайтерами под разные языки, поддерживаемые нашим продуктом. Плюс море кастомных плюшек типа CodeFolding. Задача стоит добавить подсветку выделенных кейвордов по всему листингу используя именно SynEdit. Смена компонента не рассматривается.

Ну ок, если так. Просто изначально было не понятно, что все только в пределах SynEdit
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40108877
ma1tus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DelDelphi, пример
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40108914
DelDelphi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Softologic
Ну ок, если так. Просто изначально было не понятно, что все только в пределах SynEdit


Я потому сразу ссылку на Lazarus форум дал, так как нужен аналог. Задача в листингах до пары мегабайт щелкать по опкодам и операндам и чтобы аналогичные подсвечивались по всему тексту. Тупой search и подсветка тут непокатят - повиснет все после тысячного найденного eax или ebx (как пример). Надеялся что есть что-то уже отлаженное нативное, которое следит за скроллом, кареткой, перемещениями по тексту и подсвечивает асинхронно блоками динамически.

ma1tus, благодарю. Погляжу.
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40108943
kapas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В SynEdit для подобных вещей существует спец. класс TSynEditPlugin

С ним работать достаточно просто:

1. Определяем нужный тип
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
    TSelectTextMarkupHighlighter = class(TSynEditPlugin)
    private
        FAttribute: TSyntaxHighlighterAttribute;
        FEnabled: boolean;
        FWholeWordOnly: boolean;
        FCaseSensitivity: boolean;
    protected
      function GetEnabled(): boolean; overload; virtual;
      procedure SetEnabled(const AValue: boolean); overload; virtual;
      function GetWholeWordOnly(): boolean; overload; virtual;
      procedure SetWholeWordOnly(const AValue: boolean); overload; virtual;
      function GetCaseSensitivity(): boolean; overload; virtual;
      procedure SetCaseSensitivity(const AValue: boolean); overload; virtual;
    protected
      procedure AfterPaint(ACanvas: TCanvas; const AClip: TRect; AFirstRow, ALastRow: Integer); override;
    public
      procedure AfterConstruction(); override;
      destructor Destroy(); override;
    published
        property Attribute: TSyntaxHighlighterAttribute read FAttribute write FAttribute;
        property Enabled: boolean read GetEnabled write SetEnabled;
        property WholeWordOnly: boolean read GetWholeWordOnly write SetWholeWordOnly;
        property CaseSensitivity: boolean read GetCaseSensitivity write SetCaseSensitivity;
    end;


или
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
    TBlockMarker = class(TSynEditPlugin)
....
    protected
      procedure AfterPaint(ACanvas: TCanvas; const AClip: TRect; AFirstRow, ALastRow: integer); overload; override;
      procedure LinesInserted(AFirstRow, ACountRows: integer); overload; override; // обрабатываем вставки
      procedure LinesDeleted(AFirstRow, ACountRows: integer); overload; override;  // обрабатываем удаления
....
    public
//      procedure AfterConstruction(); override; // необязательно

    end;



2. Главная процедура (привожу рабочий вариант)

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
      procedure TSelectTextMarkupHighlighter.AfterPaint(ACanvas: TCanvas; const AClip: TRect; AFirstRow, ALastRow: Integer);
      var
        AStoreFont: TFont;
        AStoreBrush: TBrush;
        ASelectText: string;
        ACurrPt: TPoint;
        ARect: TRect;
        AIndexRow: Integer;
        ACurrCoord: TBufferCoord;
        ASelectCoord: TBufferCoord;
        ASelectEndCoord: TBufferCoord;
        ASearchPos: integer;
        AOffset: integer;
        ASelectSize: integer;
        ARow: string;
        AOrgRow: string;
        AOrgText: string;
      begin
        inherited AfterPaint(ACanvas, AClip, AFirstRow, ALastRow);
        if (not Enabled) then exit;
        if (not Editor.SelAvail) then exit;
        if (Editor.SelectionMode <> smNormal) then exit;
        ASelectText := Editor.SelText;
        ASelectSize := Editor.SelLength;
        ASelectCoord := Editor.CharIndexToRowCol(Editor.SelStart);
        ASelectEndCoord := Editor.CharIndexToRowCol(Editor.SelEnd);
        if (ASelectCoord.Line <> ASelectEndCoord.Line) then exit;
// Выделение располагается в одной строке!!!
        ARow := Editor.Lines[ASelectCoord.Line - 1];
        if (WholeWordOnly and (not ASelectText.WordInRow(ASelectCoord.Char, ARow))) then exit;
// Выделение есть слово!!!
        AStoreFont := TFont.Create();
        try
          AStoreFont.Assign(ACanvas.Font);
          AStoreBrush := TBrush.Create();
          try
            AStoreBrush.Assign(ACanvas.Brush);
            if (Attribute.Background <> clNone) then
              begin
                ACanvas.Brush.Color := Attribute.Background;
                ACanvas.Brush.Style := bsSolid
              end
            else
              begin
                ACanvas.Brush.Style := bsClear;
              end;
// Внимание, очень важно: свойства ACanvas.Pen нельзя менять - иначе будут проб-
// лемы с отрисовкой CodeFolding!
            AFirstRow := Editor.TopLine;
            ALastRow := Editor.TopLine + Editor.LinesInWindow - 1;
            if (not CaseSensitivity) then
              ASelectText := ASelectText.UpperCase();
            for AIndexRow := AFirstRow to ALastRow do
              begin
                AOffset := 1;
                ARow := Editor.Lines[AIndexRow - 1];
                AOrgRow := ARow;
                if (not CaseSensitivity) then
                  begin
                    ARow := Editor.Lines[AIndexRow - 1].UpperCase();
                  end;
                while (true) do
                  begin
                    ASearchPos := System.Pos(ASelectText, ARow, AOffset);
                    if (ASearchPos <= 0) then break;
                    if ((ASearchPos = ASelectCoord.Char) and (AIndexRow = ASelectCoord.Line)) then
                      begin
                        AOffset := ASearchPos + ASelectSize;
                        continue;
                      end;
                    if (WholeWordOnly and (not ASelectText.WordInRow(ASearchPos, ARow))) then
                      begin
                        AOffset := ASearchPos + ASelectSize;
                        continue;
                      end;
                    AOrgText := System.Copy(AOrgRow, ASearchPos, ASelectSize);
                    ACurrCoord := BufferCoord(ASearchPos, AIndexRow);
                    ACurrPt := Editor.RowColumnToPixels(Editor.BufferToDisplayPos(ACurrCoord));
                    ARect := Rect(ACurrPt.X, ACurrPt.Y, ACurrPt.X + Editor.CharWidth * ASelectSize, ACurrPt.Y + Editor.LineHeight);
                    ACanvas.FillRect(ARect);
                    ACanvas.TextRect(ARect, ACurrPt.X, ACurrPt.Y, AOrgText);
                    AOffset := ASearchPos + ASelectSize;
                  end
              end;
            ACanvas.Brush.Assign(AStoreBrush);
          finally
            System.SysUtils.FreeAndNil(AStoreBrush);
          end;
          ACanvas.Font.Assign(AStoreFont);
        finally
          System.SysUtils.FreeAndNil(AStoreFont);
        end;
        Editor.InvalidateGutterLines(AFirstRow, ALastRow);
        Editor.InvalidateLines(AFirstRow, ALastRow);
      end;



или (альтернативный, кода больше....)
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
      procedure TBlockMarker.AfterPaint(ACanvas: TCanvas; const AClip: TRect; AFirstRow, ALastRow: integer);
      var
        ABlockMarkup: TBlockMarkup;
      begin
        if (not Enabled) then exit;
// Рисуем то что нужно...
//        for ABlockMarkup in FMarkups do
//          begin
//            if (not ABlockMarkup.Check(Editor)) then continue;
//            ABlockMarkup.Draw(Editor, ACanvas);
//          end;
      end;



3. Инициализация
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
      procedure TfmEditDocument.FormCreate(Sender: TObject);
      begin
.............................
        ASelectTextMarkup := TSelectTextMarkupHighlighter.Create(edTextEdit);
        with ASelectTextMarkup do
          begin
            Attribute.Background := $008FA0EF; // $008FA0EF; // $00CFAAE7; // clYellow; // clMoneyGreen; //$0078AAFF; //$0078AAFF;
            Enabled := false;
          end;
        AMarkupBlocks := TBlockMarker.Create(edTextEdit);
        with AMarkupBlocks do
          begin
            Enabled := false;
          end;
......................
 end;    
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40109300
DelDelphi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kapas,

благодарю за ответ! К сожалению как вижу существует несколько форков SynEdit. Мой переработанный вариант основан на официальном sourceforge.net/projects/synedit/ (который мультиплатформенный под Delphi/Kylix). Пытался по простому интегрировать Ваш код в него - море всего не находит и в типах и в интерфейсе. Взять другой форк проблематично - так как много интегрировано собственных наработок в этот. Если есть время и желание - просьба подсказать пошагово сие внедрение. Увы без документации на интерфейсы SynEdit - равносильно это написать самому с нуля, чем внедрять то, что не внедряется.
Заранее благодарю если возникнет желание помочь.
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40109336
kapas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DelDelphi, могу только более подробно прокомментировать код. Не сегодня... :-(
1. Сам работаю с версией https://github.com/SynEdit/SynEdit
2. Этом коде в основном все стандартное из TSynEdit. Отдельные функции можно дописать самому

Успехов.
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40109416
Фотография Кроик Семён
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DelDelphi,

посмотрите примеры кода отсюда, это не оно? ( https://forum.lazarus.freepascal.org/index.php?topic=19424.0 )
в смысле, если по событию "выделение" определить, какая часть текста выделена и передать её в SynEdit.SetHighlightSearch(...)
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40109590
ma1tus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
не обязательно через search, не обязательно в плагине... отрисовкой только в видимых строках в его же обработчике; топорно, нативно, "на официальном"
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40109596
kapas
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ma1tus,
Можно и так :-) Дело вкуса.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
..........................
 if DoTransient then
  begin
    // plugins
    if FPlugins <> nil then
      for i := 0 to FPlugins.Count - 1 do
        TSynEditPlugin(FPlugins[i]).PaintTransient(Canvas, TransientType);
    // event
    if Assigned(FOnPaintTransient) then
    begin
      Canvas.Font.Assign(Font);
      Canvas.Brush.Color := Color;
      HideCaret;
      try
        FOnPaintTransient(Self, Canvas, TransientType);
      finally
        ShowCaret;
      end;
    end;
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40109639
ma1tus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kapas, ну да ) Привёл упрощенный.
С т.з. декомпозиции плагин предпочтительней
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40109699
DelDelphi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кроик Семён,

Это форум лазарус. Да, в нем все это сделано и работает. У меня как раз вопрос как это сделать в Delphi, не портируя горы лазарусовского кода. Задача усложняется тем, что нужна динамическая подсветка огромного числа кейвордов что под курсором где щелкнул пользователь. При этом листинги порой на пару мегабайт. В Lazarus реализовано с учетом этих вещей насколько я понял. То есть адаптивная подсветка по мере скролла (и также отмена подсветки старого кейворда), а не скопом всех мегабайт. Если реализовывать по простому - будет все жутко тормозить при щелчках пользователя с кейворда на кейворд, когда каждый встречается в листинге несколько сотен или тысяч раз (операнды и регистры ассемблера). А если начать щелкать быстрее - или повесит приложение или приведет к тормозам. Это не вариант.

Пока к сожалению все что вижу из советов - либо не потянет эту задачу или требует несколько дней на на внедрение/адаптацию и тестирование, учитывая что мой форк основан на SynEdit 2016 года + был полностью адаптирован под юникод (для продукта критичен корректный показ строк из иероглифов, строк справа налево и так далее со всем функционалом SynEdit. К сожалению взять другой форк не получится - много своих продуктозависимых вещей добавлено и исправлено. Мерджить десятки файлов и переписывать сотню функций - тестирования и отладки на месяц.
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40109702
DelDelphi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ma1tus,
kapas,
Вот это уже гораздо ближе, благодарю парни! Надо проверить на своей задаче. Отпишу.
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40109704
DelDelphi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ma1tus,

Благодарю! Именно то что искал!
...
Рейтинг: 0 / 0
SynEdit и подсветка текущего выделенного слова по документу
    #40114375
SergSni
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я как-то имел опыт использования PaintTransient и ...
Есть там ряд нюансов при рисовании. Например, надо следить чтобы не нарисовать на Gutter-e
А при перемещении курсора по строкам это событие всегда вызывается и как следствие все эти выделенные куски мигают при перерисовке. Мелочь, но неприятно и это я так и не победил
...
Рейтинг: 0 / 0
22 сообщений из 22, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / SynEdit и подсветка текущего выделенного слова по документу
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]