2012-04-17 13 views
0

shift - some-keyこのスクリプトとの組み合わせはどうすればわかりますか?
矢印キーを押したときに期待通りの結果が得られましたが、shift - tabを押すと、KEY_BTABの値が返されません。私はshifttabを押しWin32 :: Console :: Inputで `shift`-` key`の組み合わせをキャッチするにはどうすればいいですか?

use warnings; 
use 5.12.0; 
use Win32::Console qw(STD_INPUT_HANDLE ENABLE_MOUSE_INPUT); 
use constant { 
    RIGHT_ALT_PRESSED => 0x0001, 
    LEFT_ALT_PRESSED => 0x0002, 
    RIGHT_CTRL_PRESSED => 0x0004, 
    LEFT_CTRL_PRESSED => 0x0008, 
    SHIFT_PRESSED  => 0x0010, 

    VK_LEFT  => 0x25, 
    VK_UP  => 0x26,  
    VK_RIGHT => 0x27,  
    VK_DOWN  => 0x28,  
    VK_TAB  => 0x09,  
}; 
use constant SHIFTED_MASK => 
    RIGHT_ALT_PRESSED | 
    LEFT_ALT_PRESSED | 
    RIGHT_CTRL_PRESSED | 
    LEFT_CTRL_PRESSED | 
    SHIFT_PRESSED; 

my %d = (
    KEY_DOWN   => 258, 
    KEY_UP    => 259, 
    KEY_LEFT   => 260, 
    KEY_RIGHT   => 261, 
    KEY_BTAB   => 353, 
); 

my $con_in = Win32::Console->new(STD_INPUT_HANDLE); 
$con_in->Mode(ENABLE_MOUSE_INPUT); 

while (1) { 
     my $key = getch(); 
     say "<$key>"; 
     last if $key == 113; 
} 

sub getch { 
    my @event = $con_in->Input(); 
    my $event_type = shift(@event); 
    if (defined $event_type and $event_type == 1) { 
     my ($key_down, $repeat_c, $vkcode, $vsccode, $char, $ctrl_ks) = @event; 
     if ($char) { 
      return $char; 
     } 
     else { 
      if ($vkcode == VK_UP and ($ctrl_ks & SHIFTED_MASK) == 0) { 
       return $d{KEY_UP}; 
      } 
      elsif ($vkcode == VK_DOWN and ($ctrl_ks & SHIFTED_MASK) == 0) { 
       return $d{KEY_DOWN}; 
      } 
      elsif ($vkcode == VK_RIGHT and ($ctrl_ks & SHIFTED_MASK) == 0) { 
       return $d{KEY_RIGHT}; 
      }   
      elsif ($vkcode == VK_LEFT and ($ctrl_ks & SHIFTED_MASK) == 0) { 
       return $d{KEY_LEFT}; 
      } 
      elsif ($vkcode == VK_TAB and $ctrl_ks == SHIFT_PRESSED) { 
       return $d{KEY_BTAB}; # <-- 
      } 
      else { 
       say "beep"; 
      } 
     } 
    } 
} 

出力:getchルーチンを編集した後
ビープ
< 1>
< 9>
< 9>
ビープ
< 1>

この方法で

sub getch { 
    my @event = $con_in->Input(); 
    my $event_type = shift(@event); 
    if (defined $event_type and $event_type == 1) { 
     my ($key_down, $repeat_count, $virtual_keycode, $virtual_scancode, $char, $ctrl_key_state) = @event; 
     if ($char) { 
      if ($key_down) { 
       return $char for $repeat_count; 
      } 
     } 
     else { 
      if ($virtual_keycode == VK_UP and ($ctrl_key_state & SHIFTED_MASK) == 0) { 
       if ($key_down) { 
        return $d{KEY_UP} for $repeat_count; 
       } 
      } 
      elsif ($virtual_keycode == VK_DOWN and ($ctrl_key_state & SHIFTED_MASK) == 0) { 
       if ($key_down) {   
        return $d{KEY_DOWN} for $repeat_count; 
       } 
      } 
      elsif ($virtual_keycode == VK_RIGHT and ($ctrl_key_state & SHIFTED_MASK) == 0) { 
       if ($key_down) { 
        return $d{KEY_RIGHT} for $repeat_count; 
       } 
      }   
      elsif ($virtual_keycode == VK_LEFT and ($ctrl_key_state & SHIFTED_MASK) == 0) { 
       if ($key_down) { 
        return $d{KEY_LEFT} for $repeat_count; 
       } 
      } 
      elsif ($virtual_keycode == VK_TAB and ($ctrl_key_state & SHIFTED_MASK) == SHIFT_PRESSED) { 
       if ($key_down) { 
        return $d{KEY_BTAB} for $repeat_count; 
       } 
      } 
      else { 
       say "beep"; 
      } 
     } 
    } 
} 

私はこの出力を得る:
ビープ音を
< 1>
< 9>
< 0>
ビープ
< 1>

+1

私たちを懸命にしないでください。 Shift + Tabキーを押すと何が返されますか? – mob

+0

もう少しエラーがあるようです。 –

+1

EXPRのEXPRを返すとはどういう意味ですか? – mob

答えて

1

だと思います。 if ($char)の小切手を適切な場所に移動してください。


第2に、あなたのチェックが間違っています。たとえば、Caps Lockがオンの場合、次の機能は動作しません。

elsif ($vkcode == VK_TAB and $ctrl_ks == SHIFT_PRESSED) 

あなただけが興味を持っているフラグをチェックする必要があります。

elsif ($vkcode==VK_TAB and ($ctrl_ks & SHIFTED_MASK) == SHIFT_PRESSED) 

を最後に、時にはあなただけの複数のプレスのために一度通知を得ます。それは$repeat_countによって通知されます。これを無視するので、キーを無視する可能性があります。

$repeat_countを2番目のスニペットで処理しようとしましたが、悲惨に失敗します。問題の一部は、for 1..$repeat_countであるべきときに私の他の回答からfor $repeat_countをコピーしたことです。もう1つの問題は、$repeat_countが1より大きい場合でも1つの値しか返さないということです。


my @kbd_queue; 
sub getch { 
    my @event; 
    if (@kbd_queue) { 
     @event = (1, @{ pop @kbd_queue }); 
    } else { 
     @event = $con_in->Input(); 
    } 

    my $event_type = shift(@event); 
    if (defined $event_type and $event_type == 1) { 
     my ($key_down, $repeat_count, $virtual_keycode, $virtual_scancode, $char, $ctrl_key_state) = @event; 
     return -1 if !$key_down; 

     if ($virtual_keycode == VK_UP and ($ctrl_key_state & SHIFTED_MASK) == 0) { 
      push @kbd_queue, \@event for 2..$repeat_count; 
      return $d{KEY_UP}; 
     } 
     ... 
     elsif ($virtual_keycode == VK_TAB and ($ctrl_key_state & SHIFTED_MASK) == SHIFT_PRESSED) { 
      push @kbd_queue, \@event for 2..$repeat_count; 
      return $d{KEY_BTAB}; 
     } 
     elsif ($char) { 
      push @kbd_queue, \@event for 2..$repeat_count; 
      return $char; 
     } 
     else { 
      say "beep"; 
     } 
    } 
} 

あなたは、テーブル駆動型のものにこれを変換する必要があります。

3

私はあなたのコードを実行し、$ctrl_ksが持っています私がヒットしたときの値48(0x0030)シフト + 、およびの場合はがリリースされた場合は32(0x0020)です。私はあなたのチェックに取得することはありませんので、あなたがしたいのチェックは、まず、$charが9に設定されている

elsif ($vkcode==VK_TAB and ($ctrl_ks & SHIFT_PRESSED)==SHIFT_PRESSED) { 
    return $d{KEY_BTAB}; 
+1

や '($ ctrl_ks&SHIFTED_MASK)== SHIFT_PRESSED'、彼が望んでいる場合だけで+ TABをシフトしていないCtrl + Shiftキー+ TABまたは+ Altキー+ TABをシフト –