由於我在 windows 平台開發,因次要用到 win32 的 api 來處理顏色,這很惱人~
之前寫的 PTT 截圖程式,就是用 win32 api,主要是用 SetConsoleTextAttribute 這個 api 來設定顏色。程式碼如下:
Console::ColorType Console::set_color(ColorType color) throw(std::logic_error) { CONSOLE_SCREEN_BUFFER_INFO csbi; WORD oldColor; if (GetConsoleScreenBufferInfo(out_, &csbi)) oldColor = csbi.wAttributes; else throw std::logic_error("Can't Get Console Screen Buffer Info"); if (color==0x00) color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; /* set text and background color */ SetConsoleTextAttribute(out_, color); /* FOREGROUND_BLUE(0x01), FOREGROUND_GREEN(0x02), FOREGROUND_RED(0x04), FOREGROUND_INTENSITY(0x08), BACKGROUND_BLUE(0x10), BACKGROUND_GREEN(0x20), BACKGROUND_RED(0x40), BACKGROUND_INTENSITY(0x80) ex: FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE */ return oldColor; }
在 codeproject 找到了一篇文章,利用 IO manipulator 來包裝使得改變顏色變得很輕鬆。
Add Color to Console Projects
注意此文章的 Points of Interest 有說明 IO Manipulator 的運作原理。
程式碼如下:
//------------------------------------------------------------------------------
// Console.h: interface for the Console manipulators.
//------------------------------------------------------------------------------
#if !defined( CONSOLE_MANIP_H__INCLUDED )
#define CONSOLE_MANIP_H__INCLUDED
//------------------------------------------------------------------------------
//------------------------------------------------------------------"includes"--
#include <iostream>
#include <iomanip>
#include <windows.h>
namespace JadedHoboConsole
{
static const WORD bgMask( BACKGROUND_BLUE |
BACKGROUND_GREEN |
BACKGROUND_RED |
BACKGROUND_INTENSITY );
static const WORD fgMask( FOREGROUND_BLUE |
FOREGROUND_GREEN |
FOREGROUND_RED |
FOREGROUND_INTENSITY );
static const WORD fgBlack ( 0 );
static const WORD fgLoRed ( FOREGROUND_RED );
static const WORD fgLoGreen ( FOREGROUND_GREEN );
static const WORD fgLoBlue ( FOREGROUND_BLUE );
static const WORD fgLoCyan ( fgLoGreen | fgLoBlue );
static const WORD fgLoMagenta( fgLoRed | fgLoBlue );
static const WORD fgLoYellow ( fgLoRed | fgLoGreen );
static const WORD fgLoWhite ( fgLoRed | fgLoGreen | fgLoBlue );
static const WORD fgGray ( fgBlack | FOREGROUND_INTENSITY );
static const WORD fgHiWhite ( fgLoWhite | FOREGROUND_INTENSITY );
static const WORD fgHiBlue ( fgLoBlue | FOREGROUND_INTENSITY );
static const WORD fgHiGreen ( fgLoGreen | FOREGROUND_INTENSITY );
static const WORD fgHiRed ( fgLoRed | FOREGROUND_INTENSITY );
static const WORD fgHiCyan ( fgLoCyan | FOREGROUND_INTENSITY );
static const WORD fgHiMagenta( fgLoMagenta | FOREGROUND_INTENSITY );
static const WORD fgHiYellow ( fgLoYellow | FOREGROUND_INTENSITY );
static const WORD bgBlack ( 0 );
static const WORD bgLoRed ( BACKGROUND_RED );
static const WORD bgLoGreen ( BACKGROUND_GREEN );
static const WORD bgLoBlue ( BACKGROUND_BLUE );
static const WORD bgLoCyan ( bgLoGreen | bgLoBlue );
static const WORD bgLoMagenta( bgLoRed | bgLoBlue );
static const WORD bgLoYellow ( bgLoRed | bgLoGreen );
static const WORD bgLoWhite ( bgLoRed | bgLoGreen | bgLoBlue );
static const WORD bgGray ( bgBlack | BACKGROUND_INTENSITY );
static const WORD bgHiWhite ( bgLoWhite | BACKGROUND_INTENSITY );
static const WORD bgHiBlue ( bgLoBlue | BACKGROUND_INTENSITY );
static const WORD bgHiGreen ( bgLoGreen | BACKGROUND_INTENSITY );
static const WORD bgHiRed ( bgLoRed | BACKGROUND_INTENSITY );
static const WORD bgHiCyan ( bgLoCyan | BACKGROUND_INTENSITY );
static const WORD bgHiMagenta( bgLoMagenta | BACKGROUND_INTENSITY );
static const WORD bgHiYellow ( bgLoYellow | BACKGROUND_INTENSITY );
static class con_dev
{
private:
HANDLE hCon;
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
public:
con_dev()
{
hCon = GetStdHandle( STD_OUTPUT_HANDLE );
}
private:
void GetInfo()
{
GetConsoleScreenBufferInfo( hCon, &csbi );
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
}
public:
void Clear()
{
COORD coordScreen = { 0, 0 };
GetInfo();
FillConsoleOutputCharacter( hCon, TEXT(' '),
dwConSize,
coordScreen,
&cCharsWritten );
GetInfo();
FillConsoleOutputAttribute( hCon,
csbi.wAttributes,
dwConSize,
coordScreen,
&cCharsWritten );
SetConsoleCursorPosition( hCon, coordScreen );
}
void SetColor( WORD wRGBI, WORD Mask )
{
GetInfo();
csbi.wAttributes &= Mask;
csbi.wAttributes |= wRGBI;
SetConsoleTextAttribute( hCon, csbi.wAttributes );
}
} console;
inline std::ostream& clr( std::ostream& os )
{
os.flush();
console.Clear();
return os;
};
inline std::ostream& fg_red( std::ostream& os )
{
os.flush();
console.SetColor( fgHiRed, bgMask );
return os;
}
inline std::ostream& fg_green( std::ostream& os )
{
os.flush();
console.SetColor( fgHiGreen, bgMask );
return os;
}
inline std::ostream& fg_blue( std::ostream& os )
{
os.flush();
console.SetColor( fgHiBlue, bgMask );
return os;
}
inline std::ostream& fg_white( std::ostream& os )
{
os.flush();
console.SetColor( fgHiWhite, bgMask );
return os;
}
inline std::ostream& fg_cyan( std::ostream& os )
{
os.flush();
console.SetColor( fgHiCyan, bgMask );
return os;
}
inline std::ostream& fg_magenta( std::ostream& os )
{
os.flush();
console.SetColor( fgHiMagenta, bgMask );
return os;
}
inline std::ostream& fg_yellow( std::ostream& os )
{
os.flush();
console.SetColor( fgHiYellow, bgMask );
return os;
}
inline std::ostream& fg_black( std::ostream& os )
{
os.flush();
console.SetColor( fgBlack, bgMask );
return os;
}
inline std::ostream& fg_gray( std::ostream& os )
{
os.flush();
console.SetColor( fgGray, bgMask );
return os;
}
inline std::ostream& bg_red( std::ostream& os )
{
os.flush();
console.SetColor( bgHiRed, fgMask );
return os;
}
inline std::ostream& bg_green( std::ostream& os )
{
os.flush();
console.SetColor( bgHiGreen, fgMask );
return os;
}
inline std::ostream& bg_blue( std::ostream& os )
{
os.flush();
console.SetColor( bgHiBlue, fgMask );
return os;
}
inline std::ostream& bg_white( std::ostream& os )
{
os.flush();
console.SetColor( bgHiWhite, fgMask );
return os;
}
inline std::ostream& bg_cyan( std::ostream& os )
{
os.flush();
console.SetColor( bgHiCyan, fgMask );
return os;
}
inline std::ostream& bg_magenta( std::ostream& os )
{
os.flush();
console.SetColor( bgHiMagenta, fgMask );
return os;
}
inline std::ostream& bg_yellow( std::ostream& os )
{
os.flush();
console.SetColor( bgHiYellow, fgMask );
return os;
}
inline std::ostream& bg_black( std::ostream& os )
{
os.flush();
console.SetColor( bgBlack, fgMask );
return os;
}
inline std::ostream& bg_gray( std::ostream& os )
{
os.flush();
console.SetColor( bgGray, fgMask );
return os;
}
}
//------------------------------------------------------------------------------
#endif //!defined ( CONSOLE_MANIP_H__INCLUDED )
於是設定顏色就和使用 std::setw(10) 的方式一樣:
#include "Console.h" namespace con = JadedHoboConsole; int main() { using std::cout; using std::endl; cout << "I like " << con::fg_green << "green" << con::fg_white << " eggs and ham." << endl; }
舒服!!
這片文章花了很長的時間在處理如何貼程式碼 = =
回覆刪除這篇有教學,只是對於水平軸的顯示我還不知道要到哪裡設定,可能這個樣本對於水平軸本來就不支援。
http://klcintw4.blogspot.com/2006/11/blog-post_03.html
另外一篇,這個方法就可以出現水平軸,只是會有 < > 顯示的問題 = =
http://blog.uioiu.com/2009/11/blogger-syntax-highlighting.html
還有加上 hover 滑鼠移動時,可以調整 code 框的 size