Version 0 of ddeexec

Updated 2003-05-20 22:38:43

The windows shell uses the ddeexec registry key to try and open file type using a running dde service. You can specify both application and topic and the command (in dde parlance - the item) to be called.

The following is a sample application that runs a dde server and associates with files with a .z_t extension. You can open a file in this application by running either 'wish dde-edit.tcl <filename>' or once you have run 'wish dde-edit.tcl -install' to setup the file association - you can just do 'start xyzzy.z_t' and the Windows Shell will open the file in your tcl app for you.


 # dde-edit.tcl - Copyright (C) 2003 Pat Thoyts <[email protected]>
 #
 # Illustrate launching tcl applications via dde. This code requires a DDE
 # package that implements TIP 120.
 #
 # $Id: 8940,v 1.1 2003-05-21 08:01:36 jcw Exp $

 load debug/tcldde12g.dll Dde
 #package require dde 1.2.4

 namespace eval ::DdeEdit {
     variable uid
     if {![info exists uid]} {set uid 0}
     variable dialogs
 }

 # -------------------------------------------------------------------------
 # Description:
 #  Begin the dde service.
 #
 proc ::DdeEdit::DdeEdit {args} {
     dde servername -handler [namespace origin DdeHandler] DdeEdit

     button .b -text "Exit" -command {destroy .}
     set t [text .t]

     $t insert end $args

     pack .b -side bottom -fill x
     pack .t -side top -fill both -expand 1

     tkwait window .
 }

 # -------------------------------------------------------------------------
 # We expect to receive commands in fairly standard DDE style.
 # eg: Open("<filename>"), etc.
 # If it doesn't match up - reject it.
 #
 proc ::DdeEdit::DdeHandler {cmd} {
     set bits [split $cmd ()]
     switch -exact -- [set verb [lindex $bits 0]] {
         Open { return [DdeHandleOpen [lindex $bits 1]] }
         Run  { return [DdeHandleRun [lindex $bits 1]] }
         Exit { return [DdehandleExit] }
         default {
             return -code error "invalid dde command:\
                 \"$verb\" must be one of Open, Run or Exit."
         }
     }
     return
 }

 proc ::DdeEdit::DdeHandleOpen {filename} {
     set filename [string trim $filename "\""]
     if {![file readable $filename]} {
         return -code error "file \"$filename\" is not readable: \
 [llength $filename]\
     [llength [lindex $filename 0]]"
     }
     set f [open $filename r]
     set d [read $f]
     close $f
     ShowDialog $d
 }

 proc ::DdeEdit::DdeHandleExit {} {
     after 100 {destroy .}
 }

 # -------------------------------------------------------------------------
 # Description:
 #  Show a simple dialog without locking up the application.
 #  DDE calls need to return within a reasonable amount of time or the calling
 #  application raises an error - this means we cannot use tk_messageBox here.
 #
 proc ::DdeEdit::ShowDialog {text} {
     variable uid
     variable dialogs

     set dlg [toplevel .t[incr uid]]
     set t [text $dlg.t]
     button $dlg.b -text "Close" -command [list destroy $dlg]

     $t insert end $text

     pack $dlg.b -side bottom -fill x
     pack $dlg.t -side top -fill both -expand 1
     lappend dialogs $dlg
 }

 # -------------------------------------------------------------------------
 # Description:
 #  Pop the nth element off a list. Used in options processing.
 #
 proc ::DdeEdit::Pop {varname {nth 0}} {
     upvar $varname args
     set r [lindex $args $nth]
     set args [lreplace $args $nth $nth]
     return $r
 }

 # -------------------------------------------------------------------------
 # Description:
 #  Called to register the ".z_t" file suffix with Windows.
 #
 proc ::DdeEdit::install {} {
     package require registry
     set HKCR HKEY_CLASSES_ROOT
     registry set "$HKCR\\.z_t" {} z_tfile
     registry set $HKCR\\z_tfile {} "DDE Test File"
     registry set $HKCR\\z_tfile\\shell {} {}
     registry set $HKCR\\z_tfile\\shell\\&Open {} "&Open"
     registry set $HKCR\\z_tfile\\shell\\&Open\\ddeexec {} "Open(\"%1\")"
     registry set $HKCR\\z_tfile\\shell\\&Open\\ddeexec\\application {} "TclEval"
     registry set $HKCR\\z_tfile\\shell\\&Open\\ddeexec\\topic {} "DdeEdit"
     registry set $HKCR\\z_tfile\\shell\\&Open\\command {} \
         "[file nativename [info script]] \"%1\""
 }

 # -------------------------------------------------------------------------

 if {$tcl_interactive} {
     puts "loaded"
 } else {
     if {[llength $argv] == 1 && [string match "-install" [lindex $argv 0]]} {
         ::DdeEdit::install
         puts "install done"
         exit 0
     }

     # See if we already have a running app.
     package require Tk
     if {[dde services TclEval DdeEdit] != {}} {
         wm withdraw .
         set filename [file normalize [lindex $argv 0]]
         dde eval DdeEdit "Open(\"$filename\")"
         exit 0
     } else {
         eval DdeEdit::DdeEdit $argv
     }
 }