 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
pokercurious
Joined: 16 Dec 2007 Posts: 47
|
Posted: Mon Mar 31, 2008 9:45 pm Post subject: Different approaches to loading html in browser control |
|
|
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 |
|
 |
UPS
Joined: 22 Mar 2008 Posts: 41
|
Posted: Mon Mar 31, 2008 10:22 pm Post subject: |
|
|
1 Second late? WHO CARES? What's so important about 1 second????  _________________ I deliver fast! |
|
| Back to top |
|
 |
pokercurious
Joined: 16 Dec 2007 Posts: 47
|
Posted: Mon Mar 31, 2008 10:42 pm Post subject: |
|
|
| Rs2BotMaker wrote: | 1 Second late? WHO CARES? What's so important about 1 second????  |
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 |
|
 |
garry
Joined: 19 Apr 2005 Posts: 1185 Location: switzerland
|
Posted: Wed Apr 02, 2008 2:14 pm Post subject: |
|
|
| thank you pokercurious, nice example how to add html to ahk |
|
| Back to top |
|
 |
pokercurious
Joined: 16 Dec 2007 Posts: 47
|
Posted: Sat May 24, 2008 6:49 am Post subject: |
|
|
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 |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 1397
|
Posted: Sun May 25, 2008 6:50 am Post subject: Re: Different approaches to loading html in browser control |
|
|
| 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 |
|
 |
pokercurious
Joined: 16 Dec 2007 Posts: 47
|
Posted: Sun May 25, 2008 8:09 am Post subject: Re: Different approaches to loading html in browser control |
|
|
| 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 |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 1397
|
Posted: Sun May 25, 2008 9:25 am Post subject: Re: Different approaches to loading html in browser control |
|
|
| 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 |
|
 |
pokercurious
Joined: 16 Dec 2007 Posts: 47
|
Posted: Mon May 26, 2008 12:43 am Post subject: |
|
|
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 |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 1397
|
Posted: Mon May 26, 2008 3:51 am Post subject: |
|
|
| 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 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 |
|
 |
pokercurious n-l-i Guest
|
Posted: Mon May 26, 2008 12:10 pm Post subject: |
|
|
| 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
|
Posted: Mon May 26, 2008 6:33 pm Post subject: RAMBLINGS OF AN IDIOT |
|
|
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 |
|
 |
pokercurious
Joined: 16 Dec 2007 Posts: 47
|
Posted: Tue May 27, 2008 9:48 am Post subject: |
|
|
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 |
|
 |
tank
Joined: 21 Dec 2007 Posts: 1033
|
Posted: Tue May 27, 2008 2:52 pm Post subject: |
|
|
| 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 |
|
 |
pokercurious
Joined: 16 Dec 2007 Posts: 47
|
Posted: Tue May 27, 2008 6:58 pm Post subject: |
|
|
| 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:
and
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 |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|