Editable WebGadget library
-
- Enthusiast
- Posts: 115
- Joined: Wed Jun 02, 2004 10:17 pm
- Location: New Caledonia (South Pacific)
- Contact:
Editable WebGadget library
Thanks to Fr34k, I understood how the Interface of Internet Explorer works and how to use it through a WebGadget. I began to make a WYSIWYG Html Editor and created many procedure to rich this target.
You can download the open source resulting library at
http://www.rankspirit.com/downloads/wg_library.zip
This file includes about 60 procedures (with comments) to deal with the Internet Explorer Interface.
You can download the open source resulting library at
http://www.rankspirit.com/downloads/wg_library.zip
This file includes about 60 procedures (with comments) to deal with the Internet Explorer Interface.
Don't try - DO it !
-
- Enthusiast
- Posts: 115
- Joined: Wed Jun 02, 2004 10:17 pm
- Location: New Caledonia (South Pacific)
- Contact:
Here it is:
Code: Select all
XIncludeFile "WebGadgetExtras.pb"
;
ButtonWidth = 60 : ButtonHeight = 18 : ButtonLineHeight = ButtonHeight + 6
;
MyWindow=OpenWindow(#PB_Any,0,0,600,400,"WebgadgetLibrary demo",#PB_Window_ScreenCentered|#PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_TitleBar)
If CreateGadgetList(WindowID(MyWindow))=0:End:EndIf
;
WebGadget = WebGadget(#PB_Any,0,0,WindowWidth(MyWindow),WindowHeight(MyWindow)-ButtonLineHeight,"about:blank")
;
HTMLSample$ = "<html><head></head><body><div align="+Chr(34)+"center"+Chr(34)+"><p>WebGadget Library demo</p><p> </p><p>By Fr34k And Zapman</p></div></body></html>"
SetDocumentHTMLContent(WebGadget,HTMLSample$)
;
HPos = 5
ButtonFind = ButtonGadget(#PB_Any,HPos,WindowHeight(MyWindow)-ButtonHeight-2,ButtonWidth,ButtonHeight,"Find")
HPos + ButtonWidth +10
ComboContent = ComboBoxGadget(#PB_Any,HPos,WindowHeight(MyWindow)-ButtonHeight-4,100,100)
AddGadgetItem(ComboContent,-1,"Element 0 infos")
AddGadgetItem(ComboContent,-1,"Element 1 infos")
AddGadgetItem(ComboContent,-1,"Element 2 infos")
AddGadgetItem(ComboContent,-1,"Element 3 infos")
AddGadgetItem(ComboContent,-1,"Element 4 infos")
AddGadgetItem(ComboContent,-1,"Element 5 infos")
AddGadgetItem(ComboContent,-1,"Element 6 infos")
AddGadgetItem(ComboContent,-1,"Element 7 infos")
SetGadgetState(ComboContent,0)
HPos +102
ButtonDisplay = ButtonGadget(#PB_Any,HPos,WindowHeight(MyWindow)-ButtonHeight-2,ButtonWidth,ButtonHeight,">>Display")
HPos + ButtonWidth + 10
ButtonEdit = ButtonGadget(#PB_Any,HPos,WindowHeight(MyWindow)-ButtonHeight-2,80,ButtonHeight,"Edit mode")
HPos + 80 + 10
ButtonRankSpirit = ButtonGadget(#PB_Any,HPos,WindowHeight(MyWindow)-ButtonHeight-2,ButtonWidth,ButtonHeight,"RankSpirit")
HPos + ButtonWidth + 40
MouseText = TextGadget(#PB_Any,HPos,WindowHeight(MyWindow)-ButtonHeight,130,ButtonHeight,"Last clic was over...")
EditMode$ = "Off"
Repeat
;
EventID = WaitWindowEvent()
If EventID = #PB_Event_CloseWindow
Quit = 1
ElseIf EventID=#WM_SIZE
ResizeGadget(WebGadget,#PB_Ignore,#PB_Ignore,WindowWidth(MyWindow),WindowHeight(MyWindow)-ButtonLineHeight)
ResizeGadget(ButtonFind,#PB_Ignore,WindowHeight(MyWindow)-ButtonHeight-2,#PB_Ignore,#PB_Ignore)
ResizeGadget(ComboContent,#PB_Ignore,WindowHeight(MyWindow)-ButtonHeight-4,#PB_Ignore,#PB_Ignore)
ResizeGadget(ButtonDisplay,#PB_Ignore,WindowHeight(MyWindow)-ButtonHeight-2,#PB_Ignore,#PB_Ignore)
ResizeGadget(ButtonEdit,#PB_Ignore,WindowHeight(MyWindow)-ButtonHeight-2,#PB_Ignore,#PB_Ignore)
ResizeGadget(ButtonRankSpirit,#PB_Ignore,WindowHeight(MyWindow)-ButtonHeight-2,#PB_Ignore,#PB_Ignore)
ResizeGadget(MouseText,#PB_Ignore,WindowHeight(MyWindow)-ButtonHeight,#PB_Ignore,#PB_Ignore)
ElseIf EventID = #WM_LBUTTONDOWN
GetWindowRect_(GadgetID(WebGadget),re.RECT)
GetCursorPos_(pt.POINT)
;
If pt\y<re\bottom
pt\x - re\left
pt\y - re\top
x = pt\X
y = pt\y
GetElementInfosFromPoint(WebGadget,x,y,@Element.ElementInfo)
SetGadgetText(MouseText,"Last clic was over: "+Element.ElementInfo\tagname)
SetGadgetState(ComboContent,Element\Index)
EndIf
ElseIf EventID=#PB_Event_Gadget
If EventGadget() = ButtonFind
SearchString$ = InputRequester("Search","Enter the expression to search:","Zapman")
If SearchString$
FindInWebGadget(SearchString$,0,WebGadget)
EndIf
ElseIf EventGadget() = ButtonDisplay
Index = GetGadgetState(ComboContent)
If Index<0 : Index = 0 : EndIf
GetElementInfosFromIndex(WebGadget,Index,Element.ElementInfo)
tx$ = "TagPosition: "+Element\taglist+Chr(13)
tx$ + "posX: "+Str(Element\offsetTop)+Chr(13)
tx$ + "posY: "+Str(Element\offsetLeft)+Chr(13)+Chr(13)
tx$ + "Content: "+ Element\outerHTML
MessageRequester("Element 1 content",tx$,0)
ElseIf EventGadget() = ButtonEdit
If EditMode$ = "Off"
EditMode$ = "On"
SetGadgetText(ButtonEdit,"Browser Mode")
Else
EditMode$ = "Off"
SetGadgetText(ButtonEdit,"Edit Mode")
EndIf
SetWebGadgetEditable(WebGadget,EditMode$)
ElseIf EventGadget() = ButtonRankSpirit
SetGadgetText(WebGadget,"about:<body><h1>Loading...</h1></body>")
While WindowEvent() : Wend
SetGadgetText(WebGadget,"http://www.rankspirit.com")
SetWebGadgetEditable(WebGadget,EditMode$)
EndIf
EndIf
Until Quit
Don't try - DO it !
Hi zapman*,
Thanks again. This is really useful.
Edit:
This is weird. If I replace the HTMLSample$="html stuff" with
Then it runs only once in every (about) 5 times. The other times it just disappears. MessageRequesters show it doesn't even get as far as the structures in the "extras" file. (They don't pop up)
However if I don't do the read, or place something like:
immediately after the read (thus negating the efforts of the read) then it always works!
Any ideas? (the test file is about 2k in size.)
Edit again:
Using makes it work nearly every time.
Is there a way to know if a file operation is really completed?
Edit yet again:
Okay, this is not the place for this question, I'll take it to coding questions as I don't think it has anything to do with this (except incidentally).
Thanks again. This is really useful.
Edit:
This is weird. If I replace the HTMLSample$="html stuff" with
Code: Select all
HTMLSample$=""
ReadFile(2,"path\to\test.html")
While Not Eof(2)
HTMLSample$ + ReadString(2)
Wend
CloseFile(2)
However if I don't do the read, or place something like:
Code: Select all
HTMLSample$="<html><title>A</title><head></head><body>OK</body></html>"
Any ideas? (the test file is about 2k in size.)
Edit again:
Using
Code: Select all
FileBuffersSize(2,0)
Is there a way to know if a file operation is really completed?
Edit yet again:
Okay, this is not the place for this question, I'll take it to coding questions as I don't think it has anything to do with this (except incidentally).
Dare2 cut down to size
Hi zapman*,
Just remembered this thread was around so decided to be a pain and post a question for you here.
Do you know how to insert HTML at a given point in the document using this approach? That is, insert actual HTML at the caret position so that it shows as html and not htmldecoded text?
(Please say yes - oh - and please show how!)
Thanks!
Just remembered this thread was around so decided to be a pain and post a question for you here.
Do you know how to insert HTML at a given point in the document using this approach? That is, insert actual HTML at the caret position so that it shows as html and not htmldecoded text?
(Please say yes - oh - and please show how!)
Thanks!
Dare2 cut down to size
-
- Enthusiast
- Posts: 115
- Joined: Wed Jun 02, 2004 10:17 pm
- Location: New Caledonia (South Pacific)
- Contact:
Hi Dare
Using the example described in this topic, add a button and exec the following when you clic on this button:
by that way, the "<h1>Just to try</h1>" code is not interpreted but just past "as it" into the page.
Is it what you were looking at?
Using the example described in this topic, add a button and exec the following when you clic on this button:
Code: Select all
StringToPaste$ = "<h1>Just to try</h1>"
#OLECMDID_PASTE = 13
VarIn.variant\VT = #VT_BSTR
VarIn\bstrVal = StringToBStr (StringToPaste$)
WebGadget_Exec(WebGadget,#OLECMDID_PASTE,#OLECMDEXECOPT_DONTPROMPTUSER,@VarIn,@VarOut.variant)
SysFreeString_(VarIn\bstrVal)
Is it what you were looking at?
Don't try - DO it !
Hi zapman*,
Thanks for the response!
Mate, sorry for the confusing request.
I can paste/insert text, what I am looking to do is insert html so the the html is encoded and behaves like HTML. So inserting something like "<b>BOLD</b>" would produce BOLD.
I know things like Bold, Italic, Fonts, colours and etc can be set, images can be inserted, etc, etc, using #IDM_constants and am doing that. However there are cases where I need to be able to insert chunks of html code and have them wysiwyg-ed.
I cannot work out how to get the html in there and make it act like HTML! I am in danger of going bald trying to do this.
Perhaps I need to 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. Fiddly.
There must be a cleaner way. I just cannot find it.
If you have the answer, great! But if you have to spend time chasing it, please don't, I don't want to waste your time. Just hoping you have the answer at your fingertips.
Thanks for your help so far.
PS: I believe there is a command PasteHTML available via MSHTML.DLL which I assume would do the job, however I don't know how to access/use it.
Thanks for the response!
Mate, sorry for the confusing request.
I can paste/insert text, what I am looking to do is insert html so the the html is encoded and behaves like HTML. So inserting something like "<b>BOLD</b>" would produce BOLD.
I know things like Bold, Italic, Fonts, colours and etc can be set, images can be inserted, etc, etc, using #IDM_constants and am doing that. However there are cases where I need to be able to insert chunks of html code and have them wysiwyg-ed.
I cannot work out how to get the html in there and make it act like HTML! I am in danger of going bald trying to do this.

Perhaps I need to 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. Fiddly.
There must be a cleaner way. I just cannot find it.

If you have the answer, great! But if you have to spend time chasing it, please don't, I don't want to waste your time. Just hoping you have the answer at your fingertips.
Thanks for your help so far.
PS: I believe there is a command PasteHTML available via MSHTML.DLL which I assume would do the job, however I don't know how to access/use it.
Dare2 cut down to size
-
- Enthusiast
- Posts: 115
- Joined: Wed Jun 02, 2004 10:17 pm
- Location: New Caledonia (South Pacific)
- Contact:
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
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:
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)
To use the PasteHTML command you must do something as:
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]
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
Code: Select all
<h1>some words
Code: Select all
<h1>some words</h1>
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>
I'm actually making a last attempt to paste the transformed code inside the document instead ofget 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
but I have not finished.clear the doc, rewrite the updated string, reposition caret/selection
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
Be strong, boy, the way is long!![/code]
Don't try - DO it !
Hi zapman*,
lol, some good humour in your post! And as you're also struggling with this my 2 brain cells are feeling a little better about themselves.
Thanks for the code, I'll have a go with it.
I had a thought (dangerous thing to have happen). With my online wysiwyg code (dom, js) I can load another webpage, ctrl-A (select all), ctrl-c (copy), set the focus and insertion point on the wysiwyg and ctrl-P (paste). Inserts everything.
So ... I am going to try having a hidden 2nd webgadget, writing the insert stuff to that, copying to clipboard and then pasting to the main webgadget from the clipboard.
But all this tomorrow, currently have some other stuff to do.
Thanks for the help!
lol, some good humour in your post! And as you're also struggling with this my 2 brain cells are feeling a little better about themselves.
Thanks for the code, I'll have a go with it.
I had a thought (dangerous thing to have happen). With my online wysiwyg code (dom, js) I can load another webpage, ctrl-A (select all), ctrl-c (copy), set the focus and insertion point on the wysiwyg and ctrl-P (paste). Inserts everything.
So ... I am going to try having a hidden 2nd webgadget, writing the insert stuff to that, copying to clipboard and then pasting to the main webgadget from the clipboard.
But all this tomorrow, currently have some other stuff to do.
Thanks for the help!
Dare2 cut down to size
- Kwai chang caine
- Always Here
- Posts: 5494
- Joined: Sun Nov 05, 2006 11:42 pm
- Location: Lyon - France
Hello at all
What a very great code
That's exactely what i search for a long time ago.
Congratulation at the creator
But i have a problem.
This code don't work whith all internet page
I tested it whith "http://www.google.fr" and it not run
For example the function FindInWebGadget() work fine with http://www.purebasic.com and don't work with "http://www.google.fr".
Il somebody know why ? :roll:
Is it my fault ?
Thanks.
What a very great code

That's exactely what i search for a long time ago.

Congratulation at the creator

But i have a problem.
This code don't work whith all internet page

I tested it whith "http://www.google.fr" and it not run

For example the function FindInWebGadget() work fine with http://www.purebasic.com and don't work with "http://www.google.fr".
Il somebody know why ? :roll:
Is it my fault ?

Thanks.

Not a destination