playingwithbots has asked for the wisdom of the Perl Monks concerning the following question:

I was trying to write some code to do some cursor control and wanted to read single characters. I've tried everything but Win32::Console seems not to work. I'm using ActiveState 5.8.0/806. Here is the code that I think should work. It should read characters and echo "*" characters as each is read. What happens is that I enter characters and get no echo and also get no "*" until I hit "enter". I then get the "*"'s echo'ed and it has read what I entered.

use Win32::Console ; $cons = new Win32::Console(STD_INPUT_HANDLE) || die "Can't open new co +nsole\n"; $oldMode = $cons->Mode ; $cons->Mode(~(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT) & $oldMode ); while (1) { $char = $cons->InputChar(1) ; last if ord $char == 13 ; print '*' ; $password .= $char ; } print "\nPassword was $password\n" ; $cons->Mode($oldMode) ;

Any help is appreciated.

Replies are listed 'Best First'.
Re: Win32::Console Modes not Working on XP
by BrowserUk (Patriarch) on Jul 18, 2003 at 20:06 UTC

    Disabling buffering on STDOUT seems to do the trick. Using strict and lexicals does hurt either.

    #! perl -sw use strict; use Win32::Console ; $|++; # Disable buffering on STDOUT. my $password; my $cons = new Win32::Console(STD_INPUT_HANDLE) || die "Can't open new + console\n"; my $oldMode = $cons->Mode ; $cons->Mode(~(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT) & $oldMode ); while (1) { my $char = $cons->InputChar(1) ; last if ord $char == 13 ; print '*' ; $password .= $char ; } print "\nPassword was $password\n" ; $cons->Mode($oldMode) ; __END__ P:\test>junk **** Password was fred

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller

Re: Win32::Console Modes not Working on XP
by NetWallah (Canon) on Jul 18, 2003 at 21:43 UTC
    In addition to BrowserUK's suggestion of $|++; # Disable buffering on STDOUT. , the order of the mode change seems significant.

    This works:

    use Win32::Console ; $cons = new Win32::Console(STD_INPUT_HANDLE) || die "Can't open new co +nsole\n"; $|++; # Disable buffering on STDOUT. ConsoleMode_AND_WITH (~(ENABLE_ECHO_INPUT));# ConsoleMode_AND_WITH ( ~(ENABLE_LINE_INPUT));# while (1) { $char = $cons->InputChar(1) ; last if ord $char == 13 ; print '*' ; $password .= $char ; } print "\nPassword was $password\n" ; $cons->Mode($oldMode) ; sub ConsoleMode_AND_WITH(){ my $o = $cons->Mode(); $cons->Mode($o & shift); print "--Mode change from $o\[" . unpack(q(H2),chr($o)) . " ] to " . $cons->Mode() . "[". unpack(q(H2),chr($cons->Mode())) . "]\n"; }
    Changing the order of ConsoleMode_AND_WITH calls produces the "Requires ENTER key" behaviour before anything shows up.

    MS documentation says ENABLE_LINE_INPUT OFF should ignore the setting of ENABLE_ECHO_INPUT. But this is probably getting off-topic. Anyway, the code above does what you require, as does Browser's.