Using internet explorer I would like to get the position where a person has clicked on text. An error of 3 to 4 characters is fine. The text is not editable and is usually in a span element.
I am aware I could set up a click event listener for the HTMLDocument however I do not always have the HTMLDocument object and thus may miss the event.
I have tried getting a IHTMLSelectionObject, then creating a text range with the IHTMLTxtRange, however when the web page is simply clicked as opposed to at least 1 character being selected then the IHTMLTxtRange has a parent of the HTMLBody and not of the element that was clicked.
The HTMLDocument.activeElement is also unreliable. In my tests it never actually returns the element clicked, it usually returns a major parent of the element somewhere up the tree.
Using MSHTML is there another way to achieve this?
I have also tried using the WIN API GetCursorPos however I do not know what to do with this position, I do not know how to convert this into the actual element.
EDIT: I also thought of an interesting idea. When I need to know the element that has the cursor, I set a mouseDown or click event on the whole document. Then fire my own click and catch the event. In the IHTMLEventObj of the event is a FromElement which I had hoped would tell me where the cursor was. It seems it is always nothing for mouseDown and click events. For me at least this object is only used in for example mouseover events.
The following is what I have when at least a character is selected.
Private Function GetHTMLSelection(ByVal aDoc As IHTMLDocument2, ByRef htmlText As String) As Integer
Dim sel As IHTMLSelectionObject = Nothing
Dim selectionRange As IHTMLTxtRange = Nothing
Dim rangeParent As IHTMLElement4 = Nothing
Dim duplicateRange As IHTMLTxtRange = Nothing
Dim i As Integer
Dim x As Integer
Dim found As Boolean
Try
'get a selection
sel = TryCast(aDoc.selection, IHTMLSelectionObject)
If sel Is Nothing Then
Return -1
End If
'the range of the selection.
selectionRange = TryCast(sel.createRange, IHTMLTxtRange)
If selectionRange Is Nothing Then
Return -1
End If
'the the parent element of the range.
rangeParent = TryCast(selectionRange.parentElement, IHTMLElement4)
'duplicate our range so we can manipulate it.
duplicateRange = TryCast(selectionRange.duplicate, IHTMLTxtRange)
'make the dulicate range the whole element text.
duplicateRange.moveToElementText(rangeParent)
'get the length of the whole text
i = duplicateRange.text.Length
For x = 1 To i
duplicateRange.moveStart("character", 1)
If duplicateRange.compareEndPoints("StartToStart", selectionRange) = 0 Then
found = True
Exit For
End If
Next
If found Then
Debug.Print("Position is: " + x.ToString)
htmlText = duplicateRange.text
Return x
Else
Return -1
End If
Catch ex As Exception
Return -1
Finally
End Try
End Function