I was wondering if its possible to get the absolute position of specific HTML element I have loaded in webbrowser control with C#.
I tried almost all of the options that
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;
}
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.
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 ...
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;
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!
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