c++ - 赢 api readConsole()

标签 c++ windows winapi

我正在尝试使用 Win API ReadConsole(...),我想传入一个分隔符字符以停止来自控制台的输入。 下面的代码有效,但它只会停止读取 \r\n 上的输入。 例如,我希望它停止读取 '.' 上的控制台输入。

void read(char *cIn, char delim)
{
    HANDLE hFile;
    DWORD charsRead;
    DWORD charsToRead = MAX_PATH;
    CONSOLE_READCONSOLE_CONTROL cReadControl;

    cReadControl.nLength = sizeof(CONSOLE_READCONSOLE_CONTROL);
    cReadControl.nInitialChars = 0;
    cReadControl.dwCtrlWakeupMask = delim;
    cReadControl.dwControlKeyState = NULL;

    DWORD lpMode;



//    char cIn[MAX_PATH];    //-- buffer to hold data from the console

    hFile = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
                    FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
                    OPEN_EXISTING, 0, NULL);

    GetConsoleMode(hFile,&lpMode);
//    lpMode &= ~ENABLE_LINE_INPUT;   //-- turns off this flag
//    SetConsoleMode(hFile, lpMode);  //-- set the mode with the new flag off

    bool read = ReadConsole(hFile, cIn, charsToRead * sizeof(TCHAR), &charsRead, &cReadControl);
    cIn[charsRead - 2] = '\0';
}

我知道还有其他简单的方法可以做到这一点,但我只是想了解一些 win api 函数以及如何使用它们。

谢谢。

最佳答案

我看到这个问题并认为它是微不足道的,但花了最后 30 分钟试图弄明白并最终得到了一些东西。

那个dwCtrlWakeupMask CONSOLE_READCONSOLE_CONTROL 中的记录很差. MSDN 说“A user-defined control character used to signal that the read is complete.”,但为什么叫它 mask ?为什么是ULONG而不是 TCHAR或类似的东西?我试着给它喂 chars 和 wchars 但什么也没发生,所以一定有更多的故事。

我上网搜索那个特定变量并找到了这个链接: https://groups.google.com/forum/#!topic/golang-codereviews/KSp37ITmcUg这是一个随机的 Go 库编码器寻求帮助,答案是选项卡是 1 << '\t' .我试过了,很有效!

因此,对于 future 的网络搜索者,dwCtrlWakeupMask是将导致 ReadConsole 的 ASCII 控制字符的位掩码返回。你可以|一起尽可能多1 << ctrl_char随心所欲...但它不能是任意字符,因为它是 32 位值的位掩码,只有字符 1-31(含)是可能的(顺便说一下,这个组称为控制字符,它包括制表符之类的东西, backspace, bell; 本身不代表可打印字符的东西)。

因此,这个面具:

cReadControl.dwCtrlWakeupMask = (1 << '\t') | (1 << 0x08);

会导致ReadConsole在按下制表符 (\t) 或退格键 (0x08) 时返回。

ctrl+ some_ascii_value代表的字符是英文字母表中该字母的编号,从 a == 1 开始。因此,ctrl+d4 , 和 ctrl+z26 .

因此,这将在用户点击 ctrl+d 时返回或 ctrl+z :

cReadControl.dwCtrlWakeupMask = (1 << 4) | (1 << 26);

请注意,Linux 终端驱动程序也会在 read 上返回当用户点击 ctrl+d所以这可能是一个很好的兼容性。

我相信这个论点的重点是允许在处理输入模式下更容易完成制表符;否则,您必须关闭已处理的输入并一个一个地处理 key 才能做到这一点。现在你不必......虽然说实话,我仍然更喜欢用 ReadConsoleInput 来接受我的意见。用于交互式程序,因为您可以更好地控制它。

但是虽然有很多其他方法可以做你想做的事 - 并使用 .因为分隔符在这里是不可能的,因为它的值> = 32,所以你需要自己做......无论如何了解它的作用对我来说很有趣,而且网络上资源稀缺所以我正在写这个仅供将来引用。

请注意,这在 wineconsole 中似乎不起作用所以请确保您在真正的 Windows 机器上进行测试。

现在,dwControlKeyState实际上是由函数设置的。您传入的值将被忽略(至少据我所知),但是您可以在函数返回时检查它是否有给定的标志。因此,例如,在调用 ReadConsole 之后并按下键,如果你的 numlock 是打开的,它将是 32。如果 numlock 已打开并且您按下 shift+tab(并已打开 numlock),则为 48。所以你在函数返回后测试它。

我通常喜欢 MSDN 文档,但 IMO 他们在解释这个参数时完全失误了!

关于c++ - 赢 api readConsole(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43836040/

相关文章:

c++ - 在 Windows C++ 应用程序中获取主线程的控制

c++ - 在编写 Windows 桌面应用程序时,我应该在哪里跟踪我的窗口句柄?

windows - 在 Windows 上运行 zopeskel 后缺少本地命令

windows - 如何从 ruby​​ 获取 %USERPROFILE%?

java - 如何在 Torcs 赛车游戏中安装世界锦标赛的机器人?

c++ - 我可以使用 if (pointer) 而不是 if (pointer != NULL) 吗?

c++ - C WinAPI 和 C++ MFC 资源

c# - 以编程方式启用/禁用设备的 Win32 API 函数

c++ - MinGW64 和 "conflicting declaration of C function int select(...)"

c++ - 如果我在 C++ 中将(指向类 A 的指针)转换为(指向其子类 B 的指针)会发生什么