最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

winforms - C# Windows Forms and URL embedded in link names? - Stack Overflow

programmeradmin1浏览0评论

I have spent the last few hours trying to do something I thought would be basic stuff in my C# Windows Form application - to have a RichTextBox with embedded links. However, this seems to be far more complicated than anticipated, and I would appreciate some hints on this.

Please note that I am not sure if RTF and a RichTextBox is the one-and-only solution for me here, but my end-goal is that I can create something like this below:

So, a list of either web links or local files on system, and then I can of course click it and it will open. Some styling is needed also, like font-weight and bullets etc.

What I have so far is a RichTextBox named richTextBoxRessources.

I have tried this RTF code, and a million combinations in here:

string link2 = ";;
string name2 = "My Link";

StringBuilder rtf = new StringBuilder();
rtf.Append(@"{\rtf1\ansi");
rtf.Append(@"{\fonttbl\f0\fnil\fcharset0 Calibri;}");
rtf.Append(@"{\colortbl ;\red0\green0\blue255;}");
rtf.Append(@"\viewkind4\uc1\pard\f0\fs20 ");
rtf.Append($@"{{\field{{\*\fldinst HYPERLINK ""{link2}""}}{{\fldrslt{{\ul\cf1 {name2}}}}}}}");
rtf.Append(@"\par}");
richTextBoxRessources.Rtf = rtf.ToString();

Though it looks like a link in the RichTextBox, then it does not react when clicking in it.

Do note that I would need multiple links - not only one.

In my main form constructor I of course has its event-listener defined:

richTextBoxRessources.LinkClicked += richTextBoxRessources_LinkClicked;

And then its code:

private void richTextBoxRessources_LinkClicked(object sender, LinkClickedEventArgs e)
{
    Debug.WriteLine("Break-point set here");
}

As you can see in the text then I have just placed a break-point in here, but it never reaches in here, which is my problem.

I have also tried looking in to alternatives like the NuGet package EXTENDED Version of Extended Rich Text Box or Links with arbitrary text in a RichTextBox, but these I could not get working either.

I assume I must to do it with RTF code, as I need to do some bullets and font-weight also, but for now I am focusing on the embedded links.

Anyone have some good ideas for my embedded link problem?

UPDATE 1

I did find a possible "helper" for this, in this answer to Getting Hyperlinks Working in Rich Text Box Using RTF, but this is merely a "try and see if this is working", and no explanation for RTF.

  1. Create a Word file with the layout and links you want
  2. Copy/paste this to Wordpad
  3. Save as RTF file
  4. Load RTF file in text-editor and copy the RTF cod
  5. Insert RTF code in RichTextBox

This actually does make the web link clickable - but ONLY the first link!? All other links looks like normal links, but nothing happens when I click them - only the first link works.

This is my test code for it:

StringBuilder rtf = new StringBuilder();

rtf.Append("{\\rtf1\\ansi\\ansicpg1252\\deff0\\nouicompat\\deflang1033{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 Calibri; } {\\f1\\fnil\\fcharset0 Calibri; } {\\f2\\fnil\\fcharset2 Symbol; } }");
rtf.Append("{\\colortbl;\\red0\\green0\\blue255;\\red5\\green99\\blue193; }");
rtf.Append("{\\*\\generator Riched20 10.0.19041}\\viewkind4\\uc1");
rtf.Append("\\pard\\widctlpar\\sa160\\sl252\\slmult1\\kerning2\\f0\\fs22\\lang1030 Header 1:\\par");
rtf.Append("");
rtf.Append("\\pard{\\pntext\\f2\\'B7\\tab}{\\*\\pn\\pnlvlblt\\pnf2\\pnindent0{\\pntxtb\\'B7}}\\widctlpar\\fi-360\\li720\\sa160\\sl252\\slmult1 {{\\field{\\*\\fldinst{HYPERLINK \"https://link1\"}}{\\fldrslt{\\ul\\cf1\\cf2\\ul Link 1}}}}\\f0\\fs22\\par");
rtf.Append("{\\pntext\\f2\\'B7\\tab}{{\\field{\\*\\fldinst{HYPERLINK \"https://link2\"}}{\\fldrslt{\\ul\\cf1\\cf2\\ul Link 2}}}}\\f0\\fs22\\par");
rtf.Append("");
rtf.Append("\\pard\\widctlpar\\sa160\\sl252\\slmult1 Header 2:\\par");
rtf.Append("");
rtf.Append("\\pard{\\pntext\\f2\\'B7\\tab}{\\*\\pn\\pnlvlblt\\pnf2\\pnindent0{\\pntxtb\\'B7}}\\widctlpar\\fi-360\\li720\\sa160\\sl252\\slmult1 {{\\field{\\*\\fldinst{HYPERLINK \"https://link3\"}}{\\fldrslt{\\ul\\cf1\\cf2\\ul Link 3}}}}\\f0\\fs22\\par");
rtf.Append("");
rtf.Append("\\pard\\sa200\\sl276\\slmult1\\kerning0\\f1\\lang6\\par");
rtf.Append("}");

richTextBoxRessources.Rtf = rtf.ToString();

Someone in comment has suggested to look into "using HTML with a web browser control such as WebView2" - this method I don't know, but I will for sure look in to this, but I am fearing for the local links then.

UPDATE 2

i have tested the Microsoft.Web.WebView2 NuGet package, and this could work fine for web links, but as suspected then local file links does not work - it does not trigger the click-event for any files.

This is my code:

private async void InitializeWebView()
{
    await webView21.EnsureCoreWebView2Async(null);

    // Handle navigation events
    webView21.CoreWebView2.NavigationStarting += (sender, args) =>
    {
        Debug.WriteLine("NavigationStarting: " + args.Uri);
        if (args.Uri.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
        {
            args.Cancel = true;
            string localPath = new Uri(args.Uri).LocalPath;
            Process.Start(new ProcessStartInfo(localPath) { UseShellExecute = true });
        }
    };

    // HTML
    string htmlContent = @"
        <html>
        <head>
        <meta charset='UTF-8'>
        <title>Local File Test</title>
        </head>
        <body>
        <h1>Try opening local files:</h1>
        <ul>
        <li><a href='file:///C:\\GlDifxCmd.log'>Open local log file</a></li>
        <li><a href=''>Google</a></li>
        </ul>
        </body>
        </html>";

    webView21.NavigateToString(htmlContent);
}

The Debug.WriteLine is triggered at the web link, but not for the file link.

UPDATE 3

I am opting in for the an alternative solution, as handling RTF seems a little too complicated and weird for my taste. Instead of RTF and RichTextBox, I ended up using WebView2, which is a Microsoft NuGet package which will support internal generated HTML pages.

View the accepted answer below.

I have spent the last few hours trying to do something I thought would be basic stuff in my C# Windows Form application - to have a RichTextBox with embedded links. However, this seems to be far more complicated than anticipated, and I would appreciate some hints on this.

Please note that I am not sure if RTF and a RichTextBox is the one-and-only solution for me here, but my end-goal is that I can create something like this below:

So, a list of either web links or local files on system, and then I can of course click it and it will open. Some styling is needed also, like font-weight and bullets etc.

What I have so far is a RichTextBox named richTextBoxRessources.

I have tried this RTF code, and a million combinations in here:

string link2 = "https://whatever.dk";
string name2 = "My Link";

StringBuilder rtf = new StringBuilder();
rtf.Append(@"{\rtf1\ansi");
rtf.Append(@"{\fonttbl\f0\fnil\fcharset0 Calibri;}");
rtf.Append(@"{\colortbl ;\red0\green0\blue255;}");
rtf.Append(@"\viewkind4\uc1\pard\f0\fs20 ");
rtf.Append($@"{{\field{{\*\fldinst HYPERLINK ""{link2}""}}{{\fldrslt{{\ul\cf1 {name2}}}}}}}");
rtf.Append(@"\par}");
richTextBoxRessources.Rtf = rtf.ToString();

Though it looks like a link in the RichTextBox, then it does not react when clicking in it.

Do note that I would need multiple links - not only one.

In my main form constructor I of course has its event-listener defined:

richTextBoxRessources.LinkClicked += richTextBoxRessources_LinkClicked;

And then its code:

private void richTextBoxRessources_LinkClicked(object sender, LinkClickedEventArgs e)
{
    Debug.WriteLine("Break-point set here");
}

As you can see in the text then I have just placed a break-point in here, but it never reaches in here, which is my problem.

I have also tried looking in to alternatives like the NuGet package EXTENDED Version of Extended Rich Text Box or Links with arbitrary text in a RichTextBox, but these I could not get working either.

I assume I must to do it with RTF code, as I need to do some bullets and font-weight also, but for now I am focusing on the embedded links.

Anyone have some good ideas for my embedded link problem?

UPDATE 1

I did find a possible "helper" for this, in this answer to Getting Hyperlinks Working in Rich Text Box Using RTF, but this is merely a "try and see if this is working", and no explanation for RTF.

  1. Create a Word file with the layout and links you want
  2. Copy/paste this to Wordpad
  3. Save as RTF file
  4. Load RTF file in text-editor and copy the RTF cod
  5. Insert RTF code in RichTextBox

This actually does make the web link clickable - but ONLY the first link!? All other links looks like normal links, but nothing happens when I click them - only the first link works.

This is my test code for it:

StringBuilder rtf = new StringBuilder();

rtf.Append("{\\rtf1\\ansi\\ansicpg1252\\deff0\\nouicompat\\deflang1033{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 Calibri; } {\\f1\\fnil\\fcharset0 Calibri; } {\\f2\\fnil\\fcharset2 Symbol; } }");
rtf.Append("{\\colortbl;\\red0\\green0\\blue255;\\red5\\green99\\blue193; }");
rtf.Append("{\\*\\generator Riched20 10.0.19041}\\viewkind4\\uc1");
rtf.Append("\\pard\\widctlpar\\sa160\\sl252\\slmult1\\kerning2\\f0\\fs22\\lang1030 Header 1:\\par");
rtf.Append("");
rtf.Append("\\pard{\\pntext\\f2\\'B7\\tab}{\\*\\pn\\pnlvlblt\\pnf2\\pnindent0{\\pntxtb\\'B7}}\\widctlpar\\fi-360\\li720\\sa160\\sl252\\slmult1 {{\\field{\\*\\fldinst{HYPERLINK \"https://link1\"}}{\\fldrslt{\\ul\\cf1\\cf2\\ul Link 1}}}}\\f0\\fs22\\par");
rtf.Append("{\\pntext\\f2\\'B7\\tab}{{\\field{\\*\\fldinst{HYPERLINK \"https://link2\"}}{\\fldrslt{\\ul\\cf1\\cf2\\ul Link 2}}}}\\f0\\fs22\\par");
rtf.Append("");
rtf.Append("\\pard\\widctlpar\\sa160\\sl252\\slmult1 Header 2:\\par");
rtf.Append("");
rtf.Append("\\pard{\\pntext\\f2\\'B7\\tab}{\\*\\pn\\pnlvlblt\\pnf2\\pnindent0{\\pntxtb\\'B7}}\\widctlpar\\fi-360\\li720\\sa160\\sl252\\slmult1 {{\\field{\\*\\fldinst{HYPERLINK \"https://link3\"}}{\\fldrslt{\\ul\\cf1\\cf2\\ul Link 3}}}}\\f0\\fs22\\par");
rtf.Append("");
rtf.Append("\\pard\\sa200\\sl276\\slmult1\\kerning0\\f1\\lang6\\par");
rtf.Append("}");

richTextBoxRessources.Rtf = rtf.ToString();

Someone in comment has suggested to look into "using HTML with a web browser control such as WebView2" - this method I don't know, but I will for sure look in to this, but I am fearing for the local links then.

UPDATE 2

i have tested the Microsoft.Web.WebView2 NuGet package, and this could work fine for web links, but as suspected then local file links does not work - it does not trigger the click-event for any files.

This is my code:

private async void InitializeWebView()
{
    await webView21.EnsureCoreWebView2Async(null);

    // Handle navigation events
    webView21.CoreWebView2.NavigationStarting += (sender, args) =>
    {
        Debug.WriteLine("NavigationStarting: " + args.Uri);
        if (args.Uri.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
        {
            args.Cancel = true;
            string localPath = new Uri(args.Uri).LocalPath;
            Process.Start(new ProcessStartInfo(localPath) { UseShellExecute = true });
        }
    };

    // HTML
    string htmlContent = @"
        <html>
        <head>
        <meta charset='UTF-8'>
        <title>Local File Test</title>
        </head>
        <body>
        <h1>Try opening local files:</h1>
        <ul>
        <li><a href='file:///C:\\GlDifxCmd.log'>Open local log file</a></li>
        <li><a href='https://www.google'>Google</a></li>
        </ul>
        </body>
        </html>";

    webView21.NavigateToString(htmlContent);
}

The Debug.WriteLine is triggered at the web link, but not for the file link.

UPDATE 3

I am opting in for the an alternative solution, as handling RTF seems a little too complicated and weird for my taste. Instead of RTF and RichTextBox, I ended up using WebView2, which is a Microsoft NuGet package which will support internal generated HTML pages.

View the accepted answer below.

Share Improve this question edited Mar 25 at 9:37 Beauvais asked Mar 15 at 0:09 BeauvaisBeauvais 2,3195 gold badges34 silver badges70 bronze badges 8
  • This question is similar to: How can I make a hyperlink work in a RichTextBox?. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. – Trisped Commented Mar 15 at 0:20
  • It is not related to that, as I am handling RTF code, and not auto-detecting as-is links in the text. – Beauvais Commented Mar 15 at 0:25
  • That Control considers the text of the hyperlink, not the link itself. If you replace {file.Name} with file:////etc., it should work. Otherwise, you have to setup a CHARFORMAT2 struct and call SendMessage() with EM_SETCHARFORMAT to setup the link (the dwEffect member must contain CFE_LINK, I don't remember what dwMask should be set to. See the docs) – Jimi Commented Mar 15 at 1:22
  • @Jimi - as mentioned then the file:// part works already fine ;-) It is the web links that I cannot get working, but I will clarify this in my text. – Beauvais Commented Mar 15 at 9:11
  • for my purpose I need to work with RTF code...I need to do it with RTF code, as I need to do some bullets and font-weight etc..: You haven't really made a successful argument for why you need to use RTF, when with the limited information you've provided, it seems that using HTML with a web browser control such as WebView2 may be more appropriate. – It all makes cents Commented Mar 15 at 16:13
 |  Show 3 more comments

1 Answer 1

Reset to default 0

As suggested by one in the comments, then an alternative solution could be using WebView2, which is an internal rendered web page. I did not know this was a possibility, but now knowing this option, then I would prefer this solution over handling the weird RTF code.

I have settled for this solution, giving me this output here in my application:

I can tweak the layout easily, as this is web page rendering and by then quite easy.

The only anomaly is the browser engine generated "hover over link view", which looks a little weird in a Windows application (as shown by red arrow), but I assume this is just how it is, and that it cannot easily be hidden, as it is for the purpose of user security (to view link before clicking).

WebView2 handles also local files nicely.

My code is now this, but you will need to add the NuGet package named WebView2 from Microsoft, and you need to add a WebView2 component somewhere in your form (in my example it is named webView21):

private async void InitializeTabRessources()
{
    await webView21.EnsureCoreWebView2Async(null);

    webView21.CoreWebView2.WebMessageReceived += (sender, args) =>
    {
        string message = args.TryGetWebMessageAsString();
        if (message.StartsWith("openFile:"))
        {
            string fileUrl = message.Substring("openFile:".Length);
            Process.Start(new ProcessStartInfo(new Uri(fileUrl).LocalPath) { UseShellExecute = true });
        }
    };

    webView21.CoreWebView2.NewWindowRequested += (sender, args) =>
    {
        args.Handled = true; // Prevent the default behavior
        Process.Start(new ProcessStartInfo(args.Uri) { UseShellExecute = true });
    };

    // HTML code that will get internally rendered
    string htmlContent = @"
        <html>
        <head>
        <meta charset='UTF-8'>
        <script>
        document.addEventListener('click', function(e) {
        var target = e.target;
        if (target.tagName.toLowerCase() === 'a' && target.href.startsWith('file://')) {
            e.preventDefault();
            window.chrome.webview.postMessage('openFile:' + target.href);
        }
        });
        </script>
        </head>
        <body>
        <h1>Links</h1>
        <h2>Troubleshooting</h2>
        <ul>
        <li><a href='https://www.google' target='_blank'>Web link 1</a></li>
        <li><a href='https://www.microsoft' target='_blank'>Web link 2</a></li>
        </ul>
        <h2>Documentation</h2>
        <ul>
        <li><a href='https://www.google' target='_blank'>Web link 3</a></li>
        <li><a href='https://www.microsoft' target='_blank'>Web link 4</a></li>
        </ul>
        <h1>Local files</h1>
        <h2>Troubleshooting</h2>
        <ul>
        <li><a href='file:///C:/GlDifxCmd.log' target='_blank'>Local File 1</a></li>
        </ul>
        </body>
        </html>
    ";

    webView21.NavigateToString(htmlContent);
}
发布评论

评论列表(0)

  1. 暂无评论