字符在更改颜色并向后打印时重叠

Zal*_*tax 7 c++ windows console textcolor visual-studio

在此输入图像描述

正如你所看到的那样,即使有足够的空间,上部暗X也会被切割.

发生这种情况是因为它们已经改变颜色并向后打印(从右到左).

这是一个错误,错误的代码,我的系统上的错误设置或(我怀疑它)它应该是什么样的?

以下是生成此输出的代码:

#include <Windows.h>
#include <iostream>
void moveTo(int x,int y){
    COORD kord={x,y};
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),kord);
}
void setColor(WORD attributes){
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), attributes);
}

void main(){
    for(int i=9;i+1;i--)
    {
        moveTo(i,0);
        std::cout.put('X');
    }
    for(int i=-10;i;i++)
    {
        moveTo(i+10,1);
        std::cout.put('X');
    }
    setColor(8);
    for(int i=9;i+1;i--)
    {
        moveTo(i,2);
        std::cout.put('X');
    }
    for(int i=-10;i;i++)
    {
        moveTo(i+10,3);
        std::cout.put('X');
    }
    setColor(7);
    for(int i=9;i+1;i--)
    {
        moveTo(i,4);
        std::cout.put('X');
    }
    for(int i=-10;i;i++)
    {
        moveTo(i+10,5);
        std::cout.put('X');
    }
    std::cin.get();
}
Run Code Online (Sandbox Code Playgroud)

MrG*_*mez 5

这是 Windows 中的一个错误。

正如Hans Passant在勘误表中提到的:

我也重现了,Win7上的VS2008。很酷的错误。更改控制台字体可以修复它。

让我们使用这个错误隔离。我将此字体识别为Petite Terminal,这意味着你们很可能将此项目配置为 Win32 控制台应用程序。GCC 的附加重现证实了这一假设,并且从实际角度出发,我们假设所有人都在 Windows 终端内运行一个 32 位控制台应用程序。

问题是为什么它在默认终端字体、颜色 8 的上下文中恰好写入一列额外的像素,并向后写入控制台屏幕缓冲区。

具体来说,让我们将这个问题分解为几个组成部分:

  1. 当发出写入时,一个字符被写入终端数组中的某个位置
  2. 选择默认颜色 (7) 时,像素不会溢出到数组内的其他缓冲区中
  3. 选择颜色 8 时,会将额外的像素列写入缓冲区的下一个区域,该区域仅在向后朗读文本时可见

由于 (3) 中存在溢出,这是一个错误。

引用陈雷蒙的话:

控制台渲染模型假设每个角色都整齐地适合其固定大小的单元格。当新字符写入单元格时,旧单元格会被新字符套印,但如果旧字符有悬垂或悬垂,这些额外的像素就会被留下,因为它们“溢出”了所需的单元格并感染了相邻的单元格。类似地,如果相邻字符“溢出”,那些“溢出像素”将被擦除。

可以在控制台窗口中使用的字体集被修剪为经过测试并且已知可以在控制台窗口中正常工作的字体。对于英语系统,我们需要使用 Lucida 控制台和终端。

...

“好吧,那太愚蠢了。你应该阻止我选择一种明显会导致无意义的字体。”

这就是我们所做的。

我并不是要把这件事归咎于雷蒙德,但他权威地说明这是“不可能发生的”。

Windows 控制台字体的选择和测试应该已经注意到了这一点。事实上,这甚至是一个问题,这本身就是一种反常现象。