Here's a procedure which takes a few parameters (at least a unique tk toplevel window name) and shows a dialog for Search & Replace-type operations:

# 01.02.2010
# ToDo:
# - namespace
proc sr {w args} {
# eingebaute Defaults
array set a {
-command {}
-title {Suchen & Ersetzen}
-old {}
-new {}
-ignoreword 0
-ignorecase 0
-entryWidth 40
-askempty 1
-stay 0
}
array set a $args;# Fehler propagieren, kein Catch!
toplevel $w
if {[winfo viewable .]} {
wm transient $w .; # [winfo parent] statt .?
}
wm withdraw $w
wm title $w $a(-title)
wm resizable $w 0 0; # wenn überhaupt, dann nur in x-Richtung (da Feldbreite fix)
set wf1 [ttk::frame $w.txt -padding {4 8}]
set wf2 [ttk::frame $w.but -padding {4 8}]
set wf3 [ttk::labelframe $w.opt -padding {2 4} -text Optionen:]
ttk::label $wf1.oldLbl -underline 0 -text "Suchen nach:"
ttk::label $wf1.newLbl -underline 0 -text "Ersetzen durch:"
ttk::entry $wf1.oldEntry -width $a(-entryWidth) -validate key \
-validatecommand [list srVal $wf2.ok %P]
ttk::entry $wf1.newEntry -width $a(-entryWidth)
ttk::button $wf2.ok -width 10 -text "Start" -state disabled \
-command [list srDo $w $a(-command) $a(-askempty) $a(-stay)]; # -default active
ttk::button $wf2.quit -width 10 -text "Abbruch" -command [list destroy $w]
ttk::checkbutton $wf3.word -text {Wortgrenzen ignorieren} -underline 0
ttk::checkbutton $wf3.case -text {Schreibweise ignorieren} -underline 1
$wf1.oldEntry insert end $a(-old); # erspart uns globale -textvariable(n)
$wf1.newEntry insert end $a(-new)
grid $wf1.oldLbl -column 0 -row 0 -sticky nse -padx {4 4} -pady {8 0}
grid $wf1.newLbl -column 0 -row 1 -sticky nse -padx {4 4} -pady {8 0}
grid $wf1.oldEntry -column 1 -row 0 -sticky nsew -padx {4 4} -pady {8 0}
grid $wf1.newEntry -column 1 -row 1 -sticky nsew -padx {4 4} -pady {8 0}
grid $wf2.ok -column 0 -row 0 -sticky nsew -padx {0 4} -pady {8 0}
grid $wf2.quit -column 0 -row 1 -sticky nsew -padx {0 4} -pady {8 0}
pack $wf3.word $wf3.case -side left -anchor nw
grid $wf1 -column 0 -row 0 -sticky nsew -padx {4 4} -pady {4 0}
grid $wf2 -column 1 -row 0 -sticky nsew -padx {4 4} -pady {4 4}
grid $wf3 -column 0 -row 1 -sticky nsew -padx {12 12} -pady {0 12} -columnspan 2
bind $w <Escape> "$wf2.quit invoke; break;"; # <Escape> ist *überall* 'Abbruch'
bind $w <Return> "$wf2.ok invoke; break;"; # <Return> ist *überall* 'Go!' (ausser auf Escape-Button)
bind TButton <Return> "%W invoke; break;"; # alle Buttons führen sich mit <Return> aus
bind $w <Alt-s> "focus -force $wf1.oldEntry; break;"
bind $w <Alt-e> "focus -force $wf1.newEntry; break;"
bind $w <Alt-w> "$wf3.word invoke; break;"
bind $w <Alt-c> "$wf3.case invoke; break;"
$wf3.word state !alternate
$wf3.case state !alternate
# geht das nicht eleganter???
if {$a(-ignoreword)} {
$wf3.word state selected
}
if {$a(-ignorecase)} {
$wf3.case state selected
}
# Farbgebung wie früher korrigieren, nur gemäss Ttk-Systematik
bind TButton <FocusIn> {%W state active}
bind TButton <FocusOut> {%W state !active}
catch {center_window $w}
wm deiconify $w
catch {tk visibility $w}
focus -force $wf1.oldEntry;
# die -stay-Option könnte als Checkbox exportiert werden
if {!$a(-stay)} {
catch {grab set $w}
}
catch {tkwait window $w}
}
proc srVal {b v} {
# uns interessiert hier nur das Umschalten des Buttos
if {[string length $v]} {
$b configure -state normal
} else {
$b configure -state disabled
}
return 1
}
proc srDo {w command ask stay} {
# vermeidet globale Vars
set old [$w.txt.oldEntry get]
set new [$w.txt.newEntry get]
set igW [$w.opt.word instate selected]
set igC [$w.opt.case instate selected]
if {[string length $new] == 0 && $ask == 1} {
if {[tk_messageBox -type yesno -title ACHTUNG: \
-message "Die Zeichenkette '$old' wird *gelöscht* werden!
Wirklich fortfahren (J/N)?" -icon warning] == "no"} {
return
}
}
catch {uplevel #0 [list $command $old $new $igW $igC $w]}
if {$stay == 0} {
destroy $w
}
}Some little tests / demonstrations:
#######################
#
# Demos
#
proc dummyCallback {args} {
tk_messageBox -message "Dummy S/R-Aktion; args:= $args"
}
ttk::entry .e1 -width 40
pack .e1
bind .e1 <Control-f> [list sr .w1 -command dummyCallback]
bind .e1 <Control-g> [list sr .w2 -command dummyCallback -stay 1 -old Datei -ignorecase 1]
focus -force .e1Some explanations (to be continued):