Has anyone come up with a solution for this? I'm not sure why it should be so difficult.
Thanks,
Norm
Read one keypress at a time from STDIN [UPDATE]
Moderator: General Moderators
Read one keypress at a time from STDIN [UPDATE]
Last edited by npeelman on Sun Dec 19, 2004 9:56 am, edited 1 time in total.
Re: Read one keypress at a time from STDIN without <retur
Because php uses stream oriented IO. You might want to experiment with ncurses extension, particularly with [php_man]ncurses_cbreak[/php_man] function.npeelman wrote:I'm not sure why it should be so difficult.
Re: Read one keypress at a time from STDIN without <retur
Currently working on a solution to this, actually having some success. Details to follow (maybe).Weirdan wrote:Because php uses stream oriented IO. You might want to experiment with ncurses extension, particularly with [php_man]ncurses_cbreak[/php_man] function.npeelman wrote:I'm not sure why it should be so difficult.
Norm
Re: Read one keypress at a time from STDIN [UPDATE!]
Ok,npeelman wrote:Currently working on a solution to this, actually having some success. Details to follow (maybe).Weirdan wrote:Because php uses stream oriented IO. You might want to experiment with ncurses extension, particularly with [php_man]ncurses_cbreak[/php_man] function.npeelman wrote:I'm not sure why it should be so difficult.
Norm
Current point of solution. There seems to be three options:
1) ncurses/ or derivative (Windows compatible ???)
2) external DOS commands
3) system calls (win32.api via FFI - http://pecl.php.net/package/ffi )
#1, i'm really not into/up to speed 'building/makeing' on Win32 or Linux so that's out for me.
#2 is doable to a point (and actually not -much- different from #3.
#3 is working now with a few quirks.
Currently, I can receive keystrokes from the keyboard one keypress at a time, BUT I am receiving ALL keypresses system wide (for any/all applications). I am getting hung up on the window active/focus functions. If this would be the only program running I guess it's ok, if you would be using other programs at the same time then anytime this program is expecting keyboard input it would receive keystrokes while they are typed in the other applications. If anyone has any knowlege of working with PHP/Win32 api/FFI functions it would be helpfull. And if anyone is interested in the details they can email me at npeelman@cfl.rr.com
Norm
Re: Read one keypress at a time from STDIN [UPDATE!]
Actually yesnpeelman wrote: 1) ncurses/ or derivative (Windows compatible ???)
Post you code, we might be able to help you. To my understanding you should be able to use functions of win32 console subsystem (e.g. ReadConsoleInputA) without much problems.3) system calls (win32.api via FFI - http://pecl.php.net/package/ffi )
<...skipped...>
Currently, I can receive keystrokes from the keyboard one keypress at a time, BUT I am receiving ALL keypresses system wide (for any/all applications).
Re: Read one keypress at a time from STDIN [UPDATE!]
I was hoping to come up with a simple solution that would be PHP only, or in otherwords PHP and something that people already have on their computer (namely the OS). My real problem at this point is my knowlege of C/C++ style programming conventions and how they relate to the FFI package. I'm not sure if the FFI package supports ALL C/C++ variable types and I would have to create alot of structs to work with the 'window'ing message que's, etc. I was hoping that I could simply pay attention to whether my 'shell' window had focus or not and only process the keystrokes if it does, but that's not quite working either.Weirdan wrote:Actually yesnpeelman wrote: 1) ncurses/ or derivative (Windows compatible ???)Cygwin compatible.
Post you code, we might be able to help you. To my understanding you should be able to use functions of win32 console subsystem (e.g. ReadConsoleInputA) without much problems.3) system calls (win32.api via FFI - http://pecl.php.net/package/ffi )
<...skipped...>
Currently, I can receive keystrokes from the keyboard one keypress at a time, BUT I am receiving ALL keypresses system wide (for any/all applications).
I'll post some code this evening when i've had a chance to clran it up a bit. It's a mess right now.
Norm
Re: Read one keypress at a time from STDIN [UPDATE!]
npeelman wrote:I was hoping to come up with a simple solution that would be PHP only, or in otherwords PHP and something that people already have on their computer (namely the OS). My real problem at this point is my knowlege of C/C++ style programming conventions and how they relate to the FFI package. I'm not sure if the FFI package supports ALL C/C++ variable types and I would have to create alot of structs to work with the 'window'ing message que's, etc. I was hoping that I could simply pay attention to whether my 'shell' window had focus or not and only process the keystrokes if it does, but that's not quite working either.Weirdan wrote:Actually yesnpeelman wrote: 1) ncurses/ or derivative (Windows compatible ???)Cygwin compatible.
Post you code, we might be able to help you. To my understanding you should be able to use functions of win32 console subsystem (e.g. ReadConsoleInputA) without much problems.3) system calls (win32.api via FFI - http://pecl.php.net/package/ffi )
<...skipped...>
Currently, I can receive keystrokes from the keyboard one keypress at a time, BUT I am receiving ALL keypresses system wide (for any/all applications).
I'll post some code this evening when i've had a chance to clran it up a bit. It's a mess right now.
Norm
Code: Select all
<?php
//CONSTANTS
$win32 = <<<EOD
[lib='user32.dll'] int BlockInput(int fBlockIt);
[lib='user32.dll'] int BringWindowToTop(int hWnd);
[lib='user32.dll'] int EnableWindow(int hWnd, int bEnable);
[lib='user32.dll'] int GetShellWindow();
[lib='user32.dll'] int GetFocus();
[lib='user32.dll'] int GetForegroundWindow();
[lib='user32.dll'] int GetActiveWindow(int hWnd);
[lib='user32.dll'] int GetAsyncKeyState(int v_key);
[lib='user32.dll'] int GetKeyState(int v_key);
[lib='user32.dll'] int GetKeyNameText(int lparam, int *lpstring, int nsize);
[lib='user32.dll'] int GetKeyboardState(char* lpkeystate);
[lib='user32.dll'] int GetTopWindow(int hWnd);
[lib='user32.dll'] int LockSetForegroundWindow(int uLockCode);
[lib='user32.dll'] int SetForegroundWindow(int hWnd);
[lib='user32.dll'] int SetFocus(int hWnd);
[lib='kernel32.dll'] int GetLastError();
EOD;
/*
GetKeyState -> For A-Z,a-z, and 0-9 set v_key == ascii-code for desired key.
else use virtual key code
*/
$key_in = 0;
$key = '';
$kb_array = str_repeat('0',256);
$kb_array2 = $kb_array;
//$accept = "ABCDEFGHIJKLMNOPQRSTUVWXYZ ".chr(13).chr(27);
// $accept = all key codes
for($loop = 0; $loop <= 256; $loop++)
{
@$accept .= chr($loop);
}
$kb_focus = 0;
$win_handle = 0;
$foreground_handle = 0;
$console32 = new ffi($win32);
$win_handle = $console32->GetShellWindow();
if ($win_handle == NULL)
{
echo "Could not get handle to shell!\n\r";
exit;
}
else
{
echo "Got handle to shell window!\n\r";
$old_focus = $console32->GetActiveWindow($win_handle);
if ($old_focus == NULL)
{
echo "win_handle focus not set!\n\r";
//exit;
}
if ($console32->BringWindowToTop($win_handle) != 0)
{
echo "Window brought to top (should be active)\n\r";
$top_handle = $console32->GetTopWindow(NULL);
}
else
{
echo "Window not brought to top!\n\r";
exit;
}
if ($console32->SetForegroundWindow($win_handle) != 0)
{
echo "Window is now foregound window!\n\r";
$foreground_handle = $console32->GetForegroundWindow();
if ($foreground_handle == NULL)
{
echo "Could not get handle to foreground window!\n\r";
exit;
}
else
{
echo "Got handle to foreground window!\n\r";
}
}
}
if ($win_handle != $foreground_handle)
{
echo "Not the same handle!\n\r";
//exit;
}
else
{
echo "The same handle!\n\r";
$go = 1;
}
echo "Window handles checked OK! \n\r";
//while ($win_handle == $console32->GetForegroundWindow())
//{
// echo "Focused!\n\r";
// sleep(1);
//}
//echo "Not focused!";
//exit;
//$go = 1;
$char = 0;
$tmp = '';
$extended = 0;
if ($go = 1)
{
echo "Will accept everything, even mouse - ESC to quit\n\r";
while(true)
{
/* this really doesn't work right
if ($win_handle == $console32->GetForegroundWindow())
{
echo "Has focus!\n\r";
}
else
{
echo "Lost focus!\n\r";
}
*/
$key_in = $console32->GetAsyncKeyState(ord($accept[$char]));
if ($key_in != 0)
{
// we have a key press
if ($char >= 112 && $char <= 124)
{
echo "\n\rFUNCTION KEY\n\r";
continue;
}
$key = $accept[$char];
/* alternate Fkey code
if ($key >= 'p' && $key <= '{')
{
$extended = 1;
}
if ($extended == 1)
{
echo "\n\rFunction key ";
switch (ord($key))
{
case 112:
{
echo 'F1';
break;
}
case 113:
{
echo 'F2';
break;
}
default:
{
echo 'F?';
break;
}
}
echo " pressed!\n\r";
$extended = 0;
}
*/
if ($key == chr(27))
{
echo "\n\r 'ESC' was pressed!\n\r";
echo "\n\r\n\rYou typed -> \n\r $tmp";
exit;
}
else
{
echo $key;
//echo $key.ord($key);
$tmp .= $key;
}
}
if ($char == (strlen($accept) - 1))
{
$char = -1;
}
usleep(500);
$char++;
}
}
/* this sortof works - keystate rotates through all values
$key_test = $console32->GetKeyState(65);
echo "The 'A' key is ";
switch ($key_test)
{
case -127:
{
echo "pressed";
break;
}
case -128:
{
echo "pressed w/shift";
break;
}
default:
{
echo "up";
}
}
*/
/* this just doesn't work at all as $kb_array never gets updated.
for($loop = 0; $loop <= 10000; $loop++)
{
$result = $console32->GetKeyboardState($kb_array);
echo "$kb_array \n\r";
echo "\n\rResult = $result\n\r";
echo $console32->GetLastError()."\n\r";
for($loop2 = 0; $loop2 <= 255; $loop2++)
{
if ($kb_array[$loop2] != 0)
{
echo "Key pressed!";
exit;
}
else
{
echo ord($kb_array[$loop2])."\n\r";
}
}
usleep(10000);
}
*/
?>