Dear Dare,
I'm working on exactly the same problem as you since four weeks and i'm completely bald actually.
I tried a dozain of different solutions to get the user-selected (highlighted) html code, transform it by my own procedures and replace it inside the document. And now, I hate hate hate hate the Microsoft developpers who worked on IE Explorer. IE is probably the worst part of Windows in terms of liability and logic. Many functions are buggy and written with the 4th dimension's way of thincking. I'm not used to be critical about Microsoft but I'm badly training myself at this occasion.
Just as an example, when you try to get the html code matching with a selection using ANY of the IE functions, the code returned is not the "real" one. ie:
Suppose that the user has selected the words "
some words" in a sentence as "
some words of a sample text" included in a h1 tag. You expect to get something as
but you will get
(IE will "complete" the code before giving it to you).
So, when you want to transform this code and to reinsert it into your document, you will obtain something like
Code: Select all
<h1>some words</h1> of a sample text</h1>
After all that pain, I personally concluded that there is not any "elegant" way of doing that and that the only reliable one is to do approx what you suggest:
get the caret or selection position, get the inner html (<body>) into a string, parse the string to locate caret/selection position, and then insert the desired code, cut the original selection (if selection), clear the doc, rewrite the updated string, reposition caret/selection
I'm actually making a last attempt to paste the transformed code inside the document instead of
clear the doc, rewrite the updated string, reposition caret/selection
but I have not finished.
Here are two of my procedures (not well tested) to do that:
(those procedures use my version of the WebGadgetExtra library which you can download using the link at the beggining of this topic)
Code: Select all
Procedure.s PutMyMarkupsAndGetTheElementCode(WebGadget) ; by Zapman
TextRange.IHTMLTxtRange = GetTxtRange(WebGadget)
If TextRange
bstr.l = 0
If TextRange\get_text(@bstr) = #S_OK And bstr And PeekS(bstr,-1,#PB_Unicode)
SelectedText$ = PeekS(bstr,-1,#PB_Unicode)
SysFreeString_(bstr)
If TextRange\parentElement(@Element.IHTMLElement) = #S_OK And Element
bstr.l = 0
If Element\get_outerText(@bstr) = #S_OK And bstr And PeekS(bstr,-1,#PB_Unicode)
ElementText$ = PeekS(bstr,-1,#PB_Unicode)
SysFreeString_(bstr)
MarkupServices.IMarkupServices = GetIMarkupServices(WebGadget)
If MarkupServices
MarkupServices\CreateMarkupPointer (@MarkupPointer1.IMarkupPointer)
If MarkupPointer1
MarkupServices\CreateMarkupPointer (@MarkupPointer2.IMarkupPointer)
If MarkupPointer2
If Trim(SelectedText$) = Trim(ElementText$) ; Selection matchs with the whole Element content -> Include the tags into the selection.
MarkupPointer1\MoveAdjacentToElement(Element,#ELEM_ADJ_BeforeBegin)
MarkupPointer2\MoveAdjacentToElement(Element,#ELEM_ADJ_AfterEnd)
Else
MarkupServices\MovePointersToRange(TextRange,MarkupPointer1,MarkupPointer2)
EndIf
InsertedString1$ = "hereisthestartoftheoldcode"
bStr = StringToBStr (InsertedString1$)
MarkupServices\InsertText(bStr,Len(InsertedString1$),MarkupPointer1)
SysFreeString_(bStr)
InsertedString2$ = "hereistheendoftheoldcode"
bStr = StringToBStr (InsertedString2$)
MarkupServices\InsertText(bStr,Len(InsertedString2$),MarkupPointer2)
SysFreeString_(bStr)
MarkupPointer2\Release()
If Element\get_outerHTML(@bStr) = #S_OK And bStr
Result$ = ReadBSTR(bstr)
SysFreeString_(bStr)
If FindString(Result$,InsertedString1$,0)=0 Or FindString(Result$,InsertedString2$,0)=0 ; one of the markups has been inserted before the entry tag of after the ending tag
If Element\get_parentElement(@Parent.IHTMLElement) = #S_OK And Parent
Element\Release()
Element = Parent
If Element\get_outerHTML(@bStr) = #S_OK And bStr
Result$ = ReadBSTR(bstr)
SysFreeString_(bStr)
EndIf
Else
Result$ = ""
EndIf
EndIf
EndIf
EndIf
MarkupPointer1\Release()
EndIf
MarkupServices\Release()
EndIf
EndIf
Element\Release()
EndIf
EndIf
TextRange\Release()
EndIf
ProcedureReturn Result$
EndProcedure
;
Procedure RemoveMyMarkupsAndSelectTextInside(WebGadget) ; by Zapman
TextRange.IHTMLTxtRange = GetTxtRange(WebGadget)
If TextRange
MarkupServices.IMarkupServices = GetIMarkupServices(WebGadget)
If MarkupServices
If TextRange\parentElement(@Element.IHTMLElement) = #S_OK And Element
MarkupServices\CreateMarkupPointer (@MarkupPointerS1.IMarkupPointer)
If MarkupPointerS1
MarkupServices\CreateMarkupPointer (@MarkupPointerS2.IMarkupPointer)
If MarkupPointerS2
MarkupPointerS1\MoveAdjacentToElement(Element,#ELEM_ADJ_BeforeBegin) ; Extend TextRange to the whole Element content
MarkupPointerS2\MoveAdjacentToElement(Element,#ELEM_ADJ_AfterEnd)
MarkupServices\MoveRangeToPointers(MarkupPointerS1,MarkupPointerS2,TextRange)
bStr = StringToBStr ("hereisthestartoftheoldcode")
varOut.VARIANT\vt = #VT_BOOL
If TextRange\findText(PeekS(bstr, -1, #PB_Unicode),$7FFFFFFF,0,@varOut) = #S_OK ; look for the first markup
MarkupServices\MovePointersToRange(TextRange,MarkupPointerS1,MarkupPointerS2)
MarkupServices\Remove(MarkupPointerS1,MarkupPointerS2) ; remove my first markup
bStr = StringToBStr ("hereistheendoftheoldcode")
varOut.VARIANT\vt = #VT_BOOL
If TextRange\findText(PeekS(bstr, -1, #PB_Unicode),$7FFFFFFF,0,@varOut) = #S_OK ; look for the second markup
MarkupServices\CreateMarkupPointer (@MarkupPointerE1.IMarkupPointer)
If MarkupPointerE1
MarkupServices\CreateMarkupPointer (@MarkupPointerE2.IMarkupPointer)
If MarkupPointerE2
MarkupServices\MovePointersToRange(TextRange,MarkupPointerE1,MarkupPointerE2)
MarkupServices\Remove(MarkupPointerE1,MarkupPointerE2) ; remove my second markup
MarkupServices\MoveRangeToPointers(MarkupPointerS1,MarkupPointerE2,TextRange)
TextRange\select()
MarkupPointerE2\Release()
Result = 1
EndIf ; If MarkupPointerE2
MarkupPointerE1\Release()
EndIf ; If MarkupPointerE1
EndIf ; If TextRange\findText(PeekS(bstr, -1, #PB_Unicode),$7FFFFFFF,0,@varOut) = #S_OK
EndIf ; If TextRange\findText(PeekS(bstr, -1, #PB_Unicode),$7FFFFFFF,0,@varOut) = #S_OK
MarkupPointerS2\Release()
EndIf ; If MarkupPointerS2
MarkupPointerS1\Release()
EndIf ; If MarkupPointerS1
Element\Release()
EndIf ; If TextRange\parentElement(@Element.IHTMLElement) = #S_OK And Element
MarkupServices\Release()
EndIf ; If MarkupServices
TextRange\Release()
EndIf ; If TextRange
ProcedureReturn Result
EndProcedure
To use the PasteHTML command you must do something as:
Code: Select all
Procedure.s PutHTMLCodeAtCaretPos(WebGadget,HTMLCode$) ; by Zapman
WebGadget_Exec(WebGadget,#OLECMDID_DELETE,#OLECMDEXECOPT_DODEFAULT,0,0) ; this line is necessary because PasteHTML doesn't always erase completely the old content (that's one of the IE bugs)
TextRange.IHTMLTxtRange = GetTxtRange(WebGadget)
If TextRange
bstr = StringToBStr (HTMLCode$)
TextRange\PasteHTML(ReadBSTR(bstr))
SysFreeString_(bstr)
TextRange\Release()
EndIf
EndProcedure
Because of all the problems I got precedently, I'm not really confident with this PastHTML command. I'll test it.
Be strong, boy, the way is long!![/code]