C++ 重载操作符<<实现cout定位输出以及设置颜色:cout<<Goto(x,y)<<setC(color)<<123<<cr;

调用<windows.h>库中几个最常用的WINAPI函数,重载了操作符<<,使得cout可以定位输出以及设置颜色。

用法: cout<<Goto(x,y)<<setC(foreColor,bgColor)<<“输出内容”<<cr;

Goto(x,y) 定位到坐标(x,y) ,控制台窗口的左上角第一格坐标为(0,0);
Goto(x)    定位坐标到本行的 x ,即默认y为当前行;
Goto()      回到本行行首,即回车不换行。
cr()           回车且换行,与std::endl等效。

setC(foreColor,bgColor) 设置前景色和背景色;
setC(foreColor) 只设置前景色,背景色不变;
setC() 前景色和背景色恢复到控制台默认值。

foreColor,bgColor 取值范围 0 ~ 15,对应颜色值如下:

/* setC()设置的颜色值DOS内部命令COLOR的相类似
如下列表中,只要把其中的A~F换成10~15即可: 

D:\CPP>color /?
设置默认的控制台前景和背景颜色。

    0 = 黑色       8 = 灰色
    1 = 蓝色       9 = 淡蓝色
    2 = 绿色       A = 淡绿色
    3 = 浅绿色   B = 淡浅绿色
    4 = 红色       C = 淡红色
    5 = 紫色       D = 淡紫色
    6 = 黄色       E = 淡黄色
    7 = 白色       F = 亮白色
*/

源代码:

#include <iostream>
#include <windows.h>
#define Stream std::basic_ostream<T1, T2>&
using namespace std;

struct HannsC { DWORD fc; DWORD bg; };
struct HannXy { SHORT pX; SHORT pY; };

HannsC setC(DWORD fc = 7, DWORD bg = 0)
{
	return {fc % 16, bg % 16 *16};
}

HannXy Goto(SHORT x = 0, SHORT y = -1)
{
	return {x, y};
}

template<typename T1, typename T2>
Stream operator<<(Stream _os, HannsC _mc)
{
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(hConsole,_mc.fc|_mc.bg);
	return _os;
}

template<typename T1, typename T2>
Stream operator<<(Stream _os, HannXy _xy)
{
    CONSOLE_SCREEN_BUFFER_INFO pBuffer;
	COORD position = {_xy.pX, _xy.pY};
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 
	if (position.Y==-1){
		GetConsoleScreenBufferInfo(hConsole, &pBuffer); 
		position.Y = pBuffer.dwCursorPosition.Y;
	}    
    SetConsoleCursorPosition(hConsole, position);
	return _os;
}

template<typename T1, typename T2>
Stream cr(Stream _out)
{
	_out.put('\n');
	_out.flush();
	return _out;
}
 
int main(void)
{
	cout << setC(23,3) << "abcdefghijklmnopqrstuvwxyz" << cr;
	cout << Goto(16,3) << setC(14,9) << "abcdefghijkl" 
		 << setC(9,14) << Goto(30) << 123 << cr << cr;
	cout << setC(13,6) << 12312303236131230 << cr;
	cout << setC(3,15) << Goto(18,10) << "3.14159265358979323";
	cout << Goto(30) << setC(12) << "END!" << Goto() << "cr && !lf";
	cout << setC() << cr;
		
	return 0;
}

输出效果:

DOS颜色命令COLOR的色号着实有点难记,顺便吐槽一下微软翻译的颜色中文名;还是自己动手宏定义这些颜色名称吧:

源代码稍微作改进,既方便颜色的记忆也增加了代码的可阅读性:

#include <iostream>
#include <windows.h>
using namespace std;

#define	cBlack	 0
#define	cNavy	 1
#define	cGreen	 2
#define	cTeal	 3
#define	cMaroon	 4
#define	cPurple	 5
#define	cOlive	 6
#define	cSliver	 7
#define	cGray	 8
#define	cBlue	 9
#define	cLime	 10
#define	cCyan	 11
#define	cRed	 12
#define	cMagenta 13
#define	cYellow	 14
#define	cWhite	 15

struct HannsC { DWORD fc; DWORD bg; };
struct HannXy { SHORT pX; SHORT pY; };

HannsC setC(DWORD fc = cSliver, DWORD bg = cBlack)
{
	return {fc % 16, bg % 16 *16};
}

HannXy Goto(SHORT x = 0, SHORT y = -1)
{
	return {x, y};
}

ostream& operator<<(ostream& _os, HannsC _mc)
{
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(hConsole,_mc.fc|_mc.bg);
	return _os;
}

ostream& operator<<(ostream& _os, HannXy _xy)
{
    CONSOLE_SCREEN_BUFFER_INFO pBuffer;
	COORD position = {_xy.pX, _xy.pY};
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 
	if (position.Y==-1){
		GetConsoleScreenBufferInfo(hConsole, &pBuffer); 
		position.Y = pBuffer.dwCursorPosition.Y;
	}    
    SetConsoleCursorPosition(hConsole, position);
	return _os;
}

ostream& cr(ostream& _out)
{
	_out.put('\n');
	_out.flush();
	return _out;
}
 
int main(void)
{
	cout << setC(cNavy,cLime) << "abcdefghijklmnopqrstuvwxyz" << cr;
	cout << Goto(16,3) << setC(cYellow,cBlue) << "abcdefghijkl" 
		 << setC(cBlue,cYellow) << Goto(30) << 123 << cr << cr;
	cout << setC(cMagenta,cOlive) << 12312303236131230 << cr;
	cout << setC(cGreen,cWhite) << Goto(18,9) << "3.1415926535897932384626";
	cout << Goto(30) << setC(cRed) << "END!" << Goto() << "cr && !lf";
	
	cout << setC(cCyan) << cr << cr << "my C++ version: " << __cplusplus ;
	cout << setC() << cr;
		
	return 0;
}

附录:SetConsoleTextAttribute:

函数原型:
WINBASEAPI WINBOOL WINAPI SetConsoleTextAttribute(HANDLE hConsoleOutput,WORD wAttributes);
函数用法:
  HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
  SetConsoleTextAttribute(hConsole,foregroundColor|backgroundColor);

只有三原色用以下宏常量设置:

FOREGROUND_RED        表示设置前景色为红色。
FOREGROUND_GREEN      表示设置前景色为绿色。
FOREGROUND_BLUE       表示设置前景色为蓝色。
BACKGROUND_RED        表示设置背景色为红色。
BACKGROUND_GREEN      表示设置背景色为绿色。
BACKGROUND_BLUE       表示设置背景色为蓝色。

其他颜色就用此6个宏及以下两个宏,做或运算得到。

FOREGROUND_INTENSITY  表示设置前景色为高亮显示。
BACKGROUND_INTENSITY  表示设置背景色为高亮显示。

例如设置高亮白色字体,用以下代码:

FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE

不知道写库函数的人是怎么想的,只给定三原色......^_^

猜你喜欢

转载自blog.csdn.net/boysoft2002/article/details/114300111