Windows 当输出与 window 的宽度匹配时,控制台 (conhost) 丢弃新行
Windows Console (conhost) discards newline when output matches witdth of the window
我在 Windows 上有一个 C++ 应用程序,它记录到标准输出(通过使用 WriteConsole 的 Win32 api)。每个日志行都包含一些文本和一个尾随的换行符。问题是:
当日志文本的宽度(不包括换行符)与控制台的宽度匹配时window,换行符将被丢弃。
看这个例子:
有 3 条日志消息:
- 第一个小于控制台宽度
- 第二个与控制台宽度完全匹配
- 第三个比控制台宽度长,因此环绕。
如果我调整 window 的大小,会发生以下情况:
第二行和第三行合并为一行,尽管它们之间打印了一个换行符。我怀疑 windows 为了聪明,在第二条消息之后丢弃了换行符,因为它会在视觉上导致第二条消息和第三条消息之间出现间隙(换行的新行 + 我的换行符) .对于那个控制台宽度来说,这一切都很好,但是当我调整大小时,一切都坏了。
Strive Sun - MSFT 在他们的回答中指出,这种行为似乎是由于设置了 ENABLE_VIRTUAL_TERMINAL_PROCESSING 标志而发生的。禁用它可以解决问题。我使用这个标志来启用不同颜色的输出,所以想找到一些方法来修复换行符而不丢失彩色输出。
有什么方法可以告诉 Windows 不要那样做(不禁用 ENABLE_VIRTUAL_TERMINAL_PROCESSING 不丢失颜色)?
有什么方法可以告诉 Windows 不要那样做吗?
经过一番调试,发现在控制台去掉ENABLE_VIRTUAL_TERMINAL_PROCESSING 样式后就不会出现这个问题了
像这样,
DWORD lp;
HANDLE std_out = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleMode(std_out, &lp);
SetConsoleMode(std_out, lp &~ENABLE_VIRTUAL_TERMINAL_PROCESSING );
...
已更新:
int main()
{
DWORD lp;
HANDLE std_out = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleMode(std_out, &lp);
SetConsoleMode(std_out, lp & ~ENABLE_VIRTUAL_TERMINAL_PROCESSING);
SetConsoleTextAttribute(std_out, FOREGROUND_RED);
DWORD written;
char str1[] = "aaaaaa\n";
char str2[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\r\ndddddd";
// char str2[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n";
char str3[] = "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\n";
int len = strlen(str2);
WriteConsoleA(std_out, str1, strlen(str1), &written, NULL);
SetConsoleTextAttribute(std_out, FOREGROUND_INTENSITY);
WriteConsoleA(std_out, str2, strlen(str2), &written, NULL);
SetConsoleTextAttribute(std_out, FOREGROUND_INTENSITY | FOREGROUND_GREEN);
WriteConsoleA(std_out, str3, strlen(str3), &written, NULL);
system("pause");
return 0;
}
更多颜色请参考:C++ Win32 Console Color
我发现,如果想继续使用 ANSI 转义码并且不想因换行而出现奇怪的错误,将其传递给 ConsoleMode 就足够了:
auto h = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleMode(h, ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
我在 Windows 上有一个 C++ 应用程序,它记录到标准输出(通过使用 WriteConsole 的 Win32 api)。每个日志行都包含一些文本和一个尾随的换行符。问题是:
当日志文本的宽度(不包括换行符)与控制台的宽度匹配时window,换行符将被丢弃。
看这个例子:
有 3 条日志消息:
- 第一个小于控制台宽度
- 第二个与控制台宽度完全匹配
- 第三个比控制台宽度长,因此环绕。
如果我调整 window 的大小,会发生以下情况:
第二行和第三行合并为一行,尽管它们之间打印了一个换行符。我怀疑 windows 为了聪明,在第二条消息之后丢弃了换行符,因为它会在视觉上导致第二条消息和第三条消息之间出现间隙(换行的新行 + 我的换行符) .对于那个控制台宽度来说,这一切都很好,但是当我调整大小时,一切都坏了。
Strive Sun - MSFT 在他们的回答中指出,这种行为似乎是由于设置了 ENABLE_VIRTUAL_TERMINAL_PROCESSING 标志而发生的。禁用它可以解决问题。我使用这个标志来启用不同颜色的输出,所以想找到一些方法来修复换行符而不丢失彩色输出。
有什么方法可以告诉 Windows 不要那样做(不禁用 ENABLE_VIRTUAL_TERMINAL_PROCESSING 不丢失颜色)?
有什么方法可以告诉 Windows 不要那样做吗?
经过一番调试,发现在控制台去掉ENABLE_VIRTUAL_TERMINAL_PROCESSING 样式后就不会出现这个问题了
像这样,
DWORD lp;
HANDLE std_out = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleMode(std_out, &lp);
SetConsoleMode(std_out, lp &~ENABLE_VIRTUAL_TERMINAL_PROCESSING );
...
已更新:
int main()
{
DWORD lp;
HANDLE std_out = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleMode(std_out, &lp);
SetConsoleMode(std_out, lp & ~ENABLE_VIRTUAL_TERMINAL_PROCESSING);
SetConsoleTextAttribute(std_out, FOREGROUND_RED);
DWORD written;
char str1[] = "aaaaaa\n";
char str2[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\r\ndddddd";
// char str2[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n";
char str3[] = "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\n";
int len = strlen(str2);
WriteConsoleA(std_out, str1, strlen(str1), &written, NULL);
SetConsoleTextAttribute(std_out, FOREGROUND_INTENSITY);
WriteConsoleA(std_out, str2, strlen(str2), &written, NULL);
SetConsoleTextAttribute(std_out, FOREGROUND_INTENSITY | FOREGROUND_GREEN);
WriteConsoleA(std_out, str3, strlen(str3), &written, NULL);
system("pause");
return 0;
}
更多颜色请参考:C++ Win32 Console Color
我发现,如果想继续使用 ANSI 转义码并且不想因换行而出现奇怪的错误,将其传递给 ConsoleMode 就足够了:
auto h = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleMode(h, ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);