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 SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Making modal dialog box

Status
Not open for further replies.

akpr

Programmer
Jul 25, 2001
19
0
0
US
I created a dialog box using TCL/TK how do i make that as modal dialog box
 
First (and most importantly), be aware that Tcl comes with several built-in modal dialogs that display platform native dialog windows. Check out:
[ul][li]tk_messageBox[/li][li]tk_dialog[/li][li]tk_getOpenFile[/li][li]tk_getSaveFile[/li][li]tk_chooseDirectory[/li][li]tk_chooseColor[/li][/ul]But let's assume that you need to create your own custom dialog. Modal dialogs are tricky in just about every language. There are several different issues to handle:
[ul][li]Preventing the user from interacting with the rest of the application[/li][li]Reporting the user's selection to the rest of the application[/li][li]Handling "non-standard window termination" (typically, the user killing the dialog window through the window manager menu or the title bar's close window icon)[/li][li]Preventing your dialog from getting "lost" on the screen[/li][li]Returning regular event control back to the application[/li][/ul]Brent Welch describes an approach for creating and using modal dialogs on pages 516-522 of Practical Progamming in Tcl/Tk, 3rd ed. Mark Harrison and Michael McLennan give a slightly different approach, which I tend to prefer, on pages 242-246 of Effective Tcl/Tk Programming.

Implementing the "modal" part of the solution involves calling grab set to direct all pointer and keyboard events to your dialog window, then calling grab release to return event processing back to normal.

Handling "non-standard window termination" involves using wm protocol to intercept the window manager's message attempting to destroy your dialog's window. I typically interpret this as the user trying to "cancel" the dialog, and so typically invoke the dialog's Cancel button.

Handling the window getting lost is trickier. If the dialog gets covered by other windows, iconified, or otherwise hidden, the user may forget about it and try to interact with the main application. However, since we've got a grab in effect, the mouse pointer and keyboard events get redirected to the dialog. I use Harrison and McLennan's trick of installing a special binding on the dialog to make sure the dialog's displayed and raised on top of all other windows. I show this code below.

Then we just need to put it all together so that everything happens in the sequence that we want it to happen. What I'm going to show is a hybrid of Welch's and Harrison and McLennan's approach. It assumes that you're using what I call a Show/Hide approach to dialog management, where you create the dialog window once, then show it as needed using wm deiconify and hide it when it's no longer needed using wm withdraw. However, the approach is adaptable to dialogs that you create as needed and destroy when dismissed (Create/Destroy approach). I don't know exactly what your dialog does. But for the sake of example, I create a simple message box with an Ok and a Cancel button. I create a procedure called Confirm that accepts one argument, the message to display, and returns 1 if the user clicked Ok or 0 if the user clicked Cancel.

Code:
###########################
# Create the dialog
###########################

toplevel .dialog
label .dialog.msg  ;# Text supplied by Confirm
pack .dialog.msg -side top -padx 4 -pady 4

button .dialog.ok -text "Ok" -command {
    # confirmStatus is a global variable that will
    # hold the value corresponding to the button
    # clicked.  It will also serve as our signal
    # to our Confirm procedure that the user has
    # finished interacting with the dialog

    set confirmStatus 1
}

button .dialog.cancel -text "Cancel" -command {
    set confirmStatus 0
}

pack .dialog.ok .dialog.cancel -side left -expand yes

# Set the window title, then withdraw the window
# from the screen (hide it)

wm title .dialog "Please confirm"
wm withdraw .dialog

# Install a binding to handle the dialog getting
# lost.  If the user tries to click a mouse button
# in our main application, it gets redirected to
# the dialog window.  This binding detects a mouse
# click and in response deiconfies the window (in
# case it was iconified) and raises it to the top
# of the window stack.
# 
# We use a symbolic binding tag so that we can
# install this binding easily on all modal dialogs
# we want to create.

bind modalDialog <ButtonPress> {
    wm deiconify %W
    raise %W
}

bindtags .dialog [linsert [bindtags .dialog] 0 modalDialog]

# Handle the &quot;non-standard window termination&quot; by
# invoking the Cancel button when we receives a
# WM_DELETE_WINDOW message from the window manager.

wm protocol .dialog WM_DELETE_WINDOW {
    .dialog.cancel invoke
}

###########################
# Display the dialog
###########################

proc Confirm {msg} {
    global confirmStatus

    # Save old keyboard focus
    set oldFocus [focus]

    # Set the dialog message and display the dialog

    .dialog.msg configure -text $msg
    wm deiconify .dialog

    # Wait for the window to be displayed
    # before grabbing events

    catch {tkwait visibility .dialog}
    catch {grab set .dialog}

    # Now drop into the event loop and wait
    # until the confirmStatus variable is
    # set.  This is our signal that the user
    # has clicked on one of the buttons.

    tkwait variable confirmStatus

    # Release the grab (very important!) and
    # return focus to its original widget.
    # Then hide the dialog and return the result.

    grab release .dialog
    focus $oldFocus
    wm withdraw .dialog

    return $confirmStatus
}

# Example of using the procedure

set result [Confirm &quot;Reformat hard drive?&quot;]
- Ken Jones, President
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