Odd. I must admit that I've never encountered this problem before, but then I almost never use a mouse with a mouse wheel. I wasn't able to recreate the problem you described when I hooked up a mouse with mouse wheel, either.
Checking the
bind command manual page, this is what it had to say about <MouseWheel> events:
"By rolling the wheel, the system will generate MouseWheel events that the application can use to scroll. Like Key events the event is always routed to the window that currently has focus...."
So, it doesn't look as though the mouse wheel is causing the focus problems. Which seems to point to the user clicking in the main window before scrolling with the mouse wheel. My guess is that you're somehow not establishing your grab properly.
Grabs are very tricky things. In particular, the window
must be already visible when you execute the
grab command, or else the grab
fails. So if your code does:
Code:
wm deiconify .dialog
grab .dialog
The window manager might not have had time to display the window before the
grab command executes.
The best way to solve this problem is as follows:
Code:
wm deiconify .dialog
tkwait visibility .dialog
grab .dialog
The
tkwait visibility command will cause your script to pause until the dialog window is displayed. It's then safe to establish the grab.
Modal dialogs are actually quite tricky beasts to create. There are a lot of things to think through and handle. I'm going to include a sample program demonstrating how I usually go about creating modal dialogs. It illustrates the different things to consider and how to go about handling them in your script.
Code:
package require Tk
# Create a simple dialog and withdraw
# it for later use
toplevel .dialog
label .dialog.msg -text "You have mail!"
pack .dialog.msg -padx 4 -pady 4
# Setting the global variable "done" is
# how we signal that we're ready to dismiss
# the dialog.
button .dialog.ok -text "Ok" -command {
set done 1
}
pack .dialog.ok -padx 4 -pady 4
wm title .dialog "New Mail"
wm group .dialog .
# Set the minimum size of the window when
# it is first displayed
bind .dialog <Configure> {
# We'll use the initial size as
# the minimum size of the window
wm minsize .dialog [winfo reqwidth .dialog] [winfo reqheight .dialog]
# We no longer need our <Configure>
# binding, so delete it.
bind .dialog <Configure> {}
}
# If the user closes the window with the
# window manager (e.g., by clicking on the
# X in the titlebar), just invoke the Ok
# button to dismiss the window without
# destroying it.
wm protocol .dialog WM_DELETE_WINDOW {
.dialog.ok invoke
}
# Once we've grabbed events, any mouse
# clicks on other windows in the application
# get redirected to our dialog. In case our
# dialog has been obscured by other windows,
# let's raise the dialog on top of all other
# windows.
bind .dialog <ButtonPress> {
raise .dialog
}
# Hide our dialog window until we need it
wm withdraw .dialog
# This is the procedure that displays the
# dialog, and then waits until it is
# dismissed.
proc DisplayDialog {} {
global done
# Display the window
wm deiconify .dialog
# Wait until the window is really
# visible before grabbing
tkwait visibility .dialog
# Now grab events and assign focus to
# the Ok button
grab .dialog
focus .dialog.ok
# Wait until the user clicks the Ok button
tkwait variable done
# Release the grab and hide the window
grab release .dialog
wm withdraw .dialog
}
# This is our main window
text .t -width 20 -height 4
button .popup -text "Check Mail" -command DisplayDialog
button .quit -text "Quit" -command exit
pack .t .popup .quit -padx 4 -pady 4
- Ken Jones, President
Avia Training and Consulting
866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax