Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];

Вниз

ГипперСсылка   Найти похожие ветки 

 
Алексей Петухов   (2005-06-06 13:21) [0]

Здравствуйте, уважаемые Мастера.

Естсь необходимось реализовать в RichEdit-е что-то вроде гиппер ссылки. И что-бы при клике мышкой на ссылке вызывалась процедура в которой можно было обработать код ссылки.

Спасибо за помощь заранее.


 
sniknik ©   (2005-06-06 13:53) [1]


TTrainingForm = class(TBaseChildForm)
 ...
 DBRichEditTheori: TDBRichEdit;
 ...
 private
 procedure RunLink(var Msg: TMessage); message WM_NOTIFY;
 ...
end;

procedure TTrainingForm.RunLink(var Msg: TMessage);
var
 p: TENLink;
 strURL: string;
begin
 if (PNMHDR(Msg.lParam).code = EN_LINK) then begin
   p:= TENLink(Pointer(TWMNotify(Msg).NMHdr)^);
   if (p.Msg = WM_LBUTTONDOWN) then begin
     SendMessage(DBRichEditTheori.Handle, EM_EXSETSEL, 0, Longint(@(p.chrg)));
     strURL:= DBRichEditTheori.SelText;
     ShellExecute(Handle, "open", PChar(strURL), nil, nil, SW_SHOWNORMAL);
   end
 end
end;

procedure TTrainingForm.FormCreate(Sender: TObject);
var
 mask: Word;
begin
 mask:= SendMessage(DBRichEditTheori.Handle, EM_GETEVENTMASK, 0, 0);
 SendMessage(DBRichEditTheori.Handle, EM_SETEVENTMASK, 0, mask or ENM_LINK);
 SendMessage(DBRichEditTheori.Handle, EM_AUTOURLDETECT, Integer(True), 0);
end;

здесь
DBRichEditTheori это RichEdit
TrainingForm это форма на которой он лежит


 
sniknik ©   (2005-06-06 13:59) [2]

> DBRichEditTheori это RichEdit
сорри это DBRichEdit. но это неважно, мзначально отлаживалось все равно на RichEdit-е, в программу с базой перенесено потом, эо кусок из нее. (т.е. работать с RichEdit тоже будет)


 
Чапаев ©   (2005-06-06 14:05) [3]

На http://rusdoc.ru посмотри, относительно недавно была статья. Хотя там несколько иная задача стояла: автоматически выделять ссылки, а уж при нажатии на ссылку выполняется ассоциированное приложение.


 
Алексей Петухов   (2005-06-06 14:06) [4]

Спасибо попробую


 
sniknik ©   (2005-06-06 14:14) [5]

> автоматически выделять ссылки, а уж при нажатии на ссылку выполняется ассоциированное приложение.
вот это [1] тоже самое ...
из хелпа программы

...
Может содержать теоретический материал для каждого вопроса свой, или общий в любом вопросе.
Позволяются ссылки на внешние источники знаний.
Ссылки определяются по префиксам "ftp:", "http:", "www.", "\\", "file:"
Так для определения ссылки на материал в интернете можно написать http:\\сайт.ru или www.сайт.ru (www - эта форма нежелательна изза неоднозначного интерпретирования системой (не на всех машинах сработает в зависимости от настроек), желательно ссылки на www записывать в форме  http:\\www.сайт.ru)
Ссылки на компьютер в локальной сети \\server\path\file.ext, не стоит задавать ссылки на файлы в сети через расшаренные файлы, т.к. на другом компе где будут просматривать материал такой расшарки скорее всего не будет.
И ссылки на локальные файлы или на подключенный расшеренный диск file:D:\file.ext.
...


 
sniknik ©   (2005-06-06 14:21) [6]

и кстати ссылка не "левая" случайно? зашол посмотреть и не нашол ничего и близко похожего (просто интересно как другие делали), точнее ссылку не даш?


 
Алексей Петухов   (2005-06-07 17:28) [7]

Уточняю Вопрос:

Хотелось бы чтобы у гиперссылки текст и ссылка отличались (в TRichEdit-е это не получилось) - текст гипперссылки был произвольным.

И можно было просмотреть текст в двух вариантах:
1. В "нормальном" режиме где виден только текст ссылки и можно по ней перейти.
2. В режиме "разметки" - где видно и текст и ссылку.

пример:
1. версия для печати
2. <A href="http://www.delphimaster.ru/cgi-bin/forum.pl?id=1118049662&amp;n=0&amp;toprint=1">версия для печати</A>


 
sniknik ©   (2005-06-07 20:08) [8]

уточняю ответ:
не там ищеш, в таком случае тебе нужен компонент с поддержкой гипертекста а не рич техт формат.


 
sniknik ©   (2005-06-07 20:10) [9]

p.s. на самом деле > [7], это не уточнение а полный поворот в другую сторону. имхо.


 
Alexander Panov ©   (2005-06-07 20:15) [10]

Можно и в RichEdit, но это не такая простая задача, как кажется.


 
Alexander Panov ©   (2005-06-07 21:55) [11]

Как мне видится, общая схема такая:

1. Перед загрузкой файла в TRichEdit разбираем текст. Все гиперссылки заменяем на соответствующий текст. При этом сама ссылка вместе с текстом, ее начальная и конечная позиции в тексте сохраняются в примерную структуру вида

 TRecLink=record
   FullBeginPos,FullEndPos: Integer;   //Исходные позиции в тексте
   CurrBegPos, CurrEndPos: Integer;  //Текущие позиции
   FullLink: String;                 //Полный текст линка
   CurrLink: String;                //Текущий текст линка текст линка
 end;

Сама гиперссылка при этом удаляется из входного потока, остается текст.

Создаем массив таких структур.

2. Выводим текст в RichEdit, заменяя атрибуты текста на нужные для линков.

3. В RichEdit.OnMouseUp получаем номер символа, на котором пользователь кликнул мышкой, используя сообщение EM_CHARFROMPOS.

4. Для запуска соответствующей программы с нужным линком выбираем из массива структур нужный линк по полученной в п.3 позиции символа.

5. При корректировке пользователем в RichEdit динамически изменяем массив структур.

6. При сохранении в файл выполняем операции, обратную п.1.

В общем-то, вот и все.


 
Alexander Panov ©   (2005-06-07 23:25) [12]

если завтра будет время - код допишу. Самому интерсно стало-)


 
Alexander Panov ©   (2005-06-08 11:52) [13]

Вот код, не претендующий на целостное решение. Сделан в качестве примера.
Работает только со ссылками вида <a href="Url">text</a>.

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
 Dialogs, Buttons, ComCtrls, StdCtrls, RichEdit, ShellApi, ToolWin;

type

 TForm1 = class(TForm)
   re: TRichEdit;
   od: TOpenDialog;
   ToolBar1: TToolBar;
   SpeedButton1: TSpeedButton;
   procedure SpeedButton1Click(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
 private
   { Private declarations }
 public
 end;

 TRecLink=class
 public
   FPosInStr: Integer;
   FLengthInStr: Integer;
   FPosUrlInLink: Integer;
   FTextInLink: Integer;
   FPosAfterInStr: Integer;
   FLink: String;
   FUrl: String;
   FText: String;

   constructor Create(const aLink: String);

 end;

 TLinksClass=class
 private
   FSrcStr: String;
   FCurrStr: String;
   FFileName: String;
   FLinks: array of TRecLink;
   procedure ParseSrcStr;
   function GetCountLinks: Integer;
   function GetLink(Index: Integer): TRecLink;
 public
   FRE: TRichEdit;

   constructor Create(RE: TRichEdit);
   destructor Destroy; override;

   procedure SetBold(const aPos,aLen: Integer);
   procedure LoadFile(const aFileName: String);
   function IndexOf(const aPos: Integer): Integer;

   procedure OpenUrl(const Url: String);

   procedure reMouseMove(Sender: TObject; Shift: TShiftState; X,
     Y: Integer);

   procedure reMouseUp(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);

   property CurrStr: String read FCurrStr write FCurrStr;
   property SrcStr: String read FSrcStr write FSrcStr;

   property CountLinks: Integer read GetCountLinks;
   property Links[Index: Integer]: TRecLink read GetLink;default;
   property Re: TRichEdit read FRE write FRE;
 end;

var
 Form1: TForm1;
 LC: TLinksClass;

implementation

{$R *.dfm}

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
 if Assigned(LC) then LC.Free;
 LC := nil;
 if od.Execute then
 begin
   LC := TLinksCLass.Create(Re);
   LC.LoadFile(od.FileName);
 end;
end;

{ TRecLink }

constructor TRecLink.Create(const aLink: String);
var
 nPos: Integer;
begin

 Self.FLink := aLink;
 Self.FLengthInStr := Length(aLink);
 nPos := Pos("="",aLink);
 Self.FPosUrlInLink := nPos+2;

 nPos := Pos("">",aLink);
 Self.FUrl := Copy(aLink,Self.FPosUrlInLink, nPos-Self.FPosUrlInLink);
 Self.FTextInLink := nPos+2;

 nPos := Pos("</",aLink);
 Self.FText := Copy(aLink,Self.FTextInLink, nPos-Self.FTextInLink);

 nPos := Pos("">",aLink);
 Self.FUrl := Copy(aLink,Self.FPosUrlInLink, nPos-Self.FPosUrlInLink);
end;

{ TLinksClass }

constructor TLinksClass.Create(RE: TRichEdit);
begin
 FRE := RE;
 FRE.OnMouseMove := reMouseMove;
 FRE.OnMouseUp := reMouseUp;
end;

destructor TLinksClass.Destroy;
begin
 FRE.Lines.Clear;
 FRE.OnMouseMove := nil;
 FRE.OnMouseUp := nil;
end;

function TLinksClass.GetCountLinks: Integer;
begin
 Result := Length(FLinks);
end;

function TLinksClass.GetLink(Index: Integer): TRecLink;
begin
 Result := FLinks[Index];
end;

procedure TLinksClass.OpenUrl(const Url: String);
begin
 ShellExecute(0, "open", PChar(URL), nil, nil, SW_SHOWNORMAL);
end;

function TLinksClass.IndexOf(const aPos: Integer): Integer;
var
 i: Integer;
begin
 Result := -1;
 for i := 0 to LC.CountLinks-1 do
 begin
   if (aPos>=LC.Links[i].FPosAfterInStr) and (aPos<=LC.Links[i].FPosAfterInStr+Length(LC.Links[i].FText)) then
   begin
     Result := i;
     Exit;
   end;
 end;
end;

procedure TLinksClass.LoadFile(const aFileName: String);
var
 M: TFileStream;
 Len: Integer;
 i: Integer;
begin
 FFileName := aFileName;
 M := TFileStream.Create(FFileName,fmOpenRead );
 Len := M.Size;
 SetLength(FSrcStr,Len);
 M.Read(FSrcStr[1],Len);
 M.Free;
 ParseSrcStr;
 FRE.Lines.Text := CurrStr;
 for i := 0 to CountLinks-1 do
 begin
   SetBold(Links[i].FPosAfterInStr,Length(Links[i].FText));
 end;
end;

procedure TLinksClass.ParseSrcStr;
var
 i: Integer;
 isLink: Boolean;
 BegPos: Integer;
 Len: Integer;
 Link: String;
 CurrLen: Integer;
begin
 BegPos := 0;
 FCurrStr := "";
 isLink := False;
 i := 1;
 Len := 0;
 CurrLen := 0;
 SetLength(FCurrStr,Length(FSrcStr));
 while i<=Length(FSrcStr) do
 begin
   if not isLink then
   begin
     if UpperCase(Copy(FSrcStr,i,2))="<A" then
     begin
       BegPos := i;
       isLink := True;
     end
     else
     begin
       Inc(CurrLen);
       FCurrStr[CurrLen] := FSrcStr[i];
     end;
   end
   else
   begin
     if UpperCase(Copy(FSrcStr,i,4))="</A>" then
     begin
       isLink := False;
       SetLength(FLinks,Len+1);
       Link := Copy(FSrcStr,BegPos,i+4-BegPos);
       FLinks[Len] := TRecLink.Create(Link);
       FLinks[Len].FPosInStr := BegPos;
       FLinks[Len].FLengthInStr := Length(Link);
       Move(FLinks[Len].FText[1],FCurrStr[CurrLen+1],Length(FLinks[Len].FText));
       FLinks[Len].FPosAfterInStr := CurrLen;
       CurrLen := CurrLen+Length(FLinks[Len].FText);
       Inc(i,3);
       Inc(Len);
     end;
   end;
   Inc(i);
 end;
end;

procedure TLinksClass.reMouseMove(Sender: TObject; Shift: TShiftState; X,
 Y: Integer);
var
 P: TPoint;
begin
 P.X := X;
 P.Y := Y;
 if IndexOf(SendMessage(FRE.Handle,EM_CHARFROMPOS,0,Integer(@P)))=-1
   then FRE.Cursor := crDefault
   else FRE.Cursor := crHandPoint;
end;

procedure TLinksClass.reMouseUp(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
var
 P: TPoint;
 Res: Integer;
begin
 P.X := X;
 P.Y := Y;
 Res := IndexOf(SendMessage(FRE.Handle,EM_CHARFROMPOS,0,Integer(@P)));
 if Res=-1 then Exit;
 OpenUrl(Links[Res].FUrl);
end;

procedure TLinksClass.SetBold(const aPos, aLen: Integer);
begin
 FRE.SelStart := aPos;


 
Alexander Panov ©   (2005-06-08 11:52) [14]

 FRE.SelLength := aLen;
 FRE.SelAttributes.Color := clNavy;
 FRE.SelAttributes.Style := [fsBold];
 FRE.SelLength := 0;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 LC.Free;
end;

end.


 
Alexander Panov ©   (2005-06-08 11:53) [15]

Динамическое изменение массива ссылок при корректировке пользователем не сделано.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.51 MB
Время: 0.084 c
14-1117844669
Белолипский Александр
2005-06-04 04:24
2005.06.29
Я увлекаюся спортивною рыбалкой!


8-1109790766
seregka
2005-03-02 22:12
2005.06.29
Прозрачность изображения+наложение 2-х изображений


1-1117931633
grol
2005-06-05 04:33
2005.06.29
Работа с 3-х мерными массивами!


4-1115563018
kzpapgsnzaaret
2005-05-08 18:36
2005.06.29
текстовое поле ч чужом приложении


6-1111926043
Mylen Farmer
2005-03-27 16:20
2005.06.29
Проверка состояния соединения





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский