1

我有一个小控制台应用程序,其中包括检查另一个操作的状态。它使用 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');
}    

这一切都完全按预期工作。但是,我也使用咖啡因来防止我的 Win 7 显示器进入睡眠状态。该实用程序通过每 59 秒模拟一次 F15 来工作,因此永远不会启动屏幕保护程序。尽管 Caffeine 的方法非常笨拙,但多年来对我来说效果很好。但是,与 Windows 一样,我的控制台应用程序也会将 F15 的模拟按下读取为真正的按键,从而导致控制台应用程序退出。如果我可以匹配 F15,我可以将其过滤掉。所以,我的问题:

如何使用 Term::ReadKey 确定是否按下了 F15?

这是在 Windows 7 Pro、Strawberry 5.12.3、Term::ReadKey v. 2.30.02 上。

(我知道我的问题可能有一个重要的xy 问题组成部分,我欢迎其他解决方案。但是,我很好奇如何做到这一点。我可以明白为什么我可能想看看功能键何时在其他情况下按下。)

4

1 回答 1

2

[很高兴你认识到这是非常 xy :)]

您正在使用以 unix 为中心的模块。使用更合适的模块:例如Win32::Console

[我之前的回答变成了评论。显然,Stack Overflow 模组希望我的答案是 99% 的重复内容?!?]

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

请参阅虚拟键代码以识别键。


上述代码的标题和定义:

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;
于 2012-05-01T06:26:29.527 回答