Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
_CONSOLEINPUT is blocking
#1
I can't find it in the documentation, but _CONSOLEINPUT seems blocking (waiting for a key) after the first call.

Code: (Select All)
$Console:Only
Do
  x%% = _ConsoleInput
  Print x%%;
Loop
Will only show one 0 and then waits for a keypress...
Is there any other way to check non-blocking for a key in a $CONSOLE window?
45y and 2M lines of MBASIC>BASICA>QBASIC>QBX>QB64 experience
Reply
#2
For a single keypress?  Not usually.  Why not create a normal program, hide the normal screen, use it to read the keystrokes via INKEY$ or _KEYHIT, and then process it on the visible CONSOLE if you need to do something like that?
Reply
#3
_CONSOLEINPUT is like _MOUSEINPUT, it just shows if new input is available and returns 1 for new keyboard input and 2 for new mouse input, however to retrieve the keyboard input use _CINP and for mouse the respective _MOUSExxx functions. _CONSOLEINPUT blocks until the actual input is retrieved, see example on the _CONSOLEINPUT and _CINP wiki pages.
Reply
#4
I'm with @mdijkens that this seems like a bug. We're currently calling `ReadConsoleInput` which blocks when there are no new events, we can call `GetNumberOfConsoleInputEvents` beforehand to check if it will block or not.
Reply
#5
(01-17-2025, 03:43 PM)RhoSigma Wrote: _CONSOLEINPUT is like _MOUSEINPUT, it just shows if new input is available and returns 1 for new keyboard input and 2 for new mouse input, however to retrieve the keyboard input use _CINP and for mouse the respective _MOUSExxx functions. _CONSOLEINPUT blocks until the actual input is retrieved, see example on the _CONSOLEINPUT and _CINP wiki pages.
Yes, I know, but the point is that it is blocking
Code: (Select All)
Do
  _Limit 10
  x%% = _ConsoleInput
  If x%% = 1 Then
    k& = _CInp
    Print k&;
  Else
    k& = 0
    Print "-";
  End If
Loop

Here I would expect to see --------------------------- all the time except when pressing keys
45y and 2M lines of MBASIC>BASICA>QBASIC>QBX>QB64 experience
Reply
#6
Just as @DSMan195276 mentioned above, it's the used WINAPI function which blocks until at least one input event could be read. I've made the fix suggested by him and will push it for the next release.

However, if you cant wait, here's the fixed version of the C-Function, just look for it in internal\c\libqb.cpp and replace it.

Code: (Select All)
int32 func__getconsoleinput() {
#ifdef QB64_WINDOWS
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    INPUT_RECORD irInputRecord;
    DWORD dwEventsRead, fdwMode, dwMode;
    CONSOLE_SCREEN_BUFFER_INFO cl_bufinfo;

    GetConsoleMode(hStdin, (LPDWORD)&dwMode);
    fdwMode = ENABLE_EXTENDED_FLAGS;
    SetConsoleMode(hStdin, fdwMode);
    fdwMode = dwMode | ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT;
    SetConsoleMode(hStdin, fdwMode);

    DWORD numEvents = 0;
    GetNumberOfConsoleInputEvents(hStdin, &numEvents);
    if (numEvents) {
        ReadConsoleInputA(hStdin, &irInputRecord, 1, &dwEventsRead);
        switch (irInputRecord.EventType) {
        case KEY_EVENT: // keyboard input
            consolekey = irInputRecord.Event.KeyEvent.wVirtualScanCode;
            if (!irInputRecord.Event.KeyEvent.bKeyDown)
                consolekey = -consolekey; // positive/negative return of scan codes.
            return 1;
        case MOUSE_EVENT: // mouse input
            consolemousex = irInputRecord.Event.MouseEvent.dwMousePosition.X + 1;
            consolemousey = irInputRecord.Event.MouseEvent.dwMousePosition.Y - cl_bufinfo.srWindow.Top + 1;
            consolebutton = irInputRecord.Event.MouseEvent.dwButtonState; // button state for all buttons
            // SetConsoleMode(hStdin, dwMode);
            return 2;
        }
    }
#endif
    return 0; // no or unhandled input
}

After that compile the following program and it should print "-" for no input, "M' for mouse input (Quick Edit mode must be off for mouse events (info added to the _CONSOLEINPUT Wiki page)) and the respective scan codes for keyboard input.

Code: (Select All)
$CONSOLE:ONLY

DO
_LIMIT 10
x%% = _CONSOLEINPUT
IF x%% = 1 THEN
k& = _CINP
PRINT k&;
ELSEIF x%% = 2 THEN
k& = 0
PRINT "M";
ELSE
k& = 0
PRINT "-";
END IF
LOOP
Reply
#7
That is great.
I am going to make that change.
Would be nice to have that in next version; waiting for input is easy enough if you still need that
45y and 2M lines of MBASIC>BASICA>QBASIC>QBX>QB64 experience
Reply
#8
I've now also created a cKeyhit that can be used in a console and returns the same keycodes as _KEYHIT 
Code: (Select All)
int32 cKeyhit() {
#ifdef QB64_WINDOWS
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    INPUT_RECORD irInputRecord;
    DWORD dwEventsRead, fdwMode, dwMode;
    CONSOLE_SCREEN_BUFFER_INFO cl_bufinfo;

    GetConsoleMode(hStdin, (LPDWORD)&dwMode);
    fdwMode = ENABLE_EXTENDED_FLAGS;
    SetConsoleMode(hStdin, fdwMode);
    fdwMode = dwMode | ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT;
    SetConsoleMode(hStdin, fdwMode);

    DWORD numEvents = 0;
    GetNumberOfConsoleInputEvents(hStdin, &numEvents);
    if (numEvents) {
        ReadConsoleInputA(hStdin, &irInputRecord, 1, &dwEventsRead);
        switch (irInputRecord.EventType) {
        case KEY_EVENT:
          if (!irInputRecord.Event.KeyEvent.bKeyDown)
            return 0;
          int32 uc = int(wchar_t(irInputRecord.Event.KeyEvent.uChar.UnicodeChar));
if (uc != 0)
return uc;
          switch (irInputRecord.Event.KeyEvent.wVirtualScanCode) {
case 42: return 100304; // LSHIFT
case 54: return 100303; // RSHIFT
case 29: return 100306; // LCTRL (+RCTRL)
case 56: return 100308; // LALT (+RALT)
case 59: return 15104;  // F1
case 60: return 15360;  // F2
case 61: return 15616;  // F3
case 62: return 15872;  // F4
case 63: return 16128;  // F5
case 64: return 16384;  // F6
case 65: return 16640;  // F7
case 66: return 16896;  // F8
case 67: return 17152;  // F9
case 68: return 17408;  // F10
case 87: return 34048;  // F11
case 88: return 34304;  // F12
case 82: return 20992;  // INSERT
case 83: return 21248;  // DELETE
case 71: return 18176;  // HOME
case 79: return 20224;  // END
case 73: return 18688;  // PAGEUP
case 81: return 20736;  // PAGEDOWN
case 75: return 19200;  // LEFT
case 77: return 19712;  // RIGHT
case 72: return 18432;  // UP
case 80: return 20480;  // DOWN
}
return 256 + irInputRecord.Event.KeyEvent.wVirtualScanCode;
        }
    }
#endif
    return 0;
}
(cpp novice)
45y and 2M lines of MBASIC>BASICA>QBASIC>QBX>QB64 experience
Reply
#9
(01-18-2025, 12:24 PM)mdijkens Wrote: I've now also created a cKeyhit that can be used in a console and returns the same keycodes as _KEYHIT 
Code: (Select All)
int32 cKeyhit() {
#ifdef QB64_WINDOWS
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    INPUT_RECORD irInputRecord;
    DWORD dwEventsRead, fdwMode, dwMode;
    CONSOLE_SCREEN_BUFFER_INFO cl_bufinfo;

    GetConsoleMode(hStdin, (LPDWORD)&dwMode);
    fdwMode = ENABLE_EXTENDED_FLAGS;
    SetConsoleMode(hStdin, fdwMode);
    fdwMode = dwMode | ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT;
    SetConsoleMode(hStdin, fdwMode);

    DWORD numEvents = 0;
    GetNumberOfConsoleInputEvents(hStdin, &numEvents);
    if (numEvents) {
        ReadConsoleInputA(hStdin, &irInputRecord, 1, &dwEventsRead);
        switch (irInputRecord.EventType) {
        case KEY_EVENT:
          if (!irInputRecord.Event.KeyEvent.bKeyDown)
            return 0;
          int32 uc = int(wchar_t(irInputRecord.Event.KeyEvent.uChar.UnicodeChar));
if (uc != 0)
return uc;
          switch (irInputRecord.Event.KeyEvent.wVirtualScanCode) {
case 42: return 100304; // LSHIFT
case 54: return 100303; // RSHIFT
case 29: return 100306; // LCTRL (+RCTRL)
case 56: return 100308; // LALT (+RALT)
case 59: return 15104;  // F1
case 60: return 15360;  // F2
case 61: return 15616;  // F3
case 62: return 15872;  // F4
case 63: return 16128;  // F5
case 64: return 16384;  // F6
case 65: return 16640;  // F7
case 66: return 16896;  // F8
case 67: return 17152;  // F9
case 68: return 17408;  // F10
case 87: return 34048;  // F11
case 88: return 34304;  // F12
case 82: return 20992;  // INSERT
case 83: return 21248;  // DELETE
case 71: return 18176;  // HOME
case 79: return 20224;  // END
case 73: return 18688;  // PAGEUP
case 81: return 20736;  // PAGEDOWN
case 75: return 19200;  // LEFT
case 77: return 19712;  // RIGHT
case 72: return 18432;  // UP
case 80: return 20480;  // DOWN
}
return 256 + irInputRecord.Event.KeyEvent.wVirtualScanCode;
        }
    }
#endif
    return 0;
}
(cpp novice)

Well done all on finding the issue and fixing!

Question - how would you use your c stuff in QB64? DECLARELIBRARY ?

Could you post an example for us?
grymmjack (gj!)
GitHubYouTube | Soundcloud | 16colo.rs
Reply
#10
(8 hours ago)grymmjack Wrote: Question - how would you use your c stuff in QB64? DECLARELIBRARY ?

Could you post an example for us?

It's a modification to the C-Function int32 func__getconsoleinput(), just look for it in internal\c\libqb.cpp and replace it and then recompile your code.
Reply




Users browsing this thread: 1 Guest(s)