我有一个小的控制台应用程序,其中包括检查另一个操作的状态。每隔一秒,它会使用Term :: ReadKey检查按键。如果已按下'r'键,则刷新显示:
{ # generate display ...
print "Press 'r' to refresh, any other key to exit: ";
my $resp = readkey();
print $resp;
redo if $resp =~ /r/i;
}
exit;
sub readkey {
my $key;
ReadMode('cbreak');
while (not defined $key) {
if (defined ($key = ReadKey(-1)) ) {
exit if $key =~ /\cC/i; # allow Ctrl-C to behave normally
return $key;
} else {
sleep 1;
}
}
ReadMode('normal');
}
这一切都与预期完全一致。但是,我也使用Caffeine让我的Win 7显示器无法进入睡眠状态。这个实用程序的工作原理是每隔59秒模拟一次F15的按下,从而永远不会让屏幕保护程序启动。虽然Caffeine的方法非常糟糕,但它对我来说已经很好用了很多年了。但是,像Windows一样,我的控制台应用程序也会将F15的模拟按键读作真正的按键,导致控制台应用程序退出。如果我可以匹配F15,我可以过滤掉它。所以,我的问题是:
如何使用Term :: ReadKey确定是否已按下F15?
这是在Windows 7 Pro,Strawberry 5.12.3,Term :: ReadKey v.2.30.02。
(我知道我的问题可能有一个重要的x-y problem组件,我欢迎其他解决方案。但是,我很好奇如何做到这一点。我明白为什么我可能想看到在其他情况下按下功能键时。)
答案 0 :(得分:2)
[你很高兴你认识到这是非常的xy:)]
您正在使用以Unix为中心的模块。使用更合适的模块:Win32::Console,例如。
[我之前的回答转换为评论。显然,Stack Overflow mods希望我的答案是99%repeated content?!?]
my $con_in = Win32::Console->new(STD_INPUT_HANDLE);
for (;;) {
my @event = $con_in->Input();
my $event_type = shift(@event);
next if !defined($event_type) || $event_type != 1; # 1: Keyboard
my ($key_down, $repeat_count, $vkcode, $vscode, $char, $ctrl_key_state) = @event;
if ($vkcode == VK_F15 && ($ctrl_key_state & SHIFTED_MASK) == 0) {
if ($key_down) {
say "<Up> pressed/held down" for 1..$repeat_count;
} else {
say "<Up> released";
}
}
}
有关键盘事件的详情,请参阅KEY_EVENT_RECORD。
请参阅Virtual-Key Codes以确定密钥。
上述代码的标题和定义:
use strict;
use warnings;
use feature qw( say );
use Win32::Console qw( STD_INPUT_HANDLE );
use constant {
RIGHT_ALT_PRESSED => 0x0001,
LEFT_ALT_PRESSED => 0x0002,
RIGHT_CTRL_PRESSED => 0x0004,
LEFT_CTRL_PRESSED => 0x0008,
SHIFT_PRESSED => 0x0010,
VK_F15 => 0x7E,
};
use constant SHIFTED_MASK =>
RIGHT_ALT_PRESSED |
LEFT_ALT_PRESSED |
RIGHT_CTRL_PRESSED |
LEFT_CTRL_PRESSED |
SHIFT_PRESSED;