473,847 Members | 1,830 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

detect keyboard input without reading it?

Hi all,
I was wondering if you could help out with this problem that I am having.
What I am trying to do is detect keyboard input in a while loop without
halting/pausing the loop until the key is pressed (without hitting return).
I looked at serveral faq's on the net and installed the cspan readkey module
and neither seems to work most likey its me since I am getting frustrated.
but anyway here's a sample code.

while (1) {
if (keypress) {
print "you've pressed: $key\n";
}
else {
print"Continuin g to loop...\n";
sleep 1; # delay the loop incase you need to control-c out.
}
}

TIA!
Scott Shaw
ss***@twmi.rr.c om

Jul 19 '05 #1
1 20474
"Scott Shaw" <ss***@twmi.rr. com> wrote in message news:<%P******* *************** *@twister.colum bus.rr.com>...
I was wondering if you could help out with this problem that I am having.
What I am trying to do is detect keyboard input in a while loop without
halting/pausing the loop until the key is pressed (without hitting return).
I looked at serveral faq's on the net and installed the cspan readkey module
and neither seems to work most likey its me since I am getting frustrated.


Dear Scott,

I know I've been frustrated trying to make a portable Perl program
that accepts individual keystrokes. The simple solution is to install
the Term::ReadKey module, but that isn't always an option since it's
not always possible to install modules on every platform you'll
encounter.

Therefore, I wrote the following script to provide a portable way
to read individual keystrokes without resorting to non-standard Perl
modules. You can run it to see a demo, and then just replace the demo
code with your code. It's been tested on aix, linux, sunos, darwin
(MacOS X), and ActiveState Perl (for Win32). It seems to work exactly
the same on all platforms except that restoreCursorPo sition() didn't
seem to work on MacOS X. In order to make my code support all those
platforms, I had to check to see what OS it was running on, and then
carry out the special case for that OS. As a result, my code is quite
lengthy, but it works.

To do what you want to do, I recommend removing the lines after
"package main;" and replacing them with:

$| = 1; # autoflush
PortableReadKey ::getKeyInit();

while (1) {
my $key = PortableReadKey ::getKeyNonBloc king();

if (defined $key) {
print "you've pressed: $key\n";
}
else {
print"Continuin g to loop...\n";
sleep 1; # delay the loop incase you need to control-c out.
}
}

I included the full program down below. I suggest you try it to
get a feel of what it can do. Feel free to use it, study it, and/or
modify it (in other words, this program is in the public domain). The
code I mentioned is included below. Once you test it out a few times,
you can put the code above into the "package main" section of the code
below.

Got it? Let me know if you don't quite understand.

I hope this helps.

-- Jean-Luc
And here is the code:

#!/usr/bin/perl -w

use strict;

package PortableReadKey ;

my $type;
my @bsd = qw(darwin);
my @non_bsd = qw(aix linux sunos);

use IO::Select;
my $s = IO::Select->new();
$s->add(\*STDIN) ;

my ($old_mode, $input_con, $output_con); # for win32
my ($saved_x, $saved_y) = (0,0); # for win32

sub getKeyInit {
if ($^O eq "MSWin32") {
unless (eval "require Win32::Console" ) {
die "Cannot find module Win32::Console" ;
}
$type = "win32";
$input_con = new Win32::Console(
Win32::Console: :STD_INPUT_HAND LE() );
$old_mode = $input_con->Mode();
$output_con = new Win32::Console(
Win32::Console: :STD_OUTPUT_HAN DLE() );
} elsif (eval "require Term::ReadKey") {
# print "\nUsing Term::ReadKey.. .\n";
$type = "ReadKey";
} elsif (grep {$^O eq $_} @bsd) { $type = "bsd";
} elsif (grep {$^O eq $_} @non_bsd) { $type = "non_bsd";
} else {
print "Could not determinte type for \"$^O\".\nExiti ng...\n";
exit(1);
}
}

sub turnOffEcho {
my $break_out = 0;
if ($type eq "ReadKey") {
Term::ReadKey:: ReadMode('cbrea k');
} elsif ($type eq "bsd") {
# No idea if this works:
system "stty cbreak -echo </dev/tty >/dev/tty 2>&1";
$break_out = 1 if $?; # if true, user most likely hit CTRL-C
} elsif ($type eq "non_bsd") {
system("stty", '-echo', '-icanon', 'eol', "\001");
$break_out = 1 if $?; # if true, user most likely hit CTRL-C
} elsif ($type eq "win32") {
$input_con->Mode(
~(Win32::Consol e::ENABLE_LINE_ INPUT()
| Win32::Console: :ENABLE_ECHO_IN PUT())
& $old_mode );
} else { die "\nsub getKeyInit() was never called";
}
if ($break_out) {
PortableReadKey ::turnOnEcho();
print "\n";
if (exists $SIG{INT} && $SIG{INT}) {
&{$SIG{INT}} ;
} else {
exit(1);
}
}
}

sub turnOnEcho {
my $break_out = 0;
if ($type eq "ReadKey") {
Term::ReadKey:: ReadMode('norma l');
} elsif ($type eq "bsd") {
# No idea if this works:
system "stty -cbreak echo </dev/tty >/dev/tty 2>&1";
$break_out = 1 if $?; # if true, user most likely hit CTRL-C
} elsif ($type eq "non_bsd") {
system("stty", 'echo', 'icanon', 'eol', '^@'); # ASCII null
$break_out = 1 if $?; # if true, user most likely hit CTRL-C
} elsif ($type eq "win32") { $input_con->Mode( $old_mode);
} else { die "\nsub getKeyInit() was never called";
}
if ($break_out) {
print "\n";
if (exists $SIG{INT} && $SIG{INT}) {
&{$SIG{INT}} ;

} else {
exit(1);
}
}
}

# The subroutine PortableReadKey ::turnOffEcho() MUST
# be called before getKeyBlocking( ) for it to function
# correctly.
sub getKeyBlocking {
my $key;
if ($type eq "ReadKey") {
# For some reason this messes up when ENTER
# is pressed under MSWin32:
$key = Term::ReadKey:: ReadKey(0);
} elsif ($type eq "bsd" or $type eq "non_bsd") { $key =
getc(STDIN);
} elsif ($type eq "win32") {
$key = $input_con->InputChar(1) ;
$key = "\n" if defined $key and ord($key) == 13;
} else { die "\nsub getKeyInit() was never called";
} return $key;
}

# The subroutine PortableReadKey ::turnOffEcho() MUST
# be called before getKeyNonBlocki ng() for it to function
# correctly.
sub getKeyNonBlocki ng {
my $key;
if ($type eq "ReadKey") {
$key = Term::ReadKey:: ReadKey(-1);
} elsif ($type eq "bsd" or $type eq "non_bsd") {
sysread(STDIN,$ key,1) if $s->can_read(0);
} elsif ($type eq "win32") {
while ($input_con->GetEvents()) {
my @event = $input_con->Input();
# print " \@event = (@event)\n";
if (defined $event[0] and $event[0] == 1
and $event[1] and $event[5]) {
$key = chr($event[5]);
$key = "\n" if defined $key and ord($key) == 13;
return $key;
}
}
} else {
die "\nsub getKeyInit() was never called";
}
return $key;
}

sub clearScreen {
if ($type eq "win32") {
$output_con->Cls();
} elsif ($type eq "bsd" or $type eq "non_bsd"
or $type eq "ReadKey") {
print "\e[2J"; # clear screen and move cursor
# to home position
print "\e[H"; # move cursor to home position
# (necessary for some systems)
} else { die "\nsub getKeyInit() was never called";
}
}

sub moveCursorAbsol ute {
my ($x, $y) = @_;
# Note that negative values may not give
# the desired results.
if ($type eq "win32") {
$output_con->Cursor($x, $y);
} elsif ($type eq "bsd" or $type eq "non_bsd"
or $type eq "ReadKey") {
printf("\e[%d;%dH", $y, $x);
} else { die "\nsub getKeyInit() was never called";
}
}

sub moveCursorRelat ive {
my ($x, $y) = @_;
if ($type eq "win32") {
my ($current_x, $current_y) = $output_con->Cursor();
# Note that negative values may not give
# the desired results.
$x += $current_x;
$y += $current_y;
$x = 0 if $x < 0;
$y = 0 if $y < 0;
$output_con->Cursor($x, $y);
} elsif ($type eq "bsd" or $type eq "non_bsd"
or $type eq "ReadKey") {
if ($x > 0) { # Go right:
printf("\e[%dC", $x);
} elsif ($x < 0) { # Go left:
printf("\e[%dD", -$x);
}
if ($y > 0) { # Go down:
printf("\e[%dB", $y);
} elsif ($y < 0) { # Go up:
printf("\e[%dA", -$y);
}
} else { die "\nsub getKeyInit() was never called";
}
}

sub saveCursorPosit ion {
if ($type eq "win32") {
($saved_x, $saved_y) = $output_con->Cursor();
} elsif ($type eq "bsd" or $type eq "non_bsd"
or $type eq "ReadKey") {
print "\e[s";
} else { die "\nsub getKeyInit() was never called";
}
}

sub restoreCursorPo sition {
if ($type eq "win32") {
$output_con->Cursor($saved_ x, $saved_y);
} elsif ($type eq "bsd" or $type eq "non_bsd"
or $type eq "ReadKey") {
print "\e[u";
} else { die "\nsub getKeyInit() was never called";
}
}
package main;

$| = 1; # autoflush

PortableReadKey ::getKeyInit();

PortableReadKey ::clearScreen() ;
my $key;
PortableReadKey ::turnOffEcho() ;
print "Press a key for an example of a blocking read...\n";
$key = PortableReadKey ::getKeyBlockin g();
# print "ASCII = ", ord($key), "\n";
$key = "[ENTER]" if $key eq "\n";
$key = "[ESCAPE]" if $key eq "\e";
$key = "[BACKSPACE]"
if $key eq "\b" or $key eq "\cH" or $key eq "\c?";
# Now check for CTRL combinations:
eval qq/\$key = "[CTRL-$_]"
if \$key eq "\\c$_"/ for ('A' .. 'Z');
print "\n";
print "Good! You pressed \"$key\"!\n\ n";
my $num_secs = 30;
print <<"END_INSTRUCT IONS";
Now, after you press ENTER, you can type for the next
$num_secs seconds. A '.' will be printed every second.
Any key you type will show up as the '*' symbol.
This is an example of a non-blocking read.
END_INSTRUCTION S
PortableReadKey ::moveCursorAbs olute(3,10);
print "Press ENTER when ready.";
# Warning on win32 systems: when the echo is turned off,
# reading from <STDIN> won't work, even to read
# an ENTER keypress.
PortableReadKey ::turnOnEcho();
<STDIN>;
print "\n";
print "Now, type!";
PortableReadKey ::moveCursorRel ative(-4,1);
PortableReadKey ::turnOffEcho() ;
my $input = "";
my ($start_time, $current_time);
$start_time = $current_time = time;
print ".";
while (time - $start_time < $num_secs) {
PortableReadKey ::turnOffEcho() ;
$current_time != time and ($current_time = time and print ".");
my $key = PortableReadKey ::getKeyNonBloc king();
$input .= $key, print "*" if defined $key;
}
PortableReadKey ::turnOnEcho();

print qq(\n\nYou typed "$input".\n );

print "Now for examples of cursor positioning.\n" ;
print "Hit ENTER to continue."; <STDIN>;

PortableReadKey ::clearScreen() ;
PortableReadKey ::moveCursorAbs olute(10,10);
print "Now at (10,10). (Press ENTER)";
PortableReadKey ::saveCursorPos ition();
<STDIN>;
PortableReadKey ::moveCursorAbs olute(5,5);
print "Now at (5,5). (Press ENTER)";
<STDIN>;
PortableReadKey ::restoreCursor Position();
print "Back to previous position!\n\n";

__END__
Jul 19 '05 #2

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
3432
by: Patricio Stegmann | last post by:
Hello, I'm trying to capture all keyboard events from some different web page layouts: framesets with different stuff, like flash or whatever ! The problem I am getting is that only focused documents get those events, and even worse, if an "object" like a swf clip gets the focus, all keyboard events are only sent to that object. What I would like is to be able to get the events to a particular script/function so I can handle them...
3
2246
by: srbstar | last post by:
Can a program detect if it's stdin is coming from keyboard input vs. being redirected from a file? If it's from a file, I want to fputs() the text. But if it's from the keyboard, I won't (don't want it typed, then fputs()'d. SRB
0
6747
by: rs | last post by:
Hi guys, I am trying to read from a USB keyboard using vb.net and HID classes. the USB keyboard is not my primary keyboard. I have a ps2 keyboard connected and is detected in device manager as my keyboard. the USB keyboard is detected as HID keyboard device. the program finds the keyboard if it is attached. and I am getting valid handles. however, everytime I use the readfile function I am getting "object reference not set to an instant...
2
8779
by: rs | last post by:
Hi guys, I am trying to read from a USB keyboard using vb.net and HID classes. the USB keyboard is not my primary keyboard. I have a ps2 keyboard connected and is detected in device manager as my keyboard. the USB keyboard is detected as HID keyboard device. the program finds the keyboard if it is attached. and I am getting valid handles. however, everytime I use the readfile function I am getting "object reference not set to an instant...
6
2244
by: Steve | last post by:
Hi All I have an on-screen keyboard within a POS program I have written in VB.net 2005, for touch screen computers I have it set to 'always on top' so the user can move the cursor to different text boxes and type using the on-screen keyboard The keyboard launches via the mouseclick event for any text box If another form is launched, with the onscreen keyboard still visible, the
3
3011
by: NaN | last post by:
I've been trying to use _kbhit() but it didn't do what I thought it would from books, "Detects whether a keypress is available for reading." Herbert Schildt says, "If the user has pressed a key, this function returns true(non-0), but does not read the character. If no keystroke is pending, kbhit() returns false (0)." Here is the test code,
8
5313
by: BD | last post by:
How can I duplicate the behavior of the operating system shortcut keys in my application? For example, my windows form has 5 controls (textboxes), the operating system will pickup which control has the focus and handle ctrl-c, ctrl-v, or any other shortcuts. I have the same shortcuts working in my app, but have not determined how to find out which control has focus. Would I set up a loop or code for each control at form level. Any help...
5
2837
by: =?Utf-8?B?U2llZ2ZyaWVkIEhlaW50emU=?= | last post by:
I need to redundantly write C++ and C# programs to (1) determine the input language (german, french, english...) (2) determine changes in the input language (preferably a delegate rather than polling!) Can anyone guide me to the proper functions to call? Thanks, siegfried
5
7937
by: bint | last post by:
Please help. Trying to just get simple keyboard input from a C program. Ideally would like to be able to just press a key without having to press return, but at this point I don't care anymore. I can get one character using getchar(), but I have to press return. When I do, it completely skips over my second call to getchar(). Why? How do I make successive calls that read the keyboard? c = getchar(); if (c == 'y') {
0
9881
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9727
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10645
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10706
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10331
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7880
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7053
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5718
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
3
3160
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.