win api readConsole()

dma*_*ect 4 c++ windows winapi

我正在尝试使用Win API ReadConsole(...),我想传递一个分隔符char来暂停来自控制台的输入.以下代码有效,但它只停止读取输入\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';
}
Run Code Online (Sandbox Code Playgroud)

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

谢谢.

Ada*_*ppe 9

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

dwCtrlWakeupMask是非常糟糕的记录CONSOLE_READCONSOLE_CONTROL.MSDN说"用户定义的控制字符,用于表示读取已完成.",但为什么要调用它mask?为什么它是一个ULONG而不是一个TCHAR或类似的东西?我试着喂它的角色和wchars而且什么也没发生,所以故事必须有更多.

我上网搜索该特定变量,发现此链接:https://groups.google.com/forum/#!topic/golang-codereviews / KSp37ITmcUg这是一个随机Go库编码器寻求帮助,答案是那个标签是1 << '\t'.我试过了,它的确有效!

因此,对于未来的网络搜索者来说,dwCtrlWakeupMask是一个ASCII控制字符的位掩码,它将导致ReadConsole返回.您可以|在一起使用多个1 << ctrl_chars ...但它不能是任意字符,因为它是32位值的位掩码,只有字符1-31(包括)是可能的(此组btw称为控制字符,它包括tab,backspace,bell等内容;本身不代表可打印字符的东西.

这样,这个面具:

cReadControl.dwCtrlWakeupMask = (1 << '\t') | (1 << 0x08);
Run Code Online (Sandbox Code Playgroud)

ReadConsole当tab(\t)或0x08按下退格()时会导致返回.

通过所表示的字符ctrl+ some_ascii_value是英语字母表中的信,起始于一个== 1的数目所以,ctrl+d4ctrl+z26.

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

cReadControl.dwCtrlWakeupMask = (1 << 4) | (1 << 26);
Run Code Online (Sandbox Code Playgroud)

请注意,read当用户点击时,Linux终端驱动程序也会返回,ctrl+d因此这可能是一个很好的兼容性问题.

我相信这个论点的重点是允许在处理输入模式下更容易完成制表符; 否则,您必须关闭已处理的输入并逐个处理密钥才能执行此操作.现在你没有......虽然tbh,我仍然更喜欢把我的输入ReadConsoleInput用于交互式程序,因为你可以更好地控制它.

但是,虽然有很多其他方法可以做你想要的 - 并且.在这里使用分隔符是不可能的,因为它的值> = 32,所以你需要自己做...理解它的作用是有趣的无论如何,网上有稀缺的资源,所以我写这篇文章只是为了将来的参考.

请注意,这似乎不起作用,wineconsole所以请确保您在一个真正的Windows框上测试它.

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

我通常喜欢MSDN文档但IMO在解释这个参数时完全放弃了它!