我需要打印以控制台一些带有颜色内容的输出。可以在Windows原子上进行吗?在Linux中,有ansi colors支持,并且执行复杂的彩色句子确实非常方便。窗户呢?我可以执行以下操作:
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
printf(" this is how it starts ");
SetConsoleTextAttribute(hConsole, 10);
printf("YES, it should be green ");
SetConsoleTextAttribute(hConsole, 0);
printf("back to standard color\n");
在我看来,在异步应用中,这3个printf不会在控制台的同一行上打印文本。我想到了两种解决方案:
1)使用互斥锁同步所有控制台输出,以便所有消息顺序显示。似乎是针对此类问题的解决方案。
2)使用某种方法停止控制台输出一段时间,打印彩色线条,然后再次开始输出。
因此,我担心的是要获得彩色线条,而其他异步输出不会中断。是否可以在Windows中使用?什么是最佳方法?
答案 0 :(得分:0)
正如@eryksun所说,请使用WriteConsoleOutput而不是printf / std :: cout。
这与任何图形应用程序相同。只有一个线程可以完成所有编写工作。它有一个包含字符串和属性列表的队列。当线程希望打印某些内容时,它将字符串和相关属性推入队列。在打印写线程之前,先设置属性,然后打印字符串。
您将需要实现自己的线程安全队列。我的通常是小批量的输出,所以我使用一个带有uint8_t计数器和原子标记的256数组。没有边界检查:255之后uint8_t返回0。循环队列工作得很好。
您可以创建一个非常简单的类来进行编写。我通常使用这样的东西。 Scribbler是在屏幕上进行书写的类
means.mc1 <- rowMeans(mrna.c.1)
这可以像std :: cout一样使用,它将完成您可以使用std :: cout进行的所有操作。另外,您可以编写printf的变体,但要深入遍历std :: arg的深度并不是那么简单。
想要黄色输出的线程会做类似的事情
class COut : public std::ostringstream
{
Scribbler* writer;
WORD attr;
public:
COut(WORD in_attr)
{
attr = in_attr;
writer = Scribbler::Me();
}
COut& operator << (std::ostream&(*f)(std::ostream&))
{
if (f == std::endl)
{
*this << "\n";
writer->Push(attr, str());
str("");
}
else
{
*this << f;
}
return *this;
}
template <typename TT>
inline COut& operator << (const TT& t)
{
(*(std::ostringstream*) this) << t;
return *this;
}
};
想要洋红色输出的线程会做
COut yout(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
...
yout << "Yellow, yellow dirty fellow" << std::hex << std::setfill('0') << std::setw(4) << 25 << std::endl;
在发出std :: endl之前,不会打印任何内容。通过使用SetConsoleWindowInfo将不同的线程写入屏幕的不同可滚动部分,您可以对此颇具创意。只要只有一个线程进行编写,它将起作用。所有其他线程只是告诉它在哪里写输出及其颜色属性。