win api readConsole()

我正在尝试使用Win API ReadConsole(...) ,我想传递一个分隔字符来暂停控制台的input。 下面的代码工作,但它只停止阅读\r\n上的input。 我想停止阅读'.'上的控制台input'.' 例如。

 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分钟试图弄清楚,并最终有一些东西。

那个dwCtrlWakeupMaskCONSOLE_READCONSOLE_CONTROL记录的很不好。 MSDN说:“一个用户定义的控制字符,用来表示读取完成。”,但为什么它被称为mask ? 为什么它是一个ULONG而不是TCHAR或类似的东西? 我试着喂它的字符和wchars什么都没有发生,所以一定要有更多的故事。

我去网上搜索这个特定的变量,并找到了这个链接: https : //groups.google.com/forum/#!topic /golang-codereviews/ KSp37ITmcUg这是一个随机的Go库编码器寻求帮助,答案是该标签是1 << '\t' 。 我尝试了,它的工作原理!

因此,对于未来的Web搜索者, dwCtrlWakeupMask是ASCII控制字符的一个位掩码,它将导致ReadConsole返回。 你可以| 一样多的1 << ctrl_char …只要你喜欢…但它不能是任意的字符,因为它是一个32位值的位掩码,只有字符1-31(含)是可能的(这组btw被称为控制字符,它包括诸如tab,backspace,bell之类的东西;本身不代表可打印字符的东西)。

因此,这个面具:

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

当选项卡( \t )或退格键( 0x08 )被按下时,将导致ReadConsole返回。

ctrl+ some_ascii_value表示的字符是英文字母表中从a == 1开始的那个字母的编号。所以, ctrl+d4 ,而ctrl+z26

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

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

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

我相信这个论点的意义在于允许在处理的输入模式下更容易的制表符完成; 否则,你将不得不关闭处理的输入和处理键一个一个来做到这一点。 现在你不必…尽管tbh,我仍然喜欢把我的输入与ReadConsoleInput交互式的程序,因为你得到更好的控制这一切。

但是,有很多其他的方式来做你想要的 – 并使用. 作为一个分隔符在这里是不可能的,因为它有一个> = 32的值,所以你需要自己做…理解这个对我来说是有意思的,而且网上有稀缺的资源,所以我写这个仅供将来参考。

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

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

我通常喜欢MSDN文档,但国际海事组织,他们完全放弃了解释这个参数的球!

你会发现这个代码荒谬。 这很可能是唯一的方法来做到这一点。 如果你不得不适应稍后使用ReadFile,那么这是唯一不会消耗更多输入的方法。

大多数情况下,你根本不需要ReadConsole就可以在标准输入句柄上使用ReadFile,但是我离题了。

 char *cInptr = cIn; do { bool read = ReadConsole(hFile, cInptr, sizeof(TCHAR), &charsRead, &cReadControl); if (read) cInptr += charsRead; } while (read && charsRead > 0 && cInptr[-1] && cInptr[-1] != '.'); 

由于偏执,我可能在循环中有太多的测试。 我不倾向于查找所有的谓词来确定ReadConsole的合同隐含的内容。