Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

capture window's exit event

Status
Not open for further replies.

jiankunx

Technical User
Aug 16, 2002
4
CA
I want to capture event of the top window's exit event because I need to do some extra work before the program exits. But I do not know which event type I should use,in another words, what is the format of "standard X event types" mentioned in the BIND manual in TK.

bind ?? . {my scripts}

Appreciate your help
 
There are two methods that come to mind since you're dealing with toplevel windows.

One is to register a window protocol handler for the window using the wm protocol command. The window manger sends a WM_DELETE_WINDOW message to the window whenever it wants to delete the window. This includes when the user tries to close the window using the window manager's close icon (typically the little "X" in the corner of the titlebar) or the window menu. You could create the handler like this:

Code:
wm protocol . WM_DELETE_WINDOW {
    myCleanup
}

The thing to keep in mind with wm protocol is that the handler is called before the window is destroyed, and that your handler is responsible for destroying the window. Your handler can even decline to destroy the window. This is handy for posting those "Quit/Cancel" type dialogs that allow the user to decide not to close/exit. What I typically do in my applications is to invoke the same "quit" routine that I use for my File->Quit menu item. For example:

Code:
.mbar.file add command     -label "Quit" -underline 0     -command {confirmQuit}

# ...

wm protocol . WM_DELETE_WINDOW {
    .mbar.file invoke "Quit"
}

The other technique is to create a binding on the toplevel for <Destroy> events. In contrast to the WM_DELETE_WINDOW protocol, the <Destroy> event is delivered after the window is destroyed. The other trick to using the <Destroy> binding is to keep in mind that the toplevel window is also in the bindtag path for all child widgets it contains. In other words, any event delivered to a widget by default will also execute any applicable event bindings on the toplevel window that contains that widget.

This is usually quite handy (for example, it allows you to create <KeyPress> bindings on the toplevel for keyboard shortcuts that are active for the entire window), but it's not good for handling <Destroy> events. When a widget is destroyed, all of its descendants are destroyed as well. So, if you've got a <Destroy> binding on a toplevel window, it's going to get called for each widget in the window that's destroyed. To prevent the handler from executing for anything except the actual toplevel destruction, you need to add some extra code in your binding to check whech widget got the <Destroy> event. Here's how you usually do it:

Code:
bind . <Destroy> {
    # Test if the toplevel (in this case &quot;.&quot;)
    # received the event.
    if {%W == &quot;.&quot;} {
        myCleanup
    }
}

An example of a somewhat more generic test where you don't assume the toplevel is &quot;.&quot; might be:

Code:
bind . <Destroy> {
    # Test if we are a toplevel window
    if {&quot;%W&quot; == [winfo toplevel %W]} {
        myCleanup
    }
}
- Ken Jones, President, ken@avia-training.com
Avia Training and Consulting, 866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax
 
There are two methods that come to mind since you're dealing with toplevel windows.

One is to register a window protocol handler for the window using the wm protocol command. The window manger sends a WM_DELETE_WINDOW message to the window whenever it wants to delete the window. This includes when the user tries to close the window using the window manager's close icon (typically the little &quot;X&quot; in the corner of the titlebar) or the window menu. You could create the handler like this:

Code:
wm protocol . WM_DELETE_WINDOW {
    myCleanup
}

The thing to keep in mind with wm protocol is that the handler is called before the window is destroyed, and that your handler is responsible for destroying the window. Your handler can even decline to destroy the window. This is handy for posting those &quot;Quit/Cancel&quot; type dialogs that allow the user to decide not to close/exit. What I typically do in my applications is to invoke the same &quot;quit&quot; routine that I use for my File->Quit menu item. For example:

Code:
.mbar.file add command     -label &quot;Quit&quot; -underline 0     -command {confirmQuit}

# ...

wm protocol . WM_DELETE_WINDOW {
    .mbar.file invoke &quot;Quit&quot;
}

The other technique is to create a binding on the toplevel for <Destroy> events. In contrast to the WM_DELETE_WINDOW protocol, the <Destroy> event is delivered after the window is destroyed. The other trick to using the <Destroy> binding is to keep in mind that the toplevel window is also in the bindtag path for all child widgets it contains. In other words, any event delivered to a widget by default will also execute any applicable event bindings on the toplevel window that contains that widget.

This is usually quite handy (for example, it allows you to create <KeyPress> bindings on the toplevel for keyboard shortcuts that are active for the entire window), but it's not good for handling <Destroy> events. When a widget is destroyed, all of its descendants are destroyed as well. So, if you've got a <Destroy> binding on a toplevel window, it's going to get called for each widget in the window that's destroyed. To prevent the handler from executing for anything except the actual toplevel destruction, you need to add some extra code in your binding to check whech widget got the <Destroy> event. Here's how you usually do it:

Code:
bind . <Destroy> {
    # Test if the toplevel (in this case &quot;.&quot;)
    # received the event.
    if {%W == &quot;.&quot;} {
        myCleanup
    }
}

An example of a somewhat more generic test where you don't assume the toplevel is &quot;.&quot; might be:

Code:
bind . <Destroy> {
    # Test if we are a toplevel window
    if {&quot;%W&quot; == [winfo toplevel %W]} {
        myCleanup
    }
}
- Ken Jones, President, ken@avia-training.com
Avia Training and Consulting, 866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax
 
By the way, I just noticed a small error in the first <Destroy> binding I provided. That should have been:

[tt]bind . <Destroy> {
# Test if the toplevel (in this case &quot;.&quot;)
# received the event.
if {&quot;%W&quot; == &quot;.&quot;} {
myCleanup
}
}[/tt]

It all has to do with the fact that all literal strings in conditions must be quoted. Let's just leave it at that for now. :)

Oh, and sorry for the double post earlier. I encountered a slight glitch in Tek Tips, and didn't think that my first attempt was posted. Not an attempt to artificially bump up my post count. :) - Ken Jones, President, ken@avia-training.com
Avia Training and Consulting, 866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top