开发者

getting absolute position of HTML element in webbrowser control with C#

开发者 https://www.devze.com 2023-03-05 09:18 出处:网络
I was wondering if its possible to get the absolute position of specific HTML element I have loade开发者_运维技巧d in webbrowser control with C#.

I was wondering if its possible to get the absolute position of specific HTML element I have loade开发者_运维技巧d in webbrowser control with C#.

I tried almost all of the options that .Net provides.. none of them give me the correct position. all of them give me 0 for Y coordinate.. the element is definitely is not in 0..

does anybody have any solution or idea to solve this?


here is the solution I got so far:

// set the size of our web browser to be the same size as the image int width, height; width = webBrowser1.Document.Images[0].ClientRectangle.Width; height = webBrowser1.Document.Images[0].ClientRectangle.Height;

webBrowser1.Width = width;
webBrowser1.Height = height;

//scroll vertically to that element
webBrowser1.Document.Images[0].OffsetParent.ScrollIntoView(true);

//calculate x, y offset of the element
int x = webBrowser1.Document.Images[s].OffsetRectangle.Left + 
webBrowser1.Document.Images[s].OffsetParent.OffsetRectangle.Left + 
webBrowser1.Document.Images[s].OffsetParent.OffsetParent.OffsetRectangle.Left+
webBrowser1.Document.Images[s].OffsetParent.OffsetParent.OffsetParent.OffsetRectangle.Left+
webBrowser1.Document.Images[s].OffsetParent.OffsetParent.OffsetParent.OffsetParent.OffsetRectangle.Left;

int y = webBrowser1.Document.GetElementsByTagName("HTML")[0].ScrollTop;

//now scroll to that element
webBrowser1.Document.Window.ScrollTo(x, y);

now this code works perfectly.. but there is an issue with calculating the offsets. I need to calculate the offsetparent of the element then calculate the offsetparent of the offsetparent etc.. I need to do that dynamically not adding it one by one.. I don't know how to do that. any ideas?

EDIT: here is my last and final version and it works with any html element it will find the absolute position of any element I want..

   public int getXoffset(HtmlElement el)
     {
         //get element pos
         int xPos = el.OffsetRectangle.Left;

         //get the parents pos
         HtmlElement tempEl = el.OffsetParent;
         while (tempEl != null)
         {
             xPos += tempEl.OffsetRectangle.Left;
             tempEl = tempEl.OffsetParent;
         }

         return xPos; 
     }  

     public int getYoffset(HtmlElement el)
     {
         //get element pos
         int yPos = el.OffsetRectangle.Top;

         //get the parents pos
         HtmlElement tempEl = el.OffsetParent;
         while (tempEl != null)
         {
             yPos += tempEl.OffsetRectangle.Top;
             tempEl = tempEl.OffsetParent;
         }

         return yPos;
     }

then use the position with:

 //now scroll to that element
 webBrowser1.Document.Window.ScrollTo(x, y);

done!


I like previous answers but iterating through parent objects twice is not very effective. Remember - you're working with COM/ActiveX here. This works much faster:

public Point GetOffset(HtmlElement el)
{
    //get element pos
    Point pos = new Point(el.OffsetRectangle.Left, el.OffsetRectangle.Top);

    //get the parents pos
    HtmlElement tempEl = el.OffsetParent;
    while (tempEl != null)
    {
        pos.X += tempEl.OffsetRectangle.Left;
        pos.Y += tempEl.OffsetRectangle.Top;
        tempEl = tempEl.OffsetParent;
    }

    return pos;
}

and then

var point = GetOffset(element);
var x = point.X;
var y = point.Y;


Thank you, it works like a charm. I had to rewrite it as VB, and just want to share the solution:

Function GetXOffSet(ByVal elem As HtmlElement) As Integer
    Dim xPos As Integer = elem.OffsetRectangle.Left
    Dim tElm As HtmlElement = elem.OffsetParent
    Dim trig As Boolean = False
    While Not trig
        Try
            xPos += tElm.OffsetRectangle.Left
            tElm = tElm.OffsetParent
        Catch ex As Exception
            trig = True
        End Try
    End While
    Return xPos
End Function

Function GetYOffSet(ByVal elem As HtmlElement) As Integer
    Dim yPos As Integer = elem.OffsetRectangle.Top
    Dim tElm As HtmlElement = elem.OffsetParent
    Dim trig As Boolean = False
    While Not trig
        Try
            yPos += tElm.OffsetRectangle.Top
            tElm = tElm.OffsetParent
        Catch ex As Exception
            trig = True
        End Try
    End While
    Return yPos
End Function


There is a direct way to get the coordinates. IHTMLElement2 has the method getBoundingClientRect that gives you the coordinates of the element.

IHTMLDocument3 doc = (IHTMLDocument3)this.webbrowser.Document;
IHTMLElement2 element = (IHTMLElement2)doc.getElementById(idElement);
IHTMLRect rect = element.getBoundingClientRect();

int x = rect.left;
int y= rect.top;


Just sharing a slightly different implementation based on my needs to get the absolute positioning rectangle:

public Rectangle GetAbsoluteRectangle(HtmlElement element) {
    //get initial rectangle
    Rectangle rect = element.OffsetRectangle;

    //update with all parents' positions
    HtmlElement currParent = element.OffsetParent;
    while (currParent != null) {
            rect.Offset(currParent.OffsetRectangle.Left, currParent.OffsetRectangle.Top);
            currParent = currParent.OffsetParent;
    }

    return rect;
}


Not sure why but offsetparent is not allways returned (case of IE11, map object) I had to add parentElement in the loop when parentOffset is not provided

    While parent IsNot Nothing
            y += parent.offsetTop
            x += parent.offsetLeft
            If  parent.offsetParent IsNot Nothing Then
                parent = parent.offsetParent  
            Else
                parent = parent.parentElement
            End If
    End While

And you need to add IE browser position, the menu space and borders ...


The cleanest way that works for me is the following:

HtmlElement elem = webBrowser.Document.GetElementById(idElement); IHTMLRect rect = ((IHTMLElement2) elem.DomElement).getBoundingClientRect(); // rect.top and rect.left represent absolute coordinates.

0

精彩评论

暂无评论...
验证码 换一张
取 消