optcl

snichols There are two common public (free or open source) Tcl COM packages: tcom and optcl. I recently had some memory errors showing up in Event Viewer in Windows with tcom, so I tried optcl instead. Does anyone have a preference to which one they like better? The syntax is very similar with both from what I can tell. It was not hard to port my tcom Tcl script to use optcl instead.

MPJ I usually use optcl since it allows a activex control to be packed in a tk window (or not). Also I like the tlview::viewtype to figure out some of the controls interface.

"Open Tcl is a Tcl extension to provide connectivity to the resident host's component model."

http://www.sys.uea.ac.uk/~fuzz/optcl/default.html [Unable to access this page 2009 July 31]

Farzad Pezeshkpour wrote and maintains it.

  • Link for Download and Home page is Back as of 4th April 2005. Just downloaded source here without problems
  • Link seems to be dead as of 31 March 2005 - although you can get a copy from TixTclKit or NewzPoint (I think). (Don't know whether those copies are complete, or not)
  • The last release on May 30, 2000 changed the license from GPL to BSD. It can be downloaded from here [L1 ].

DDG Again the link above is dead. I put the latest BSD-licensed binary and the sources to my homepage [L2 ]. I fixed the broken zip-file issue. Pat, as that are the original sources (3010) you might diff against them. If you did this, I can remove the link above that we did not end up with two branches. I suggest having a sourceforge project. Optcl is quite useful for me in many cases.

PT 13-Jun-2008: I also have source plus some patches. I was thinking about opening up a sourceforge or google code project to maintain optcl and tclcontrol. Any comment?

I notice that DDG's optcl zip archive is corrupted and cannot be unzipped. I've made my optcl source repository a publicy accessible git repository. See [L3 ] for the web view. If you click on the snapshot link it will provide a tar.gz for you or you can get git and clone your own copy. There are some patches applied in this but I'm not sure what exactly until I get an original source release to compare against. You should be able to clone the repository via: git://cvs.patthoyts.tk/optcl

There is also a binary [L4 ] and a source [L5 ] zip archive.


[Recommend Leslie Brooks' nice example [L6 ] and commentary ...]


An example:

    #
    # Open Word and read the template for the report.  (The template
    # contains Header and Footer macros that we will use.)
    #
    set word [optcl::new word.application]
    set filename [file join [pwd] "Chapter 5 template.doc"]
    set doc [$word -with documents open $filename]
    #
    # Set the header by running a Word Macro recorded in the
    # template file and passing it the parameters it needs 
    # (System Release, RTP version, and Test Step).
    #
    $word run header "$test_step" "$SR" "$RTP_Version"
    $word run footer "$Operator"    

The template for the header macro is

    Sub Header(TestStep As String, SR As String, RTP As String)
    '
    ' Header Macro
    ' Macro recorded 7/24/01 by Leslie Brooks
    ' Set the Test Step number, the System Release number, and the
    ' RTP version number in the report header.

    .


    .

    . 
    End Sub  

Michael Jacobson: Here is some code to display a Microsoft's Internet Explorer ActiveX component in a Tk frame with the IE's scroll bar.

MPJ (5/02) Changed to use ProgId from the registry instead of the CLSID. The CLSID is a string representation of a COM Globally Unique IDentifer (GUID for short). This should make it a little easier to understand instead of the ProgId numbers.

 package require optcl
 wm title . {WebBrowers in Tk with scroll}
 set htm [optcl::new -window .htm Shell.Explorer.2] ;# for MSIE ActiveX Control
 # set htm [optcl::new -window .htm Mozilla.Browser.1] ;# for Mozilla ActiveX Control
 .htm config -width 800 -height 600
 pack .htm -fill both -expand 1
 $htm navigate www.tcl.tk
 # to view the type information for the control
 pack [button .b  -text "View TypeLibrary for IE container" -command {
                        tlview::viewtype [ optcl::class $htm ]
        } ] -side bottom

Here is the code to do it without the IE's scroll bar. Notice the difference???

 package require optcl
 wm title . {MSIE in Tk without scroll}
 set htm [optcl::new -window .htm {https://www.tcl-lang.org}]
 .htm config -width 800 -height 600
 pack .htm -fill both -expand 1
 # to view the type information for the control
 pack [button .b  -text "View TypeLibrary for IE container" -command {
                        tlview::viewtype [ optcl::class $htm ]
        } ] -side bottom

Scott Gamon - If you have an entry widget and an optcl browser widget in the same window, the entry widget is disabled after you click in the browser window.

One solution for regaining focus from OpTcl hosted ActiveX controls is to use Ffidl.

Another solution is:

 bind all <Enter> {forceFocus %W}
 bind all <ButtonPress-1> {forceFocus %W}

MPJ A little bigger example is how to play a VCD with Microsoft's MediaPlayer using optcl.

 package require optcl
 wm title . {VCD Document in Tk}
 set vcd [optcl::new -start -window .vcd MediaPlayer.MediaPlayer.1]
 .vcd config -width 640 -height 480
 pack .vcd -fill both -expand 1
 # put location of VCD file here ... need to make much smarter
 $vcd : filename "E:/mpegav/music01.dat"
 $vcd Play
 # view the loaded activex component
 ## tlview::loadedlibs .tmp2
 #how long the file is
 ## clock format [expr int([clock scan 0]+ [$vcd : duration])] -format %T
 # current position in time
 ## clock format [expr int([clock scan 0]+ [$vcd : CurrentPosition])] -format %T

MPJ Display of the Wiki in a Tk frame is yet another example Michael provides:

 package require optcl
 optcl::new -window .htm {https://wiki.tcl-lang.org}
 .htm config -width 800 -height 600
 pack .htm

LES on Aug 03 2005: Cool. But why does it use Internet Explorer? My system is configured to use Firefox. I mean, all htm(l)? pages and URL links are opened with Firefox automatically. What part of the Windows system decides that this Tk frame should hold Internet Explorer instead of Firefox?


MPJ Display the Calendar control being integrated within a Tk widget. Also see the examples files that come with OpTcl to bind events.

 package require optcl
 optcl::new -window .cal MSCAL.Calendar.7
 .cal config -width 300 -height 300
 pack .cal

See also COM on! - a tiny web browser & WippleWobble - A Mini Web Browser (for Windows)


etdxc I put together some of the commands from other peoples postings (sorry for the duplication) and a bunch of stuff I managed to work out by using the Type Library utility.

Hope it helps someone.

*****************************************************************************

ALL

 package require optcl

to view the type information for the control

 pack [button .b  -text "View TypeLibrary for IE container" -command {
     tlview::viewtype [ optcl::class $htm ]
 } ] -side bottom

view the loaded libraries

 tlview::loadedlibs .tmp2

view the type hierarchy

 tlview::viewtype [optcl::class $doc]
 tlview::viewtype [optcl::class $htm]
 tlview::viewtype [optcl::class $cal]
 tlview::viewtype [optcl::class $vcd]

*****************************************************************************

Word Start word

 set word [optcl::new word.application] 

New Document

 set doc [$word -with documents add]

Opens a document

 set doc [$word -with documents open $filename] 

Make Word visible

 $word : visible 1

Make Word invisible

 $word : visible 0

Insert text with formatting

 $word -with selection.font : name "Courier New"
 $word -with selection.font : size 10.0
 $doc -with content : text "Text in Courier 10 point \r"  ;# \r Return ???

Change colour of selected text

 $word -with selection : start 0
 $word -with selection : end 5
 $word -with selection.font : color wdcolorblue
 $word -with selection.font : bold 1

 $word -with selection : end 50000          ;# Move to end of doc
 set end [$word -with selection : end]      ;# Get the size of the doc
 $word -with selection : start $end         ;# Move to end of doc
 $word -with selection.font : name "Courier New"
 $word -with selection.font : size 10.0
 $word -with selection.range : text "Text is 14 point Courier"

 $doc select       ;# Select the text start to end I think

Exit Word

 $word quit

Minmise, Maximise, Restore

 $word : Windowstate wdWindowStateMaximize
 $word : Windowstate wdWindowStateMinimize
 $word : Windowstate wdWindowStateNormal

Page Setup

 set pSetUp [$doc PageSetup]
 $pSetUp : LeftMargin 1.0    ;# sets left margin

Printing

 $doc PrintOut               ;# Prints strainght away''
  • Background
  • Append
  • Range
  • OutputFileName
  • From
  • To
  • Item
  • Copies
  • Pages
  • PageType
  • PrintToFile
  • Collate
  • ActivePrinterMacGX
  • ManualDuplexPrint
  • PrintZoomColumn
  • PrintZoomRow
  • PrintZoomPaperWidth
  • PrintZoomPaperHeight

Print Preview

 $word : PrintPreview 1

Print Options

 set pOtions [$word : options]         ;# print options
 $p : PrintProperties 1
 $p : PrintBackground 1
 $p : PrintDraft 1

dialogs

 set d [$word : Dialogs]
 set dia [$d Item wdDialogFilePrintSetup]
 $dia Execute
 $dia Show

Display the document in powerpoint

 $doc PresentIt

Embed/Display word in IE

 $doc WebPagePreview

Turn on form design toolbar

 $doc ToggleFormsDesign

Email document

 $doc SendMail
 # $doc SendMailer FileFormat Priority      ;# not implemented error

Fax document

 # $doc SendFax Address Subject     ;# Needs Microsoft Lacal Fax

Letter Wizard

 # $doc RunLetterWizard                  ;# untested

Repaginate the document

 # $doc Repaginate                       ;# untested

Remove the documents theme

 # $doc RemoveTheme                      ;# untested

Remove Numbers >?????

 # $doc RemoveNumbers                    ;# untested

Reload as

 # $doc ReloadAs Office.MsoEncoding      ;# untested

Reload

 # $doc Reload                           ;# untested

''Send to exchange folder'

 $doc Post    

Merge

 # $doc Merge filename                   ;# untested

Data Form ?? Header Record Delimiters

 $doc DataForm

Check Spelling

 $doc CheckSpelling

Check Grammar

 $doc CheckGrammar

Summarise

 $doc AutoSummarize

Activate

 $word Activate

Change the open file path

 $word ChangeFileOpenDirectory "C:/"

?????

 # $word CheckGrammar string               ;# untested
 # $word CheckSpelling lots of args
 # $word CleanString string string
 # $word DDE''cmds''

Activate the helptool (?)

 $word HelpTool

Get the CLSID code

 $word ProductCode

Resize window

 $word Resize $x $y              ;# state needs to be normal or maximised

Fax

 $word SendFax                   ;# runs registered fax software

Set Default theme

 # $word SetDefaultTheme  args   ;# untested

'' ShowMe ?????'

 $word ShowMe                    ;# Didn't seem to do anything

Run Word macro with parm

 $word run header "arg" "arg" "arg"
 $word run footer "arg"

SaveAs

 $doc saveas "filename" 6
 # where 6 = format
 #  0 (zero) Word document
 #  1 Document template
 #  2 Text only
 #  3 Text only with line breaks
 #  4 MS-DOS text
 #  5 MS-DOS text with line breaks
 #  6 Rich Text Format (RTF)

*****************************************************************************

IE

for MSIE ActiveX Control

 set htm [optcl::new -window .htm Shell.Explorer.2]
 .htm config -width 800 -height 600
 pack .htm

for Mozilla ActiveX Control

 set htm [optcl::new -window .htm Mozilla.Browser.1]
 .htm config -width 800 -height 600
 pack .htm

Open a web page with scroll bars

 $htm navigate www.tcl.tk

Without the IE's scroll bar.

 set htm [optcl::new -window .htm {https://www.tcl-lang.org}]

Get the URL of current webpage using IE

 set current_site [$htm : LocationURL]

stevel wanted to print without the header and footer. This page http://support.microsoft.com/kb/q236777/ seems to indicate that the MS anointed way is to use a registry hack

    set rkey {HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\PageSetup}
    set header [registry get $rkey header]
    set footer [registry get $rkey footer]
    registry set $rkey header ""
    registry set $rkey footer ""
    $IE ExecWB "OLECMDID_PRINTPREVIEW" "OLECMDEXECOPT_PROMPTUSER"
    registry set $rkey header $header
    registry set $rkey footer $footer

*****************************************************************************

Play a VCD with Microsoft's MediaPlayer

 set vcd [optcl::new -start -window .vcd MediaPlayer.MediaPlayer.1]
 .vcd config -width 640 -height 480
 pack .vcd -fill both -expand 1

put location of VCD file here ... need to make much smarter

 $vcd : filename "E:/mpegav/music01.dat"
 $vcd Play

how long the file is

 clock format [expr int([clock scan 0]+ [$vcd : duration])] -format %T

current position in time

 clock format [expr int([clock scan 0]+ [$vcd : CurrentPosition])] -format %T

***************************************************************************** Calendar Control

 optcl::new -window .cal MSCAL.Calendar.7
 .cal config -width 300 -height 300
 pack .cal

Yet another example:

    set ::htm [optcl::new -window $pw.f.html Shell.Explorer.2]
    puts "Currently visible in the browser is '[$htm : LocationURL]'."

*****************************************************************************

'''Javascript State Controls

 ########################## 
 # Setup UP
 package require optcl 
 set t [toplevel .ie] 
 wm title $t "my Prototype" 
 set htm [optcl::new -window $t.htm Shell.Explorer.2] 
 $t.htm config -width 800 -height 600 
 pack $t.htm -fill both -expand 1
 $htm navigate "c:/test/test2.htm"
 after 100 set end 1
 vwait end
 ########################## 
 # Traversing the DOM tree
 
 set a [$htm : document]
 set b [$a : body]
 set c [$b : innerHTML] # contents of <body> 
 
 set slot1 [string first X. $c]
 set slot2 [string first .X $c]
 
 set slot1 [expr $slot1 + 2]
 set slot2 [expr $slot2 - 1]
  
 set isReady [string range $c $slot1 $slot2]
 
 puts [string range $c $slot1 $slot2]
 
 set done 0
 
 while {$done == 0} { 
 if {[string compare $isReady "finished"] == 0} {set done 1}
 
 set c [$b : innerHTML]
 set slot1 [string first X. $c]
 set slot2 [string first .X $c]
 set slot1 [expr $slot1 + 2]
 set slot2 [expr $slot2 - 1]
 
 set isReady [string range $c $slot1 $slot2]
 puts [string range $c $slot1 $slot2]
 
 after 1000 set end 1
 vwait end
 
 } 
 
 puts "made it"
 
 [$htm -with Document : parentWindow] execScript {javascript:resetVar()}
 
 # Now play the next audio file
 [$htm -with Document : parentWindow] execScript {javascript:myPlayer.playAudio ('java_audio/p2.jar')}

Shadowbq: Interference with Mouse Control and Bindings

Finding that having multiple widgets and optcl IE windows open confuses the bind command. The focus is staying on the IE window even when shaded behind tabs etc...

comments?


[Documentation projects: how to install in a pure tclkit; relations of Application Class to dispatch to methods and properties; asynchronous programming; ...]


FM Plugin Shockwave Flash

set flash [optcl::new -start -window .flash ShockwaveFlash.ShockwaveFlash]
pack .flash -expand 1 -fill both
$flash GetVariable \$version ; # -> WIN 9,0,124,0 for me
# play movie file.swf
$flash : EmbedMovie true Movie "file.swf"
# Add a movie in an upper layer
$flash LoadMovie 2 "layer2.swf"
after 1000 {$flash stop}
# ...etc

Optcl incorporates a separate project, TBase [L7 ], which is a C++ header file that defines a collection of classes providing typesafe and easier access to Tcl types.

Examples:

TObjPtr p = "some string";
p = 3.145;
p = true;
p = 15

-

TObjPtr p = "34.14";
try {
        double d = p;
}
catch (char *err) {
...
}