- 26 October 2010 - Hello tcl'ers, I would like to share with you a method to create a custom toplevel frame, such as a rounded rectangular or full circular/elliptical one. A solution that I present here is for the Win OS, it's using dll's provided by the OS with the help of Ffidl to access it. To demonstrate how it is implemented in tG² , click here for a short movie. Enjoy!
Note: another enthousiast has already developed a solution for the X OS, see Managed and shaped toplevel.
# ------------------------------------------------------------------------------ # TopTcl_1.tcl for tG² is under BSD License, Copyright (C) 2010 by 'SeS' # See https://wiki.tcl-lang.org/25888 # Permission is hereby granted, free of charge, to any person obtaining a copy of # this software and associated documentation files (the ``Software''), to deal in # the Software without restriction, including without limitation the rights to use, # copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the # Software, and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------ # Purpose : creates alternative toplevel frame with optional transparent shadow # ------------------------------------------------------------------------------ proc TopTcl {tParent TLT W H rndArc {shadowType 3} {sfg black}} { wm overrideredirect $tParent 1 if {$shadowType > 0} { wm attribute $tParent -topmost 1 toplevel ${tParent}copy wm geometry ${tParent}copy 1x1+5000+5000 wm overrideredirect ${tParent}copy 1 wm attribute ${tParent}copy -alpha 0.5 wm title ${tParent}copy "${tParent}copy_shadow" wm transient ${tParent}copy $tParent pack [frame ${tParent}copy.lab -bg $sfg -bd 0 -relief flat] -expand 1 -fill both update switch $TLT { "rrectangle" {dll_SetWindowRgn [getHwnd [wm title ${tParent}copy]] [dll_CreateRoundRectRgn 0 0 $W $H $rndArc $rndArc] True} "elliptic" {dll_SetWindowRgn [getHwnd [wm title ${tParent}copy]] [dll_CreateEllipticRgn [lindex $rndArc 0] [lindex $rndArc 1] $W $H] True} } bind $tParent <FocusOut> "+; wm attribute ${tParent}copy -alpha 0.1" bind $tParent <FocusIn> "+; wm attribute ${tParent}copy -alpha 0.5; eval \[bind $tParent <Configure>]" bind $tParent <Configure> "+; set geo \[split \[split \[wm geometry $tParent] x\] +\] wm deiconify ${tParent}copy wm geometry ${tParent}copy \[lindex \$geo 0 0]x\[lindex \$geo 0 1]+\[expr \[lindex \$geo 1]+$shadowType]+\[expr \[lindex \$geo 2]+$shadowType] " wm title ${tParent}copy "" } switch $TLT { "rrectangle" {dll_SetWindowRgn [getHwnd [wm title $tParent]] [dll_CreateRoundRectRgn 0 0 $W $H $rndArc $rndArc] True} "elliptic" {dll_SetWindowRgn [getHwnd [wm title $tParent]] [dll_CreateEllipticRgn [lindex $rndArc 0] [lindex $rndArc 1] $W $H] True} } #enableMoveFromAnywhere $tParent; available in official release of tG² } # ------------------------------------------------------------------------------ # TopTcl_1.tcl wrapper has dependencies to ffidl package # ------------------------------------------------------------------------------ package require Ffidl 0.6 ffidl::callout dll_CreateRoundRectRgn {int int int int int int} int [ffidl::symbol gdi32.dll CreateRoundRectRgn] ffidl::callout dll_FindWindowTitle {int pointer-utf8} int [ffidl::symbol user32.dll FindWindowA] ffidl::callout dll_SetWindowRgn {int int pointer-utf8} int [ffidl::symbol user32.dll SetWindowRgn] ffidl::callout dll_CreateEllipticRgn {int int int int} int [ffidl::symbol gdi32.dll CreateEllipticRgn] proc getHwnd {windowname} {return [dll_FindWindowTitle 0 $windowname]} # ------------------------------------------------------------------------------ # TEST SCRIPT: # ------------------------------------------------------------------------------ # Test conditions: # -WinXP OS # -ActiveState's tcl/tk v8.4.19 distribution, using "wish" # -Ffidl v0.6 set MainProgramSize [split [lindex [split [wm geo .] +] 0] x] bind . <Escape> {exit} TopTcl . rrectangle [lindex $MainProgramSize 0] [lindex $MainProgramSize 1] 20 10
See also Shape. You can also do similar things - though possibly a little more limited than the above - using wm (at least on Windows):
. configure -background yellow pack [label .l -text "Testing" -background red -foreground yellow -font "Arial 36 bold"] wm attributes . -transparentcolor yellow wm override . 1 ;# add code for dragging the window around bind . <Escape> {exit}
SeS : thanks for the additional info MG, this is interesting, maybe I can combine/integrate this into tG²