Page 1 of 2

Custom "Hyper"Links with custom targets

Posted: Wed Aug 10, 2011 9:09 am
by Roliat
Hi - me again (I'm feeling a bit dumb)!

But I got another question which I can't answer by myself. I just want to reach, that a specific Text (not an url) is highlighted and gets an custom onClick procedure in which a new Form is being opened.

Example:
[open/e67af2]My Link Text[/open]
This should open a form with the id "e67af2". The "open"-block should be erased an the id be stored in the text-info (or whatever) so that the TRichView only shows and highlights "My Link Text".

Can you tell me the way how I can reach this behaviour? With normal URLs it's ok (i think) but what about my "url-syntax". And I need this syntax....

Thank you very much.

Roliat

Posted: Wed Aug 10, 2011 9:12 am
by Sergey Tkachenko
Do you use RichViewActions?

Posted: Wed Aug 10, 2011 9:25 am
by Roliat
Thanks for your quick answer. Actually I dont use it, but if it necessary, i could do so.

Posted: Wed Aug 10, 2011 10:51 am
by Sergey Tkachenko
Ok, so we can base our code in Demos\Delphi\Assorted\Hypertext\CreateHyperlink\

This demo shows a dialog for entering hyperlink target. Then you press ok, it either creates a hyperlink from the selection, or (if the selection is empty), inserts a new link with the text 'New link'.
It is implemented in TForm1.SpeedButton1Click.
To test, you can simply type 'open/e67af2' in the dialog. In your application, you can implement your own hyperlink form returning the link's Target.

Next, what happens when you click the link: OnJump event occurs. See TForm1.RichViewEdit1Jump. First, it assigns the target of the clicked link to URL variable, then call ShellExecute to open this target.
In your case, 'open/e67af2' will be assigned to URL. In you application, you can place the code for processing this command instead of calling ShellExecute.

Posted: Wed Aug 10, 2011 11:00 am
by Roliat
Ok Thank you very much for your explanation. I looked at the demo some time ago but now I know exactly how it works ;)

But I got a further question. I'm switching my application to TRichView. So users made links in the past that now have to be detected and replaced (cutted the "[open/xxxxx]" and "[/open]", just leaving the linktext).

This could be more complicated, couldn't it? I have to search, replace and set the existing links manually, haven't I?

Thank you!

Posted: Thu Aug 11, 2011 3:07 pm
by Sergey Tkachenko
Are these documents stored as RTF, and all these '[open ... ]' are link target? Or are they visible text? You can send a sample file to richviewgmailcom.

Posted: Sun Aug 14, 2011 3:06 pm
by Roliat
Hi Sergey,

sorry, but I didn't recognize that you've posted again. These documents are RTF files, which are stored in a database. The "[open...]"-tag are visible plain text.

So the application should scan the visible Text for the "[open..]"-tags and should do the following:

1. Create a "hyperlink" with target "123aef" (e.g.)
2. Replace "[open/123aef]Link[/open]" with "Link"

Is that possible? I did already looked at your "ScanURLs" but I didn't really get it.

Many thanks

Posted: Mon Aug 15, 2011 1:22 pm
by Sergey Tkachenko
Are strings like "[open/123aef]Link[/open]" written using the same font? If yes, parsing will be simpler.

Posted: Mon Aug 15, 2011 5:01 pm
by Roliat
hey.

Yes, the strings are in the same font type, so I really need to parse the RTF. I thought of using regular expressions. That shouldn't be the problem. But I really don't understand your "ScanURLs" demo.

On wich events do I have to write my code for detecting or scanning my "hyperlinks".

Are Regular Expressions a good way or does your component deliver some special functions.

Please tell me, where do I have to add my code for scanning urls.

Thanks

Posted: Tue Aug 16, 2011 9:53 am
by Sergey Tkachenko
To process custom URL types in ScanURL, you need to assign your procedure to RVCustomURL variable, see http://www.trichview.com/help/idh_fun_r ... omurl.html .
However, in your case, this solution will work if the whole construction is a single word (i.e. does not contain characters from Delimiters property).
I.e., if the text is "[open/123aef]Link[/open], it will be passed to this function as it is. But if the text is "[open/123aef]Second link[/open]", it will be passed first as "[open/123aef]Second", then as "link[/open]".

So we need to create a custom procedure specially for you case. I'll try to make it tomorrow.

Posted: Tue Aug 16, 2011 10:11 am
by Roliat
Thanks for the explenation!
Between the brackets could be more than one word.

It's very kind of you to write the code for me and I'm really happy about it. I also will try it myself and if it works, i'll post my code. If not, I'm waiting for your solution!

Thanks, Roliat
Btw: Best support ever!

Posted: Thu Aug 18, 2011 11:27 am
by Roliat
Hi.

Sorry some bad news. As you might aleady have guessed - I've not made essential progress on the code.

Trying out more and also hoping that you post a piece of code.

Thanks

Posted: Thu Aug 18, 2011 5:31 pm
by Sergey Tkachenko
Sorry for delay :( I promise I will post a code sample tomorrow.

Posted: Fri Aug 19, 2011 4:18 pm
by Sergey Tkachenko
The code is below. This is may be not the most efficient method, but the simplest one. It uses editing methods.

Code: Select all

procedure DetectCustomLinks(RVData: TCustomRVFormattedData; rve: TCustomRichViewEdit);
var i,r,c,p1,p2,p3: Integer;
    s, Target, Text: String;
    Table: TRVTableItemInfo;
const OPENKEYWORD = '[open/';
      CLOSEKEYWORD = '[/open]';
begin
  i := RVData.ItemCount-1;
  while i>=0 do begin
    if (RVData.GetItemStyle(i)>=0) and (RVData.GetItemTag(i)=0) then begin
      s := RVData.GetItemText(i);
      p1 := Pos(OPENKEYWORD, s);
      if p1>0 then begin
        s := Copy(s, p1+Length(OPENKEYWORD), Length(s));
        p2 := Pos(']', s);
        if p2>0 then begin
          Target := Copy(s, 1, p2-1);
          p3 := Pos(CLOSEKEYWORD, s);
          if p3>0 then begin
            Text := Copy(s, p2+1, p3-p2-1);
            RVData := TCustomRVFormattedData(RVData.Edit);
            RVData.SetSelectionBounds(i, p1, i, p1+Length(OPENKEYWORD)+p3+Length(CLOSEKEYWORD)-1);
            rve.ApplyStyleConversion(CONVERT_TO_HYPERTEXT);
            rve.InsertStringTag(Text, Target);
            // for older versions of TRichView: rve.InsertStringTag(Text, Integer(StrNew(PChar(Target))));
            continue;
          end;
        end;
      end;
      end
    else if RVData.GetItemStyle(i)=rvsTable then begin
      Table := TRVTableItemInfo(RVData.GetItem(i));
      for r := 0 to Table.RowCount-1 do
        for c := 0 to Table.ColCount-1 do
          if Table.Cells[r,c]<>nil then
             DetectCustomLinks(TCustomRVFormattedData(Table.Cells[r,c].GetRVData), rve);
    end;
    dec(i);
  end;

end;
Call:

Code: Select all

  DetectCustomLinks(RichViewEdit1.RVData, RichViewEdit1);
I created this code as an addition to Assorted\Hypertext\CreateHyperlink\ demo, so it uses a style conversion CONVERT_TO_HYPERTEXT.

If you use procedures from Assorted\Hypertext\URLs\, then instead of rve.ApplyStyleConversion(CONVERT_TO_HYPERTEXT) you can write:

Code: Select all

URLScanEvent(RVData.GetItemStyle(i), r);
rve.ApplyTextStyle(r);
Update 2011-Oct-22: changed for compatibility with TRichView 13.3+

Posted: Sun Aug 21, 2011 1:36 pm
by Roliat
Hello!

Please apologize my delay. But sometime your board doesn't send me a notification. I just checked an the last mail was from "18.08.2011 19:31" (my timezone).

I just detected your code some minutes ago, so I couldn't check it. But I assume it will work great ;)

However, I'll post a reply when I worked with the code.

Thank you very much for your support.