I'm doing a school project in which I need to change text colour frequently. Project target is Console app currently for Windows only. Using Codeblocks with MinGW for Debugging. I'm not a noob, but Intermediate-ish.
So using this everywhere in the code was ugly:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), __col._colour_code);
Even if I wrapped it in a function, it still is cumbersome and ugly because you cannot continue your cout chain. You have break the chain as you must call the SetColour
in a new statement, e.g.:
SetColour(GRAY); cout << setcol(PURPLE) << " ID:[";
SetColour(AQUA); cout << song.GetID();
SetColour(GRAY); cout << "]" << " ";
SetColour(GREEN); cout << song.GetTitle();
SetColour(WHITE); cout << " by ";
SetColour(BRIGHT); cout << song.GetArtist() << "\n";
What I wanted was a functionality like that of setw
, setprecision
, etc. So I opened the iomainp.h
and looked for some hints:
struct _Setw { int _M_n; };
inline _Setw
setw(int __n)
{ return { __n }; }
template<typename _CharT, typename _Traits>
inline basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is, _Setw __f)
{
__is.width(__f._M_n);
return __is;
}
template<typename _CharT, typename _Traits>
inline basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, _Setw __f)
{
__os.width(__f._M_n);
return __os;
}
So I created a new function of my own in a 100% analogous way:
enum Colour { BLACK=0x00, DARK_GREEN=0x02, WHITE=0x07, GRAY,
BLUE=0x09, GREEN, AQUA, RED, PURPLE, YELLOW, BRIGHT };
struct _colour_struct
{
uint8_t _colour_code;
};
inline _colour_struct setcolour (Colour colour_foregrnd, Colour colour_backgrnd =BLACK)
{
uint8_t colour_code = colour_backgrnd;
colour_code <<= 4;
colour_code |= colour_foregrnd;
return { colour_code };
}
namespace std
{
template<typename _CharT, typename _Traits>
inline basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, _colour_struct __col)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), __col._colour_code);
return __os;
}
}
SURPRISE! (for me) Its working!! e.g.:
cout << setcolour(GRAY) << " ID:[" << setcolour(AQUA) << song.GetID() << setcolour(GRAY) << "]" << " "
<< setcolour(GREEN) << song.GetTitle()
<< setcolour(WHITE) << " by "<< setcolour(BRIGHT) << song.GetArtist() << "\n";
But consider the output of this code:
std::cout << std::setw(20) << setcolour(AQUA) << "1st time" << "\n";
std::cout << "2nd time" << "\n";
std::cout << "3rd time" << "\n";
Notice that setw
DIDN'T stick, it was Reset in the second line. How ??
(Debugging showed no extra call being executed to reset it.)
But my setcolour
DID stick for rest of the program. Why ??
(Although its 100% analogous to setw
).
How can I make setcolour
just like setw
??? I need this functionality to make my program more clean and logical.
Also I found this: Which iomanip manipulators are sticky
But the answers and comments just there only confused me. Apperently, setw
calls cout.width(0), but debugging showed no such call, nor such a line of code was found in iomanip.h
. Also didn't understand the answer there. Please explain.
EDIT
Maybe I wasn't direct in asking the question.
Like cout.width(0)
(in context of setw
) gets called each time,
How can I make my SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0)
(in context of setcolour
) get called each time ???
How should I approach this problem ??