AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Different approaches to loading html in browser control
Goto page 1, 2  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
pokercurious



Joined: 16 Dec 2007
Posts: 47

PostPosted: Mon Mar 31, 2008 9:45 pm    Post subject: Different approaches to loading html in browser control Reply with quote

I've been playing around with the cwebpage DLL, experimenting with using browser controls - for an application I'm working on, I'd like to change the contents of the control based on a selection from a listbox. The html is not from a url, but loaded from memory.

One thing I've noticed is that there is about a 1-second delay before it displays the html. Below is sample code that works (pieces liberally borrowed from code pasted by the user garry), but on the weird delay (The code needs the cwebpage.dll to be in the same directory - download it here).

Is there any way to speed the process up so it loads faster?

UPDATE/EDIT: So it turns out that the lbbrowse3.dll (download here), which is also used in IE4AHK.ahk, was what I needed - it took care of the speed issues and, apparently, the issue of IE.ahk (the other alternative) with respect to handling longer html strings in memory (see this thread). The code also ends up being a little cleaner (insofar as what I need it for) - the lbbrowse3.dll example is shown below the cwebpage one. I struggled with this for a while - maybe this will help somebody like me who doesn't really know what he/she is doing.

Best,
pokercurious

Code:

; Using cwebpage.dll
; Some test HTML
html1 = <body style="background-color:red; color:yellow">Hello!</body>
html2 = <body style="background-color:black; color:white">Bienvenidos!</body>
html3 = <body style="background-color:orange; color:blue">Guten Tag!</body>
html4 = <body style="background-color:brown; color:yellow">Aloha!</body>
html5 = <body style="background-color:green; color:black">Konichiwa!</body>

; Load the cwebpage DLL
cwebpageHandle := DllCall("LoadLibrary", "str", "cwebpage.dll")

; Create some GUI
Gui,1: Add, ListBox, x10 y10 w110 h100 vhtmlvar ghtmlchange, 1||2|3|4|5
Gui,1: Show, x150 y130 h115 w330, cwebpage speed tester
WinGet, mainGuiHandle, ID, A

; Second GUI for the browser control
Gui,2: +ToolWindow -Caption
Gui,2: Show, w190 h95
WinGet, browserGuiHandle1, ID, A
Gui,2: +LastFound
DllCall("SetParent", "uint", WinExist(), "uint", mainGuiHandle)
DLLCall("cwebpage\EmbedBrowserObject", "uint", browserGuiHandle1)
WinMove, ahk_id %browserGuiHandle1%, , 130, 10

; Get the party started
GoSub, htmlchange
OnExit, Cleanup
Return

; DLLCall that sets the browser control
htmlchange:
  Gui, submit, nohide
  DLLCall("cwebpage\DisplayHTMLStr"
        , "uint"  , browserGuiHandle1
        , "str"   , html%htmlvar%)
return

cleanup:
GuiClose:
Gui1Close:
Gui2Close:
  DLLCall("cwebpage\UnEmbedBrowserObject", "uint", browserGuiHandle1)
  DllCall("FreeLibrary", "uint", cwebpageHandle)
ExitApp


Code:

; Using lbbrowse3.dll
; Some test HTML
html1 = <body style="background-color:red; color:yellow">Hello!</body>
html2 = <body style="background-color:black; color:white">Bienvenidos!</body>
html3 = <body style="background-color:orange; color:blue">Guten Tag!</body>
html4 = <body style="background-color:brown; color:yellow">Aloha!</body>
html5 = <body style="background-color:green; color:black">Konichiwa!</body>

; Load the lbbrowse3 DLL
lbbHandle := DllCall("LoadLibrary", "str", "lbbrowse3.dll")

; Create some GUI
Gui, Add, ListBox, x10 y10 w110 h100 vhtmlvar ghtmlchange, 1||2|3|4|5
Gui, Show, x150 y130 h115 w330, lbbbrowse3 speed tester
WinGet, mainGuiHandle, ID, A

DLLCall("lbbrowse3\CreateBrowser"
        , "uint", mainGuiHandle
        , "Int", "130"
        , "Int", "10"
        , "Int", "190"
        , "Int", "95"
        , "Str", "about:blank")
DllCall("lbbrowse3\ShowStatusbar"
        , "int", 0)

; Get the party started
GoSub, htmlchange
OnExit, Cleanup
Return

; DLLCall that sets the browser control
htmlchange:
  Gui, submit, nohide
  DllCall("lbbrowse3\BrowserString", "str", html%htmlvar%)
return

cleanup:
GuiClose:
  Gui, Destroy
  DllCall("lbbrowse3\DestroyBrowser")
  DllCall("FreeLibrary", "UInt", lbbHandle)
ExitApp


Last edited by pokercurious on Sat May 24, 2008 6:51 am; edited 4 times in total
Back to top
View user's profile Send private message
UPS



Joined: 22 Mar 2008
Posts: 41

PostPosted: Mon Mar 31, 2008 10:22 pm    Post subject: Reply with quote

1 Second late? WHO CARES? What's so important about 1 second???? Shocked
_________________
I deliver fast!
Back to top
View user's profile Send private message
pokercurious



Joined: 16 Dec 2007
Posts: 47

PostPosted: Mon Mar 31, 2008 10:42 pm    Post subject: Reply with quote

Rs2BotMaker wrote:
1 Second late? WHO CARES? What's so important about 1 second???? Shocked


Well, try running the sample code and see - it feels really slow.

Secondly, (not that I'm a programmer by any stretch of the imagination - more of an interested hobbyist) programmers tend to worry about things like optimization - 1 second can be kind of a big deal.

Thirdly, this is the "Ask for Help" forum, and that's what I did. If you have any information about how to improve the performance of the browser control, I would appreciate your sharing it.

Best,
pokercurious
Back to top
View user's profile Send private message
garry



Joined: 19 Apr 2005
Posts: 1185
Location: switzerland

PostPosted: Wed Apr 02, 2008 2:14 pm    Post subject: Reply with quote

thank you pokercurious, nice example how to add html to ahk
Back to top
View user's profile Send private message
pokercurious



Joined: 16 Dec 2007
Posts: 47

PostPosted: Sat May 24, 2008 6:49 am    Post subject: Reply with quote

I've been playing around, trying to figure out how IE.ahk really works (so that I don't have to ship around the the lbbrowse.dll with my scripts).

I've finally gotten some usage down, and have translated the script from my original post into one that uses IE.ahk. I had to actually change things around a bit and do some DOM manipulation, but that wasn't really that bad a thing to learn anyway.

I initially switched to using the lbbrowse because of the difficulty I had with getting IE.ahk to load html (see Lexikos' post here).

I used Lexikos' document.write technique, but had to do some DOM manipulation because document.write only appends text, and there doesn't seem to be a good way (that I know of) to clear the html before writing again.

Anyway, here it is (you'll need IE.ahk and EZ.ahk):

Code:
#SingleInstance force

; Needs IE.ahk and EZ.ahk - uncomment lines below if not in standard library
;#Include IE.ahk ; - http://www.autohotkey.com/forum/topic19225.html
;#Inlucde EZ.ahk ; - http://www.autohotkey.com/forum/topic26402.html

basehtml =
(
<html>
  <body>
    <div id="htmlhere"></div>
  </body>
</html>
)

style1 = background-color:red; color:yellow;
html1 = Hello!
style2 = background-color:black; color:white;
html2 = Bienvenidos!
style3 = background-color:orange; color:blue;
html3 = Guten Tag!
style4 = background-color:brown; color:yellow;
html4 = Aloha!
style5 = background-color:green; color:black;
html5 = Konichiwa!

IE_Init()
COM_Init()

; Create the GUI
Gui, Add, ListBox, x10 y10 w110 h100 vindex ghtmlchange, 1||2|3|4|5
Gui, Show, x150 y130 h115 w330, IE control speed tester
WinGet, mgh, ID, A

; Create the browser control
pwb := IE_Add(mgh, 130, 10, 190, 85)

; Load about:blank to initialize MSHTML.
IE_LoadURL(pwb, "about:blank")

; Create the document object and fill it with basehtml
#_document := IE_Document(pwb)
ez_invoke("document.write", basehtml)

GoSub, htmlchange
Return

htmlchange:
  Gui, submit, nohide
   
   ; Set the css style
   ez_invoke("document.body.style.cssText=", style%index%)

   ; Set the html
   #_htmlhere := ez_invoke("document.getElementById", "htmlhere")
   ez_invoke("htmlhere.innerHTML=", html%index%)   
return

GuiClose:
Gui, Destroy
COM_Release(pwb)
IE_Term()
ExitApp
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 1397

PostPosted: Sun May 25, 2008 6:50 am    Post subject: Re: Different approaches to loading html in browser control Reply with quote

pokercurious wrote:
UPDATE/EDIT: So it turns out that the lbbrowse3.dll (download here), which is also used in IE4AHK.ahk, was what I needed - it took care of the speed issues and, apparently, the issue of IE.ahk (the other alternative) with respect to handling longer html strings in memory (see this thread). The code also ends up being a little cleaner (insofar as what I need it for) - the lbbrowse3.dll example is shown below the cwebpage one. I struggled with this for a while - maybe this will help somebody like me who doesn't really know what he/she is doing.

There is one more possibility, using COM_AtlAxCreateControl() or COM_AtlAxCreateContainer():
Code:
pdoc := COM_AtlAxCreateControl(hGui, "MSHTML:" . Your_Html_Text)
or
Code:
haxw := COM_AtlAxCreateContainer(hGui, l, t, w, h, "MSHTML:" . Your_Html_Text)
pdoc := COM_AtlAxGetControl(haxw)
Back to top
View user's profile Send private message
pokercurious



Joined: 16 Dec 2007
Posts: 47

PostPosted: Sun May 25, 2008 8:09 am    Post subject: Re: Different approaches to loading html in browser control Reply with quote

Sean wrote:
There is one more possibility, using COM_AtlAxCreateControl() or COM_AtlAxCreateContainer():
Code:
pdoc := COM_AtlAxCreateControl(hGui, "MSHTML:" . Your_Html_Text)
or
Code:
haxw := COM_AtlAxCreateContainer(hGui, l, t, w, h, "MSHTML:" . Your_Html_Text)
pdoc := COM_AtlAxGetControl(haxw)


What is "MSHTML:" . html_string and where can I read about it.

I'm trying to figure this stuff out but have a long way to go, tbh.

How would I recreate the the lbbrowse script from the original post with these techniques? For instance, how would I change the html string completely like in that script? Also, when I create an html control with COM_AtlAXCreateContainer with this html: "<body style="background-color:red; color:yellow">Hello!</body>" the styling doesn't come through. I'm guessing that's because whatever the mshtml function is doing is not rewriting the entire html object, but just sticking text in a node somewhere.

I'm willing to read and learn, I just need a little help getting pointed in the right direction.
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 1397

PostPosted: Sun May 25, 2008 9:25 am    Post subject: Re: Different approaches to loading html in browser control Reply with quote

pokercurious wrote:
What is "MSHTML:" . html_string and where can I read about it.
Here is a link to AtlAxCreateControl in MSDN:
http://msdn.microsoft.com/en-us/library/da181h29.aspx

AtlAxCreateContainer is really a wrapper of CreateWindowEx for AtlAxWin and then apply AtlAxCreateControl to the just created AtlAxWin.

Quote:
How would I recreate the the lbbrowse script from the original post with these techniques? For instance, how would I change the html string completely like in that script? Also, when I create an html control with COM_AtlAXCreateContainer with this html: "<body style="background-color:red; color:yellow">Hello!</body>" the styling doesn't come through. I'm guessing that's because whatever the mshtml function is doing is not rewriting the entire html object, but just sticking text in a node somewhere.

I always thought
Code:
pdoc := COM_AtlAxCreateControl(hGui, "MSHTML:" . Your_Html_Text)
is equivalent to
Code:
pdoc := COM_AtlAxCreateControl(hGui, "htmlfile")
COM_Invoke(pdoc, "write", Your_Html_Text)
COM_Invoke(pdoc, "close")
but looks like not. It seems to care only for text streams. Sorry for that.

BTW, IHTMLDocument2 currently does not support clear method which does what you're after. So, always invoke close after each write:
Code:
COM_Invoke(pdoc, "write", Your_Html_Text_1)
COM_Invoke(pdoc, "close")
Sleep 3000
COM_Invoke(pdoc, "write", Your_Html_Text_2)
COM_Invoke(pdoc, "close")
Back to top
View user's profile Send private message
pokercurious



Joined: 16 Dec 2007
Posts: 47

PostPosted: Mon May 26, 2008 12:43 am    Post subject: Reply with quote

So, with your help, I've translated the test script to just use the COM.ahk functions (code below). Using the "close" method after "write" works like a charm

However, if I call COM_Release or COM_AtlAxWinTerm on my way out of the script, I get an error message saying AHK has stopped working.

If I instead comment those lines out, everything seems to work fine. Is this a problem - I thought one had to be careful with memory management with COM stuff.

Btw, thanks for your patience sean - I appreciate your responses.


Code:
#SingleInstance force

html1 = <body style="background-color:red; color:yellow">Hello!</body>
html2 = <body style="background-color:black; color:white">Bienvenidos!</body>
html3 = <body style="background-color:orange; color:blue">Guten Tag!</body>
html4 = <body style="background-color:brown; color:yellow">Aloha!</body>
html5 = <body style="background-color:green; color:black">Konichiwa!</body>

; Create the GUI
Gui, Add, ListBox, x10 y10 w110 h100 vindex ghtmlchange, 1||2|3|4|5
Gui, Show, h115 w330, Learning from sean...
WinGet, mgh, ID, A

; Create the browser control
COM_AtlAxWinInit()
haxw := COM_AtlAxCreateContainer(mgh, 130, 10, 190, 95, "MSHTML:")
pdoc := COM_AtlAxGetControl(haxw)

; Get the party started
GoSub, htmlchange
OnExit, Cleanup
Return

; Set the HTML
htmlchange:
   Gui, submit, nohide
   COM_Invoke(pdoc, "write", html%index%)
   COM_Invoke(pdoc, "close")
return

cleanup:
GuiClose:
   ;COM_Release(pdoc)
   ;COM_AtlAxWinTerm()
ExitApp
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 1397

PostPosted: Mon May 26, 2008 3:51 am    Post subject: Reply with quote

pokercurious wrote:
However, if I call COM_Release or COM_AtlAxWinTerm on my way out of the script, I get an error message saying AHK has stopped working.
There had been a related post by corrupt, but I failed to locate it for now. That was the reason to introduce Gui, Destroy. However, I think the real cause in this case is
Code:
OnExit, Cleanup
AHK executes the cleanup routine two times, assuming you're exiting the script by closing the Gui window.

The safest way to do cleanup may be this:
Code:
Cleanup:
GuiClose:
   OnExit
   COM_Release(pdoc)
   Gui, Destroy
   COM_AtlAxWinTerm()
ExitApp
Back to top
View user's profile Send private message
pokercurious n-l-i
Guest





PostPosted: Mon May 26, 2008 12:10 pm    Post subject: Reply with quote

Sean wrote:
The safest way to do cleanup may be this:
Code:
Cleanup:
GuiClose:
   OnExit
   COM_Release(pdoc)
   Gui, Destroy
   COM_AtlAxWinTerm()
ExitApp


Thanks! That works perfectly, and you helped me understand exactly what it is that OnExit does.

Once again, many thanks. =)
Back to top
tank



Joined: 21 Dec 2007
Posts: 1033

PostPosted: Mon May 26, 2008 6:33 pm    Post subject: RAMBLINGS OF AN IDIOT Reply with quote

Sorry i just noticed this line
If i were going to open a gui window and write to it


Code:

COM_Init()
COM_AtlAxWinInit()
Gui, +LastFound +Resize
Gui, Show, w800 h600 Center, WebBrowser
hWnd := WinExist()
CLSID_WebBrowser := "{8856F961-340A-11D0-A96B-00C04FD705A2}"
IID_IWebBrowser2 := "{D30C1661-CDAF-11D0-8A3E-00C04FC9E26E}"
pwb := COM_CreateObject(CLSID_WebBrowser, IID_IWebBrowser2)
COM_AtlAxAttachControl(pwb, hWnd)
COM_Invoke(pwb, "Navigate","http://google.com")
Loop
if rdy:=COM_Invoke(pwb, "ReadyState")=4
break
COM_Invoke(pwb, "Navigate","http://yahoo.com")
Loop
if rdy:=COM_Invoke(pwb, "ReadyState")=4
break
         doc:=COM_Invoke(pwb, "Document")
         parentWindow:=COM_Invoke(doc, "parentWindow")

myhtml=
(
document.write("some html here");
)
COM_Invoke(parentWindow, "execScript",myhtml) ; executes the write as javascript
COM_Invoke(doc, "write",myhtml);this works just like the javascript execution above but is shorter and may depending on your nheeds give you what you need
COM_AtlAxWinTerm(),COM_Term()


Looks like this is already resolved but just sharing any how
_________________
Read this
Com
Automate IE7 with Tabs
Back to top
View user's profile Send private message
pokercurious



Joined: 16 Dec 2007
Posts: 47

PostPosted: Tue May 27, 2008 9:48 am    Post subject: Reply with quote

tank, can your method be used to put a browser control in a specific part of a gui?

Because this:

Code:
haxw := COM_AtlAxCreateContainer(mgh, 130, 10, 190, 95, "MSHTML:")
pdoc := COM_AtlAxGetControl(haxw)


doesn't give me a vertical scrollbar, whereas this:

Code:
CLSID_WebBrowser := "{8856F961-340A-11D0-A96B-00C04FD705A2}"
IID_IWebBrowser2 := "{D30C1661-CDAF-11D0-8A3E-00C04FC9E26E}"
pwb := COM_CreateObject(CLSID_WebBrowser, IID_IWebBrowser2)
COM_AtlAxAttachControl(pwb, hWnd)


does, although if I can't position the browser control within the gui, it's not of much use to me.

Hm, it just occurred to me that I could just create a new gui and use setparent to accomplish the same thing.

In any case, if there is a good way (other than just to create a new gui), please let me know.
Back to top
View user's profile Send private message
tank



Joined: 21 Dec 2007
Posts: 1033

PostPosted: Tue May 27, 2008 2:52 pm    Post subject: Reply with quote

pokercurious wrote:

although if I can't position the browser control within the gui, it's not of much use to me.

True i have found this only gives you the one control in a set position the size of the gui window
Code:

CLSID_WebBrowser := "{8856F961-340A-11D0-A96B-00C04FD705A2}"
IID_IWebBrowser2 := "{D30C1661-CDAF-11D0-8A3E-00C04FC9E26E}"
pwb := COM_CreateObject(CLSID_WebBrowser, IID_IWebBrowser2)
COM_AtlAxAttachControl(pwb, hWnd)

Sean had written In the IEcontrol.ahk script a function for this taken out of that and converted for use with the come library would be like this
Code:

COM_AtlAxWinInit()
pwb:=COM_AtlAxGetControl(COM_AtlAxCreateContainer(hWnd, x, y, w, h, "Shell.Explorer") ) ; x and y are the topleft most coordinates w and h are width and hieght
COM_AtlAxWinTerm()

http://www.autohotkey.com/forum/viewtopic.php?t=19225&postdays=0&postorder=asc&start=135
there are alot of techniches in there discussed However, It refers to functions that are wrappers for com library. unless your interested in loosing the IE.ahk and learing which com functions are actually used just use both files
ok so here is my previous post using the above instead
Code:


COM_Init()
COM_AtlAxWinInit()
Gui, +LastFound +Resize
Gui, Show, w800 h600 Center, WebBrowser
COM_AtlAxWinInit()
pwb:=COM_AtlAxGetControl(COM_AtlAxCreateContainer(WinExist(),0, 0, 400, 600, "Shell.Explorer") )

pwb2:=COM_AtlAxGetControl(COM_AtlAxCreateContainer(WinExist(), 400, 0, 400, 600, "Shell.Explorer") )


COM_Invoke(pwb, "Navigate","http://google.com")
COM_Invoke(pwb2, "Navigate","http://yahoo.com")
Loop
if rdy:=COM_Invoke(pwb, "ReadyState")=4
break
Loop
if rdy:=COM_Invoke(pwb2, "ReadyState")=4
break
         doc:=COM_Invoke(pwb2, "Document")
         parentWindow:=COM_Invoke(doc, "parentWindow")

myhtml=
(
document.write("some html here");
)
COM_Invoke(parentWindow, "execScript",myhtml) ; executes the write as javascript
COM_Invoke(doc, "write",myhtml) ;this works just like the javascript execution above but is shorter and may depending on your nheeds give you what you need
COM_AtlAxWinTerm()

COM_Term()

_________________
Read this
Com
Automate IE7 with Tabs
Back to top
View user's profile Send private message
pokercurious



Joined: 16 Dec 2007
Posts: 47

PostPosted: Tue May 27, 2008 6:58 pm    Post subject: Reply with quote

tank wrote:
http://www.autohotkey.com/forum/viewtopic.php?t=19225&postdays=0&postorder=asc&start=135
there are alot of techniches in there discussed However, It refers to functions that are wrappers for com library. unless your interested in loosing the IE.ahk and learing which com functions are actually used just use both files


That's what I was initially doing. I think I'd rather move away and learn the COM functions.

And I was actually trying something very similar to the code you just posted, but I was trying to gain access to the document object before navigating to anything, turns out navigating somewhere is required to create the document object?

So this works beatifully:

Code:
#SingleInstance force

html1 = <body style="background-color:red; color:yellow">Hello!</body>
html2 = <body style="background-color:black; color:white">Bienvenidos!</body>
html3 = <body style="background-color:orange; color:blue">Guten Tag!</body>
html4 = <body style="background-color:brown; color:yellow">Aloha!</body>
html5 = <body style="background-color:green; color:black">Konichiwa!</body>

; Create the GUI
Gui, +LastFound
Gui, Add, ListBox, x10 y10 w100 h100 vindex ghtmlchange, 1||2|3|4|5
Gui, Show, h120 w330, Learning from sean (and tank)...
mgh := WinExist()

COM_AtlAxWinInit()
pwb := COM_AtlAxGetControl(COM_AtlAxCreateContainer(mgh, 120, 10, 200, 100, "Shell.Explorer"))
COM_Invoke(pwb, "Navigate","about:blank")
pdoc := COM_Invoke(pwb, "Document")

GoSub, htmlchange
return

; Set the HTML
htmlchange:
   Gui, submit, nohide
   COM_Invoke(pdoc, "write", html%index%)
   COM_Invoke(pdoc, "close")
return


GuiClose:
   COM_Release(pdoc)
   COM_Release(pwb)
   Gui, Destroy
   COM_AtlAxWinTerm()
ExitApp


One quick question about your use of:

Code:
COM_Init()

and
Code:
COM_Term()


From looking at COM.ahk, it would appear that COM_AtlAxWinInit() and COM_AtlAxWinTerm() make those redundant. Is there a reason you've included those?

And am I incorrect when I use:
Code:
COM_Release(pdoc)
COM_Release(pwb)


I was under the impression that releasing COM objects was required, though I'm not entirely sure how it works.

Finally, and this may be my most important question: where do you learn about the types of things that can be activeX controls? For example, how do you go about learning that you can use "Shell.Explorer" there?

I can't find it in the msdn reference under createwindowex or the info about window classes.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group