2

I'm playing around with the D programming language and am wondering how I can grab a character without requiring the user to press enter.

Pseudocode example of what I want:

while(true){
    if(userHasPressedChar()){
        writeln(getChar());
    }
}

In C++ I can use conio.h's "getch()", but i have yet to find anything similar here.

Edit: I am using Windows 7.

Edit 2: I found a solution at this forum, which I could alter for my own use. module main;

import std.stdio;
import core.sys.windows.windows;


void main() {
    auto hCon = GetStdHandle(STD_INPUT_HANDLE);
    FlushConsoleInputBuffer(hCon);
    for(;;) { // in default console mode, ctrl-C will terminate
        INPUT_RECORD inrec;
        DWORD numread;
        while(inrec.EventType != KEY_EVENT) {
            WaitForSingleObject(hCon, INFINITE);
            ReadConsoleInputW(hCon, &inrec, 1, &numread);
        }
        auto keyEvent = inrec.KeyEvent;
        writefln("VK: %x \tChar: %x \tState: %x", 
                 keyEvent.wVirtualKeyCode,
                 keyEvent.UnicodeChar,
                 keyEvent.dwControlKeyState);
    }
}
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
Grisungen
  • 333
  • 2
  • 7
  • 1
    In C(++), this is OS dependent (*conio.h* is not a standard header/library). So which OS are you using? Well, unless D specifies a standard way to do this, but I doubt it. – hyde Sep 24 '14 at 11:40
  • Anyway, presumably D has a way to use C libraries (because *everything* has a way to use C libraries). So just use *conio*. – hyde Sep 24 '14 at 11:42
  • Ah, sorry. I am using windows 7. – Grisungen Sep 24 '14 at 11:42

1 Answers1

3

You can also use various libraries. For example, my terminal.d can do this https://github.com/adamdruppe/arsd/blob/master/terminal.d for windows and linux.

Here's an example file from my book (see my SO profile if you're interested) that demonstrates the usage http://arsdnet.net/dcode/book/chapter_12/07/input.d

import terminal;

void main() {
  auto terminal = Terminal(ConsoleOutputType.linear);
  auto input = RealTimeConsoleInput(&terminal, ConsoleInputFlags.raw);
  terminal.writeln("Press any key to exit");
  auto ch = input.getch();
  terminal.writeln("Bye!");
}

The input object does the necessary conversions to the console mode to turn off line buffering and cleans up after itself. Once you create one, you have methods like input.getch() and input.kbhit() similarly to conio.

My terminal library also offers other event types for things like mouse input if you want to get into more advanced usages.

To compile, just download terminal.d and add it to your command, e.g. dmd yourfile.d terminal.d.

Didaxis
  • 8,486
  • 7
  • 52
  • 89
Adam D. Ruppe
  • 25,382
  • 4
  • 41
  • 60
  • Thanks a lot! If I can only make the clear()-function work now then this'll be perfect :) – Grisungen Sep 24 '14 at 15:11
  • ah yikes, I never implemented it! If you do it, let me know with a github pull request or something. Otherwise I can look into it later and a workaround for now would probably be something like `foreach(i; 0 .. 25) terminal.writeln();` - a bunch of blank lines to push the rest of the stuff up. – Adam D. Ruppe Sep 24 '14 at 15:18