wm title . {COM on!} package require optcl # local setting on my box at home set home c:/html/index.htm option add *Button.pady 0 option add *Button.borderWidth 1 option add *Button.relief flat bind Button <Enter> {+ %W config -relief raised} bind Button <Leave> {+ %W config -relief flat} set htm [optcl::new -window .htm Shell.Explorer.2] .htm config -width 600 -height 400 frame .fr button .fr.h -text ^ -command {catch {$htm navigate [set url $home]}} button .fr.o -text ... -command {$htm navigate [set url [tk_getOpenFile]]} button .fr.b -text < -command {catch {$htm goBack}} button .fr.f -text > -command {catch {$htm goForward}} button .fr.p -text P -command { catch {$htm ExecWB OLECMDID_PRINT OLECMDEXECOPT_PROMPTUSER}} entry .fr.e -textvar url -width 80 bind .fr.e <Return> {$htm navigate $url} set url $home pack {*}[winfo children .fr] -side left -fill y pack .fr -fill x pack .htm -fill both -expand 1 catch {$htm navigate $url} bind . <Escape> {exec wish $argv0 &; exit} ;# useful in development
SO 2009-09-19: I appreciate Richard mentioning our conversation in the chatroom, and the little script I mailed him. I would be remiss, however, if I failed to point out that my little hack was based on a script provided by Michael Jacobson, on the optcl page. Also, I would love to see other examples of using optcl/tcom appear on the wiki. These are truly powerful tools for those of us who spend most of our programming time in the world of windows.
MPJ 2002-09-19: Note there is a little bug in Tk or optcl that does not allow the text box to grab the focus correctly. See solution for regaining focus from OpTcl hosted ActiveX control, comp.lang.tcl, 2002-03-01. I notice that your little app has this problem too. I mention it on the optcl page with this solution (using my other favorite dll ... ffidl). UPDATE I like the way GPS solved this on his WippleWobble - A Mini Web Browser (for Windows) page using forceFocus proc.
load ffidl05.dll ffidl::callout dll_SetFocus {int} int [ffidl::symbol user32.dll SetFocus] proc GrabFocus {args} {dll_SetFocus [winfo id .]} bind . <Button> +GrabFocusWe can also add the use of event bindings from the ActiveX componet to this interface. Here is a little code from NewzPoint to display the [MouseOver] urls in a status bar at the bottom.
proc linkchanged {id page} { global link htm if {$page eq {} || [string equal -nocase done $page]} { set link [$htm : LocationURL] } else { set link $page } } optcl::bind $htm StatusTextChange linkchanged label .sta -relief sunken -borderwidth 2 -anchor w -textvariable link pack .sta -fill x -expand 1Another item that is a must-have for a browser is security level (icon). Here is how to implement it with optcl.
optcl::bind $html SetSecureLockIcon security proc security {id secureid} { global securitylevel set securitylevel [lindex \ {Unsecure Mixed Unknown 40Bits 56Bits Fortezza 128Bits} $secureid] } # now put securitylevel in a status barFinally, a moving icon is usually implemeted to show that the browser is navigating to a link and it stops when the link is displayed. This can be accomplished by binding to the BeforeNavigate2 and NavigateComplete2 events. Also you can always check on the status of a page by calling the Busy method (boolean return value).
set pagestatus [$htm : Busy] ;# 1 is busy, 0 is displayed
Martin Lemburg 2002-09-20:I "clean" up the code, collected the suggestions and tips - here is the "new" code:
package require optcl; proc forceFocus {win} { catch {focus -force $win} ;# MPJ change } proc linkchanged {id page} { global link htm; if {($page eq {}) || [string equal -nocase done $page]} { set link [$htm : LocationURL]; } else { set link $page; } return } proc security {id secureid} { global securitylevel set securitylevel [lindex { Unsecure Mixed Unknown 40Bits 56Bits Fortezza 128Bits } $secureid] return } proc startLoading args { global stopLoading loadingTime set loadingTime 0.00 set stopLoading 0 after 250 incrLoadingTime return } proc incrLoadingTime {} { global stopLoading loadingTime set loadingTime [format {%.2lf} [expr {$loadingTime + 0.25}]] if {!$stopLoading} { after 250 incrLoadingTime } return } proc stopLoading {args} { global stopLoading set stopLoading 1 return } set home http://www.google.com wm title . {COM on!} option add *Button.pady 0 option add *Button.borderWidth 1 option add *Button.relief flat bind Button <Enter> {+ %W config -relief raised} bind Button <Leave> {+ %W config -relief flat} frame .fr button .fr.h -text ^ -command {catch {$htm navigate [set url $home]}} button .fr.o -text ... -command {$htm navigate [set url [tk_getOpenFile]]} button .fr.b -text < -command {catch {$htm goBack}} button .fr.f -text > -command {catch {$htm goForward}} button .fr.p -text P -command { catch {$htm ExecWB "OLECMDID_PRINT" "OLECMDEXECOPT_PROMPTUSER"}} entry .fr.e -textvar url -width 80 label .fr.l -textvar loadingTime -width 7 -relief sunken -borderwidth 2 pack {*}[winfo children .fr] -side left -fill none -expand 0 pack .fr.e -side left -fill x -expand 1 pack .fr.l -side right -fill none -expand 0 set htm [optcl::new -window .htm Shell.Explorer.2]; .htm config -width 600 -height 400; frame .sta label .sta.info -relief sunken -borderwidth 2 -anchor w -textvariable link label .sta.secu -relief sunken -borderwidth 2 -anchor w \ -textvariable securitylevel -width 10 pack .sta.info -side left -fill x -expand 1 pack .sta.secu -side right -fill none -expand 0 set url $home pack .fr -side top -fill x -expand 0 pack .htm -side top -fill both -expand 1 pack .sta -side bottom -fill x -expand 0 bind .fr.e <Return> {$htm navigate $url} # useful in development bind . <Escape> {exec wish $argv0 &; exit} # MPJ change bind all <Enter> {forceFocus %W} bind all <ButtonPress-1> {forceFocus %W} optcl::bind $htm StatusTextChange linkchanged catch {optcl::bind $htm SetSecureLockIcon security} optcl::bind $htm BeforeNavigate2 startLoading optcl::bind $htm NavigateComplete2 stopLoading catch {$htm navigate $url};
Michael Jacobson: I updated the above so it does not need ffidl anymore. Give credit to GPS for this trick. Also if someone wants to try this code out in a Starkit format then just download this file http://mywebpages.comcast.net/jakeforce/COMon!.kit (92kb) and run with with TclKit. (Note: that it includes the optcl extension so all you need are the Tclkit executable and the COMon! Starkit)VL 2003-06-11: Trying to run the starkit on my w2k machine I get an error. I'll try to hunt it down when I have some time but if anyone know the problem help is appreciated?
event not found: SetSecureLockIconMPJ: There are different versions of the IE COM object depending on which version of windows you are using. Some do not have the SetSecureLockIcon event. Therefore I just put a catch around this line are repacked the starkit. Please download and try it again. VL: works like a charm!VL 2003-06-11: Now if I could only add the local html-file I want to view as a commandline argument this would be perfect before I get my table-viewer stuff finished?MPJ: Per you request I updated my starkit to take the 1st argument as the new home page. So you can do this...
tclkit COMon!.kit www.yahoo.comAnd yahoo will be the new home page and start to load. Please download and try it again.VL: Thanks!Here is a Starkit version where I changed the homepage to be served locally using the code from the Comic Server page ... http://mywebpages.comcast.net/jakeforce/COMon!ics.kit (96kb). If you want to see the code just unwrap it "tclkit sdx.kit unwrap COMon!ics.kit".
Michael Jacobson 2002-12-13: I just added a print button to the examples after noticing RS' remarks that it was not supported (it is but you need to use the OLE interface to the WebBrowser component). Below is how you can also do a CUT, COPY and PASTE button too.
button .fr.pa -text PA -command { catch {$htm ExecWB OLECMDID_PASTE OLECMDEXECOPT_DODEFAULT}} button .fr.co -text CO -command { catch {$htm ExecWB OLECMDID_COPY OLECMDEXECOPT_DODEFAULT}} button .fr.cu -text CU -command { catch {$htm ExecWB OLECMDID_CUT OLECMDEXECOPT_DODEFAULT}}In fact, the cut and paste are pretty interesting to have available all the time (MSIE allows it only for text fields).