Getting mouse click coordinates in a WebBrowser Do

2020-02-13 04:01发布

问题:

I am capturing click coordinates within a PictureBox but I want to achieve the same thing with a WebBrowser. After some research I found out that it is not possible to subscribe to the Mouse Click event of a WebBrowser control.
What are the possible ways to capture the clicks? Is there a sort of element which would allow me to navigate through the page but still capture the click?

I tried to create a transparent panel but transparent color doesn't mean see through as I see and when the element is in the back also doesn't capture the click, being able to capture the clicks with panel being behind the WebBrowser would also work.

PictureBox code:

private void uploadedPNG_MouseClick(object sender, MouseEventArgs e)
{
    if(uploadedPNG.Image != null && !string.IsNullOrEmpty(deviceHeight.Text) && !string.IsNullOrEmpty(deviceWidth.Text))
    {
        mouseX = e.X;
        mouseY = e.Y;
        targetHeight = Int32.Parse(deviceHeight.Text);
        targetWidth = Int32.Parse(deviceWidth.Text);
        int outPutWidth = (mouseX * targetWidth) / uploadedPNG.Width;
        int outPutHeight = (mouseY * targetHeight) / uploadedPNG.Height;
        ConsoleText.Text = "Clicked X coordinate " + outPutWidth + " Clicked Y coordinate " + outPutHeight;
    }
}

回答1:

The WebBrowser itself doesn't provide Mouse Click coordinates: you're not actually clicking on the Control client area, you're clicking on the content of the HtmlDocument.

You can use the HtmlDocument.Click or HtmlDocument.MouseDown events to retrieve the Mouse pointer coordinates on an initialized HtmlDocument.

Note:
The HtmlElementEventArgs object returns the Mouse coordinates in both absolute coordinates (the whole Document area), in e.ClientMousePosition and relative to the clicked HtmlElement, in e.OffsetMousePosition.

This can be tricky, because you need to subscribe to the Click event when the current HtmlDocument is already created: you cannot subscribe to the event of the default Document object:
i.e., subscribing to the event in Form.Load with:

webBrowser1.Document.Click += (obj, evt) => { /*Do something */ };  

will not accomplish anything. The event will never be raised: the Document is null thus, of course, it's not referency any current/active HtmlDocument.

An HtmlDocument is ready when the WebBrowser.DocumentCompleted event is raised and its ReadyState is set to WebBrowserReadyState.Complete.

You can subscribe to the Document.Click event when the Document is fully loaded, then remove the event before the WebBrowser navigates to a new page, creating a new document.

Also, the DocumentCompleted event may be raised multiple times for a single HTMLpage, so you need to be sure that you don't subscribe to the same event multiple times:

Note:
A HtmlDocument may contain more than one Frame/IFrame and each Frame may have its own HtmlDocument; IFrames have one each for sure. Refer to the notes in this question for more informations on this matter:
How to get an HtmlElement value inside Frames/IFrames?

An example:

bool WebBrowserDocumentEventSet = false;

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    WebBrowser wb = (sender as WebBrowser);
    if (wb.ReadyState == WebBrowserReadyState.Complete && WebBrowserDocumentEventSet == false)
    {
        WebBrowserDocumentEventSet = true;
        wb.Document.MouseDown += this.OnHtmlDocumentClick;
    }
}

private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
    (sender as WebBrowser).Document.MouseDown -= this.OnHtmlDocumentClick;
    WebBrowserDocumentEventSet = false;
}

protected void OnHtmlDocumentClick(object sender, HtmlElementEventArgs e)
{
    Console.WriteLine(e.ClientMousePosition);
}