''From the [bind] man page:'' Some mice on the Windows platform support a mouse wheel which is used for scrolling documents without using the scrollbars. 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. When the event is received you can use the %D substitution to get the delta field for the event which is a integer value of motion that the mouse wheel has moved. The smallest value for which the system will report is defined by the OS. On Windows 95 & 98 machines this value is at least 120 before it is reported. However, higher resolution devices may be available in the future. The sign of the value determines which direction your widget should scroll. Positive values should scroll up and negative values should scroll down. Example binding to scroll a canvas (in [a little XML browser]) up or down: bind .t.c {%W yview scroll [expr {-%D/120}] units} Dividing by 120 leads to scrolling one line per wheel click (minimum effective wheel movement) - use a smaller divisor if you want to scroll faster. ([RS]) By "cubing" the number of units, you have the effect that slow turning of the wheel moves slowly, while fast turning lets you jump up or down: bind .t.c {%W yview scroll [expr {int(pow(%D/-120,3))}] units} [Kevin Walzer] On OS X/Aqua the correct mousewheel binding would be: bind .t.c {%W yview scroll [expr {- (%D)}] units} [PAK] This didn't work on my Windows 2000 box with Tcl 8.4. Instead I accumulated all MouseWheel events for 200 ms before cubing. E.g., bind .t.c { collect %W %D } set ::afterid {} set ::delta 0 proc collect {W D} { global delta global afterid if {$afterid eq {}} { set delta $D set afterid [after 200 "$W yview scroll \[expr {int(pow(\$delta/-120,3))}] units"] } else { incr delta $D } } This will also work on Unix with the Button-4/Button-5 to MouseWheel translation given below. ---- [rmax] AFAIK, works on Windows only. On X you have to bind to the and events. - IIRC, Button-4/5 is even not the only way of mapping the mouse wheel on X. As X doesn't support mouse wheels natively, there are at least three different possible mappings floating around, but I don't currently tremember the other two. [ZB] 2007-10-09 I'm using (8.5b1 on Linux) something like this - and it just works: bind .win "MouseScroll %D" ---- [KBK] Note that on Windows, the events don't go to the window that contains the mouse pointer, but rather the window that has the ''keyboard'' focus. For various arcane reasons, this behavior is The Right Thing, but it surprises most programmers the first time they see it. Also, note that directing the events to the window with the focus means that the window that is to be scrolled must be able to take the focus. [PAK] If you insist on doing The Wrong Thing, you can do so by binding the toplevel window to the event then trigger a virtual event <> with the correct window. Because you can't set -delta for virtual events, you will need to save the delta value in a global variable which you can recover in the wheel binding. bind [winfo toplevel .t.graph] { trigger %W %X %Y %D } proc trigger {W X Y D} { set w [winfo containing -displayof $W $X $Y] if { $w ne "" } { set x [expr {$X-[winfo rootx $w]}] set y [expr {$Y-[winfo rooty $w]}] global delta set delta $D event generate $w <> -rootx $X -rooty $Y -x $x -y $y } } bind .t.graph <> { %W zoom %x %y $delta } [KPV] Tip 171 [http://www.tcl.tk/cgi-bin/tct/tip/171.html] proposes to change events from being sent to the focus window to the window containing the mouse. This is actually how BWidgets has been doing it all along. I find that this is more intuitive and is The Right Thing. ---- '''Font resizing via mousewheel:''' The following binding reconfigures a widget with -font attribute (e.g. [text], [message], [entry] ...) according to mousewheel rotation: pack [text .t -font {Helvetica 10} -wrap word -width 30 -height 10] .t insert end "This is a little demo text to test the font sizing via mousewheel" catch {bind .t { set font [%W cget -font] set fs [expr {[lindex $font 1]+%D/120}] %W config -font [lreplace $font 1 1 $fs] }} I've added the [catch] because on older Windows versions this event is not supported. Also, the default font does not scale in fine steps - but by specifying one that is implemented as TrueType, the effect is really nice ;-) [RS] ---- [MGS] Here's a quick little hack to get MouseWheel events on X (Linux): bind all \ {event generate [focus -displayof %W] -delta 120} bind all \ {event generate [focus -displayof %W] -delta -120} Then you could do (for instance): bind Scrollbar {eval [%W cget -command] scroll [expr {%D/-120}] units} but this won't work (as it is) for scrollbars with no -command set. [RS]: Then again, a [scrollbar] without -command is a pretty useless creature... ---- [RWC] Some links to other MouseWheel code: * http://colas.nahaboo.net/mouse-wheel-scroll/#tcl * [http://code.activestate.com/recipes/68394/%|%Supporting mouse wheel on vertical scrollbars (ActiveState Cookbook)] Of the above, only the ASPN example will vertically scroll a canvas. Later in the ASPN article is another implementation that attempts to include horizontal scrolling, but doesn't appear to work for a canvas. ---- [RS] 2007-09-24: I'm not sure how the state of discussion is about mousewheel enabling by just mousing-over, but I wanted this for a UI with a listbox and a text widget, both scrollable. Simple but useful: foreach i {.listbox .text} {bind $i {focus %W}} [MG] has added this binding to one of his apps, which has a lot of textwidgets, for handling mousewheel events (requires Tcl 8.5): bind Text {} bind all [list mouseWheel %W %D] proc mouseWheel {widget delta} { if { $delta >= 0 } { set cmd [list yview scroll [expr {-$delta/3}] pixels] } else { set cmd [list yview scroll [expr {(2-$delta)/3}] pixels] } set over [winfo containing -displayof $widget {*}[winfo pointerxy $widget]] if { $over == "" || [catch {$over {*}$cmd}] } { catch {$widget {*}$cmd} } return; };# mouseWheel It attempts to scroll the widget the mouse is over first, and then tries the one with the focus (where the event was actually generated) if it fails. ---- <> in TCL 8.6 [HaO] 2012-03-08: Koen Danckaert enlighted me in the MouseWheel implementation in Tcl 8.6 by a [clt] post of today titled "MouseWheel TIP #171 interaction with canvas" [http://groups.google.com/group/comp.lang.tcl/browse_thread/thread/afa34a966e4bbe83/d1b2fd5b4e45473b#d1b2fd5b4e45473b] . <> ---- !!!!!! [Tk syntax help] - [Arts and Crafts of Tcl-Tk Programming] %| [Category Discussion] | [Category GUI] |% !!!!!!