如何使用此脚本捕获shift
- some-key
组合?
当我按下箭头键时,我得到了我期望的结果,但当我按shift
- tab
时,它不会返回KEY_BTAB
值。
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";
}
}
}
}
当我按shift
和tab
时输出:
哔
&LT 1为卤素;
&LT; 9基
&LT; 9基
哔
&LT 1为卤素;
以这种方式编辑getch
例程
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";
}
}
}
}
我得到这个输出:
哔
&LT 1为卤素;
&LT; 9基
&℃,GT;
哔
&LT 1为卤素;
答案 0 :(得分:3)
当我运行你的代码时,当我点击 Shift + Tab 时,$ctrl_ks
的值为48(0x0030),当elsif ($vkcode==VK_TAB and ($ctrl_ks & SHIFT_PRESSED)==SHIFT_PRESSED) {
return $d{KEY_BTAB};
的值为32(0x0020) > Shift 已下达。我想你要做的检查是
{{1}}
答案 1 :(得分:1)
首先,$char
设置为9,因此您永远不会进行检查。将if ($char)
支票移至更合适的位置。
其次,你的检查是错误的。如果启用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
,但却失败了。问题的一部分是你应该for $repeat_count
从我的其他答案中复制for 1..$repeat_count
,而另一个问题是,即使$repeat_count
大于1,你也只返回一个值。< / p>
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";
}
}
}
你应该把它转换成桌面驱动的东西。