0

I have a C# winform project with a webbrowser control. I'm loading an HTML page with images into the webbrowser. Each image has a different ID:

<img src="F:\Temp\file12948.jpg" id="12948" width="180px">

Is there a way to pass the ID into a variable when clicking on the image so I can use the ID in my code? The path to the image can also be used as I can extract the number from there.

I have already searched here there and everywhere for a solution but can't find anything related.

Rado
  • 151
  • 2
  • 13
  • If you don't want any javascript code in the page, Possible duplicate of [.Net How to get the ID of the clicked Element in a Webbrowser](https://stackoverflow.com/q/41293979/11683). If you are happy with jsavascript click handlers, Possible duplicate of [WinForms - How do I execute C# application code from inside WebBrowser control?](https://stackoverflow.com/q/305915/11683). – GSerg Sep 09 '17 at 18:47
  • Thanks, already seen and tested the first one though. It seems to require using the webbrowser context menu rather than the left mouse button, which is what I'm looking for. – Rado Sep 09 '17 at 18:49
  • The JavaScript thing might do, if nothing else works. Are there any disadvantages to this other than the user may have disabled javascript in IE? – Rado Sep 09 '17 at 18:56

2 Answers2

3

You can dynamically attach to image's onClick event.

public class TestForm : Form
{
    WebBrowser _WebBrowser = null;
    public TestForm()
    {
        _WebBrowser = new WebBrowser();
        _WebBrowser.ScriptErrorsSuppressed = true;
        _WebBrowser.Dock = DockStyle.Fill;
        this.Controls.Add(_WebBrowser);

        WebBrowserDocumentCompletedEventHandler Completed = null;

        Completed = (s, e) =>
        {
            //add onclick event dynamically
            foreach (var img in _WebBrowser.Document.GetElementsByTagName("img").OfType<HtmlElement>())
            {
                img.AttachEventHandler("onclick", (_, __) => OnClick(img));
            }

            _WebBrowser.DocumentCompleted -= Completed;
        };

        _WebBrowser.DocumentCompleted += Completed;

        var imgurl = "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png";
        //_WebBrowser.Navigate("http://edition.cnn.com/2017/09/09/us/hurricane-irma-cuba-florida/index.html");
        _WebBrowser.DocumentText = $"<html>  <img src='{imgurl}' id=123 />  </html>";
    }

    void OnClick(HtmlElement img)
    {
        MessageBox.Show(img.GetAttribute("id"));
    }
}
L.B
  • 114,136
  • 19
  • 178
  • 224
1

On simple way would be to use browser navigation. When clicking you can navigate to a special URL, then you handle the Navigating event and if the url is the special url you cancel the navigation and handle the data.

public MainWindow()
{
    InitializeComponent();
    br.NavigateToString(@"<a href=""http://messages?id=12948""><img src=""F:\Temp\file12948.jpg"" id=""12948"" width=""180px"" ></a>");
    br.Navigating += this.Br_Navigating;
}

private void Br_Navigating(object sender, NavigatingCancelEventArgs e)
{
    if(e.Uri.Host == "messages")
    {
        MessageBox.Show(e.Uri.Query);
        e.Cancel = true;
    }
}

This works if you have some control over the HTML. You could also set the URL from JS if you don't want to add the anchor.

Edit

The above version is for a WPF application. The winforms version is as follows:

public Form1()
{
    InitializeComponent();
    webBrowser1.DocumentText = @"<a href=""http://messages?id=12948""><img src=""F:\Temp\file12948.jpg"" id=""12948"" width=""180px"" ></a>";
    webBrowser1.Navigating += this.webBrowser1_Navigating;

}

private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
    if (e.Url.Host == "messages")
    {
        MessageBox.Show(e.Url.Query);
        e.Cancel = true;
    }
}
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
  • Well it's part of a database project, all data are local. I've been thinking of something similar - navigate to another webbrowser instance instead of opening IE (I have the code for that) and then get the Uri from there. – Rado Sep 09 '17 at 19:12
  • It was my understanding you were using the web browser control, if so, the navigation would happen in the same instance, and if you cancel the navigation the users will never notice any navigation – Titian Cernicova-Dragomir Sep 09 '17 at 19:16
  • Well this code seems to be for WPF (does work there), but NavigatingCancelEventArgs is not supported by WinForms it seems. – Rado Sep 10 '17 at 18:51
  • @Rado Creating a win forms version now will post shortly, should still work. – Titian Cernicova-Dragomir Sep 10 '17 at 19:04
  • @Rado added a winforms version, the event arg type was different, but the technique works in pretty much the same way. – Titian Cernicova-Dragomir Sep 10 '17 at 19:07
  • @TitianCernicova-Dragomir the problem with your code is that you assume every image is in an `a` tag. There may be other images which don't trigger any navigation.. – L.B Sep 10 '17 at 20:33
  • Yes, that works. I actually tried the same thing except for using webBrowser1.Navigate instead of webBrowser1.DocumentText, but that didn't work. Thanks! – Rado Sep 10 '17 at 20:35
  • @L.B I do say that he needs to have control of the HTML for this to work. It is not necessary to wrap the IMG in an `a` tag, changing the HTML to trigger navigation on click from JavaScript is also an option. The advantage of using navigation is that it is simpler to code. – Titian Cernicova-Dragomir Sep 10 '17 at 20:38
  • @Rado don't forget to upvote and mark as answered if you found the answer useful. – Titian Cernicova-Dragomir Sep 10 '17 at 20:39
  • @TitianCernicova-Dragomir yes, but your code won't detect image clicks that don't trigger a navigation – L.B Sep 10 '17 at 20:43
  • @L.B Don't get me wrong, I like your answer better too, I did upvote it. But as long as you have control over the HTML, both can be used to achieve the same result. In some ways, my way may offer more flexibility, as the C# code doesn't have to care what the HTML looks like. The interface between the C# and the HTML is done through the URL and not the specific tags used. But weather that is an advantage depends on the use case. – Titian Cernicova-Dragomir Sep 10 '17 at 20:51
  • @TitianCernicova-Dragomir the keyword here is `as long as you have control over the HTML`. I don't say your answer wouldn't work or bad. Just includes some assumptions – L.B Sep 10 '17 at 20:53
  • @L.B yes, I agree, if you don't have control over the HTML your solution is the only one aplicable, but he does mention in the comment to my answer "Well it's part of a database project, all data are local". So he has full control over the HTML, probably just the web control to display something. – Titian Cernicova-Dragomir Sep 10 '17 at 20:56
  • @Titian upvoted but as I already had LBs solution working I've marked that as the answer. If there are problems with it I'll try yours instead of course. I do appreciate your help! – Rado Sep 10 '17 at 20:56
  • @Rado Sure no problem, 10x for the upvote, whichever you use is up to you either solution can work in the given scenario :) – Titian Cernicova-Dragomir Sep 10 '17 at 20:58