Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Нажимаемый текст в TRichEdit (не только URL) / 11 сообщений из 11, страница 1 из 1
16.03.2018, 23:33
    #39616167
_Промешан_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нажимаемый текст в TRichEdit (не только URL)
Есть такой код
https://stackoverflow.com/questions/2480173/detect-click-on-url-in-richedit

Это связано с URL.

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

К примеру я хочу разместить файлы и при нажатии - открывать их. Предположительно файлы бы в тексте назывались (без полного пути): 1.jpg, 2.zip и тд.

Реализуемо?
...
Рейтинг: 0 / 0
17.03.2018, 01:13
    #39616179
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нажимаемый текст в TRichEdit (не только URL)
_Промешан_Реализуемо?

Лично я не вижу препятствий. Накладываешь CFE_LINK на любой кусок текста, ловишь EN_LINK,
обрабатываешь по своему разумению.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
17.03.2018, 18:06
    #39616278
_Промешан_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нажимаемый текст в TRichEdit (не только URL)
Dimitry Sibiryakov_Промешан_Реализуемо?

Лично я не вижу препятствий. Накладываешь CFE_LINK на любой кусок текста, ловишь EN_LINK,
обрабатываешь по своему разумению.

А есть более полный код? В приведенном по ссылке есть переменные, которые нигде не объявлены. Например:
Код: pascal
1.
SendMessage(RichEdit1.Handle, EM_EXSETSEL, 0, LongInt(@chrg)); 



Плюс - где хранить непосредственные ссылки, которые по тексту будут отрабатывать? Отдельный лист вести где есть ссылка на сам текст после установки CFE_LINK?
...
Рейтинг: 0 / 0
17.03.2018, 20:02
    #39616300
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нажимаемый текст в TRichEdit (не только URL)
Ты прямо в MSDN смотри, а не в примеры. Там чёрным по-англицки расписано что в какие
параметры совать.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
22.03.2018, 22:18
    #39619151
_Промешан_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нажимаемый текст в TRichEdit (не только URL)
Dimitry SibiryakovТы прямо в MSDN смотри, а не в примеры. Там чёрным по-англицки расписано что в какие
параметры совать.

А можно ссылкой?
...
Рейтинг: 0 / 0
22.03.2018, 23:10
    #39619163
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нажимаемый текст в TRichEdit (не только URL)
...
Рейтинг: 0 / 0
23.03.2018, 23:16
    #39619870
_Промешан_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нажимаемый текст в TRichEdit (не только URL)
Dimitry Sibiryakov https://msdn.microsoft.com/en-us/library/windows/desktop/bb774230(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/bb787883(v=vs.85).aspx

Прочитал.
Попытался погуглить код, находится пока только вариант как тексту линк сделать. Но без примеров, как сохранить к этому тексту доп информацию (какую-то структуру данных)
А вот как отработать нажатие по тексту с EN_LINK и взять эти данные - не нашел.
...
Рейтинг: 0 / 0
24.03.2018, 00:51
    #39619881
_Промешан_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нажимаемый текст в TRichEdit (не только URL)
В общем более менее нашел код. Копал отсюда: https://stackoverflow.com/questions/42532760/adding-true-hyperlink-support-to-trichedit?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

Получил такой код, только он не совсем корректно работает с текстом. Я уже и так и эдак поизвращался (строка dec(SelStart,2 * FRichEdit.Lines.Text.CountChar(#$D)); дает это понять), но так и не смог правильно выделить текст. То не выделяет начало текста, то конец.
И каким-то образом это кратно наличию #$D#$A в тексте.

Код: 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.
procedure TRichEditExtended.InsertLinkText(const LinkText: string; SelStart: integer = -1);
var
  Fmt: CHARFORMAT2;
begin
  if SelStart = -1 then
  begin
    SelStart := FRichEdit.Lines.Text.Length;
    FRichEdit.Text := FRichEdit.Text + LinkText;
    dec(SelStart,2 * FRichEdit.Lines.Text.CountChar(#$D));
  end
  else
  begin
    FRichEdit.SelStart := SelStart;
    FRichEdit.SelText := LinkText;
  end;
  FRichEdit.SelStart := SelStart;
  FRichEdit.SelLength := Length(LinkText);

  FillChar(Fmt, SizeOf(Fmt), 0);
  Fmt.cbSize := SizeOf(Fmt);
  Fmt.dwMask := CFM_LINK;
  Fmt.dwEffects := CFE_LINK;

  SendMessage(FRichEdit.Handle, EM_SETCHARFORMAT, SCF_SELECTION, LPARAM(@Fmt));

  FRichEdit.SelStart := SelStart + Length(LinkText);
  FRichEdit.SelLength := 0;
end;



Помогите плиз.
...
Рейтинг: 0 / 0
24.03.2018, 00:55
    #39619883
_Промешан_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нажимаемый текст в TRichEdit (не только URL)
Так, кажется я накостылил, изменив этот код:

Код: pascal
1.
2.
3.
4.
    
    SelStart := FRichEdit.Lines.Text.Length - 1;
    FRichEdit.Text := FRichEdit.Text + LinkText;
    dec(SelStart,2 * (FRichEdit.Lines.Text.CountChar(#$D) - 1));



И все заработало.
Но если вы знаете более адекватный способ, пожааалуйста, стукните мне по голове и подскажите :)
...
Рейтинг: 0 / 0
24.03.2018, 01:26
    #39619889
_Промешан_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нажимаемый текст в TRichEdit (не только URL)
Теперь другой вопрос возникает.

Вся эта тема с помечанием линка работает только для последнего добавленного текста.

Как сделать, чтобы это работало для всех добавляемых текстов, которые могут быть в разных местах всего RichEdit.Text ?

Мой рабочий юнит, который нужно подключить в проект

Код: 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.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
unit uRichEditExtended;

interface
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, RichEdit, WinApi.ShellApi, Vcl.Controls, Vcl.ComCtrls,
  Generics.Collections;

type
  TZ_RichEditClickEvent = reference to procedure(const ALinkText: string);

  TZ_RichEditLink = class
    IsDefaultEvent: boolean;
    Text: string;
    OnLinkClickEvent: TZ_RichEditClickEvent;
  end;

  TZ_RichEditLinks = TList<TZ_RichEditLink>;

  TRichEditExtended = class
  protected
    class var FInstance: TRichEditExtended;
  private
    FPrevRichEditWndProc: TWndMethod;
    FRichEdit: TRichEdit;
    FRichEditLinks: TZ_RichEditLinks;
    procedure InsertLinkText(const LinkText: string; SelStart: integer = -1);
    procedure SetRichEditMasks;
    procedure RichEditWndProc(var Message: TMessage);
    procedure AfterConstruction; override;
    procedure BeforeDestruction; override;
  public
    class function This: TRichEditExtended;
    class procedure ApplyRichEdit(ARichEdit: TRichEdit);                              // -1 - вставка в конец текста, иначе в позицию указанную в SelStart без сдвига
    class function AddLinkText(AText: string; AOnLinkClickEvent: TZ_RichEditClickEvent; SelStart: integer = -1): integer;
    class function AddLinkTextWithDefaultEvent(AText: string; SelStart: integer = -1): integer;
    class procedure AddDefaultLinkTextEvent(AOnLinkClickEvent: TZ_RichEditClickEvent);
  end;

implementation

{ TRichEditExtended }
uses StrUtils;

class procedure TRichEditExtended.AddDefaultLinkTextEvent(AOnLinkClickEvent: TZ_RichEditClickEvent);
var
  REL: TZ_RichEditLink;
begin
  if (This.FRichEditLinks.Count > 0) and This.FRichEditLinks[0].IsDefaultEvent then
    This.FRichEditLinks[0].OnLinkClickEvent := AOnLinkClickEvent
  else
  begin
    REL := TZ_RichEditLink.Create;
    REL.IsDefaultEvent := true;
    REL.Text := '';
    REL.OnLinkClickEvent := AOnLinkClickEvent;
    This.FRichEditLinks.Insert(0, REL);
    REL := nil;
  end;
end;

class function TRichEditExtended.AddLinkText(AText: string; AOnLinkClickEvent: TZ_RichEditClickEvent; SelStart: integer = -1): integer;
var REL: TZ_RichEditLink;
begin
  REL := TZ_RichEditLink.Create;
  REL.IsDefaultEvent := false;
  REL.Text := AText;
  REL.OnLinkClickEvent := AOnLinkClickEvent;
  Result := This.FRichEditLinks.Add(REL);
  This.InsertLinkText(AText, SelStart);
  REL := nil;
end;

class function TRichEditExtended.AddLinkTextWithDefaultEvent(AText: string; SelStart: integer): integer;
begin
  This.AddLinkText(AText, nil, SelStart);
end;

procedure TRichEditExtended.AfterConstruction;
begin
  inherited;
  FRichEdit := nil;
  FRichEditLinks := TZ_RichEditLinks.Create;
end;

class procedure TRichEditExtended.ApplyRichEdit(ARichEdit: TRichEdit);
begin
  This.FRichEdit := ARichEdit;
  This.FPrevRichEditWndProc := This.FRichEdit.WindowProc;
  This.FRichEdit.WindowProc := This.RichEditWndProc;
  This.FRichEditLinks.Clear;
  This.SetRichEditMasks;
end;

procedure TRichEditExtended.BeforeDestruction;
begin
  if Assigned(FRichEdit) then
    FRichEdit.WindowProc := FPrevRichEditWndProc;
  FRichEdit := nil;
  FRichEditLinks.Clear;
  FRichEditLinks.Free;
  inherited;
end;

procedure TRichEditExtended.InsertLinkText(const LinkText: string; SelStart: integer = -1);
var
  Fmt: CHARFORMAT2;
begin
  if SelStart = -1 then
  begin
    SelStart := FRichEdit.Lines.Text.Length - 1;
    FRichEdit.Text := FRichEdit.Text + LinkText;
    dec(SelStart,2 * (FRichEdit.Lines.Text.CountChar(#$D) - 1));
  end
  else
  begin
    FRichEdit.SelStart := SelStart;
    FRichEdit.SelText := LinkText;
  end;
  FRichEdit.SelStart := SelStart;
  FRichEdit.SelLength := Length(LinkText);

  FillChar(Fmt, SizeOf(Fmt), 0);
  Fmt.cbSize := SizeOf(Fmt);
  Fmt.dwMask := CFM_LINK;
  Fmt.dwEffects := CFE_LINK;

  SendMessage(FRichEdit.Handle, EM_SETCHARFORMAT, SCF_SELECTION, LPARAM(@Fmt));

  FRichEdit.SelStart := SelStart + Length(LinkText);
  FRichEdit.SelLength := 0;
end;

procedure TRichEditExtended.RichEditWndProc(var Message: TMessage);
type
  PENLINK = ^ENLINK;
var
  tr: TEXTRANGE;
  str: string;
  p: PENLINK;
  i: integer;
begin
  FPrevRichEditWndProc(Message);

  case Message.Msg of
    CN_NOTIFY: begin
     if TWMNotify(Message).NMHdr.code = EN_LINK then
      begin
        P := PENLINK(Message.LParam);
        if p.msg = WM_LBUTTONDOWN then
        begin
          SetLength(str, p.chrg.cpMax - p.chrg.cpMin);
          tr.chrg := p.chrg;
          tr.lpstrText := PChar(str);
          SendMessage(FRichEdit.Handle, EM_GETTEXTRANGE, 0, LPARAM(@tr));

          for I := 0 to FRichEditLinks.Count - 1 do
            if str.ToUpper.Equals(FRichEditLinks[I].Text.ToUpper)  then
            begin
              if not Assigned(FRichEditLinks[I].OnLinkClickEvent) then
              begin
                if not FRichEditLinks[0].IsDefaultEvent then
                  raise Exception.Create('Необходимо назначить событие по умолчанию.')
                else
                  FRichEditLinks[0].OnLinkClickEvent(str)
              end
              else
                FRichEditLinks[I].OnLinkClickEvent(str);
              exit;
            end;
        end;
      end;
    end;

    CM_RECREATEWND: begin
      SetRichEditMasks;
    end;
  end;
end;

procedure TRichEditExtended.SetRichEditMasks;
var
  Mask: DWORD;
begin
  Mask := SendMessage(FRichEdit.Handle, EM_GETEVENTMASK, 0, 0);
  SendMessage(FRichEdit.Handle, EM_SETEVENTMASK, 0, Mask or ENM_LINK);
  SendMessage(FRichEdit.Handle, EM_AUTOURLDETECT, 1, 0);
end;

class function TRichEditExtended.This: TRichEditExtended;
begin
  if not Assigned(TRichEditExtended.FInstance) then
    TRichEditExtended.FInstance := TRichEditExtended.Create;
  Result := TRichEditExtended.FInstance;
end;

{ TRichEditExList }

initialization

finalization
  if Assigned(TRichEditExtended.FInstance) then
    TRichEditExtended.FInstance.Free;

end.



В FormCreate:
Код: pascal
1.
2.
3.
4.
5.
  TRichEditExtended.ApplyRichEdit(ed1);
  TRichEditExtended.AddDefaultLinkTextEvent(procedure (const T: String)begin showmessage(T); end);
  TRichEditExtended.AddLinkTextWithDefaultEvent('Link');
  ed1.Text := ed1.Text + '1231232  ';
  TRichEditExtended.AddLinkTextWithDefaultEvent('Link2');



Будет видно, что отмечен только Link2.
Link первый - обычным текстом.

Мне не хватает куска мозга, чтобы понять, какие финты надо сделать, чтобы это работало для всех вставляемых Link-текстов.
...
Рейтинг: 0 / 0
27.03.2018, 20:56
    #39621573
_Промешан_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нажимаемый текст в TRichEdit (не только URL)
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Нажимаемый текст в TRichEdit (не только URL) / 11 сообщений из 11, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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