Henri Augusto
Henri Augusto

Reputation: 349

Keyboard-independent way of detecting shift+digits

I want to be able to detect when the user press digits. This part is working with the <Key-#> bindings (code below). But i need to react differently when the users press Shift+digits. I've tried <Shift-#> but it doesn't work because pressing Shift+digits will create events corresponding for chars like !, @, #, $, %, ¨, &, *, (, )

One could "listen" for those chars but problem is their position is not the same in all keyboards.

QWERTY - English enter image description here

AZERTY - as used in parts of Belgium enter image description here

Not only different layouts (QWERTY, AZERTY, DVORAK, etc) differ but even two different QWERTY keyboards can be different depending on your locale. (My qwerty keyboard has an ¨ in the same key as 6 as oposed to ^ as seen in the picture)

So "listening for stuff like exclam, dollar, ampersand and etc is a keyboard-dependent way of detecting Shift+digits.

Question: how can i do it in a keyboard-independent way?

frame .f -padx 50 -pady 50
focus -force .f
label .f.digit_label -text "Digit:" -padx 50 -pady 20
label .f.keypress_label -text "KeyPress" -padx 50 -pady 20
pack .f
pack .f.digit_label
pack .f.keypress_label
bind .f <Key-1> {::digit_press %K}
bind .f <Key-2> {::digit_press %K}
bind .f <Key-3> {::digit_press %K}
bind .f <Key-4> {::digit_press %K}
bind .f <Key-5> {::digit_press %K}
bind .f <Key-6> {::digit_press %K}
bind .f <Key-7> {::digit_press %K}
bind .f <Key-8> {::digit_press %K}
bind .f <Key-9> {::digit_press %K}
bind .f <Key-0> {::digit_press %K}

bind .f <Shift-1> {::digit_press %K}
bind .f <Shift-2> {::digit_press %K}
bind .f <Shift-3> {::digit_press %K}
bind .f <Shift-4> {::digit_press %K}
bind .f <Shift-5> {::digit_press %K}
bind .f <Shift-6> {::digit_press %K}
bind .f <Shift-7> {::digit_press %K}
bind .f <Shift-8> {::digit_press %K}
bind .f <Shift-9> {::digit_press %K}
bind .f <Shift-0> {::digit_press %K}
bind all <Escape> {exit}
bind all <KeyPress> {::keypress %K}


proc ::digit_press {str} {
    .f.digit_label configure -text "Digit: $str"
}
proc ::keypress {str} {
    .f.keypress_label configure -text "KeyPress: $str"
}

Upvotes: 0

Views: 133

Answers (1)

Donal Fellows
Donal Fellows

Reputation: 137627

Most of the time when writing software, you want the cooked symbolic names of keys or the characters that they encode. Not in your case. Tk mostly hides the low level from you, but you can get at it if you're prepared to work at decoding it. In particular, if you do this in a raw wish:

bind . <Key> {
    puts "%A:::%s:::%k:::%K"
}

Then you can press keys and see what you get. Be aware that there's no actual guarantee that these will be the same for all keyboards! On mine (UK layout), pressing 1, 2, 3 followed by shift and the same three keys prints this:

1:::0:::26:::1
2:::0:::27:::2
3:::0:::28:::3
{}:::0:::68:::Shift_R
!:::1:::26:::exclam
@:::1:::27:::at
£:::1:::28:::sterling

As you can see, the %k field reports the keycode that does not change on shift status, and the %s field becomes 1 when the shift key is down (it's a bitmap, so use [expr {%s & 1}] to test that). You'll have to throw events away too.

Upvotes: 1

Related Questions