C语言字体背景颜色变换以及按键探测

/*
What's The Pointer?
By: Thomas Powers

An experiment in everything you're never supposed to do with pointers
This is a memory peek/poke program

You can browse memory as long as it's not a chunk of memory allocated to another app.
When you get pages of ?'s symbols that means that area of memory is inaccessible

Use the scan up (insert) or scan down (delete) key to search for the next block
of memory that is readable

You can use the 'w' key to alter the currently selected byte.
*/

#include <iostream>
#include <iomanip>
using namespace std;
#include <conio.h>	// needed for the _getch() function
#include <windows.h>
#include <string>
#include <cmath> 

const int ROWS=15;
const int COLS=16;
const int BLOCK_SIZE=ROWS*COLS;

void displayBlock(unsigned char *start, const unsigned char *homeAddr, unsigned int=0, unsigned int=0);
unsigned char *scan(unsigned char *, int);
void write(unsigned char *addr, unsigned int rowOffet=0, unsigned int colOffset=0);

enum COLOURS {
	COLOUR_DEFAULT	= 15,
	COLOUR_HIGHLIGHT= 42,
	COLOUR_OTHER	= 14
};

enum KEYS {
	ARROW_KEY	= -32,
	KEY_UP		= 72,
	KEY_DOWN	= 80,
	KEY_LEFT	= 75,
	KEY_RIGHT	= 77,
	HOME		= 71,
	PG_UP		= 73,
	PG_DOWN		= 81,
	INS		= 82,
	DEL		= 83
};

const int LOW_INVALID_CHAR=7;
const int HIGH_INVALID_CHAR=13;
const string INVALID_CHAR_NAME[7]={"Bell", "Backspace", "Tab", "Line Feed", "Home", "Form Feed", "New Line"};
enum CHARS {
	CHR_BELL	= 7,
	CHR_BACKSPACE	= 8,
	CHR_TAB		= 9,
	CHR_LINEFEED	= 10,
	CHR_HOME	= 11,
	CHR_FORMFEED	= 12,
	CHR_NEWLINE	= 13	
};

int main(int argc, char *argv[]) {
	
	// this is our magic floating pointer (which is not a floating point, just a char)
	unsigned char *p = new unsigned char;

	// It might be interesting to start at a variable, focusing us somewhere in main's stackframe
	// otherwise, just let p remain uninitialized
	unsigned char s[]="[Welcome Home]";

	// check the command line arguments
	for ( int i=1; i < argc; i++ ) {
		if ( strcmp(argv[i],"-mainframe")==0 ) { 
			p=s;
			break;
		}
		if ( strcmp(argv[i],"-?")==0 ) {
			cout << "Usage: To try to start you out near main()'s stack frame, use '-mainframe'\n"
				 << "This will point to a local variable (a char array) in main()\n";
			system("pause");
		}
	}

	unsigned int selectRow=0, selectCol=0;

	// make a copy of p so that we can always get back home
	unsigned char *home=p;

	char inp;  // some place to get a key input from the user

	// the main loop
	do {
		displayBlock(p,home,selectRow,selectCol);
		
		inp=_getch();
		if ( inp == ARROW_KEY ) {
			// arrow keys, home, ins, del, etc.. actually give _getch() two chars
			// if the first one was -32 we know this is happening
			inp=_getch();  // read from the buffer the 2nd character (which arrow key?)
			switch ( inp ) 
			{
				case KEY_RIGHT:
					selectCol++;
					selectCol%=COLS;
					break;
				case KEY_LEFT:
					selectCol--;
					selectCol%=COLS;
					break;
				case KEY_UP:
					selectRow--;
					selectRow%=ROWS;
					break;
				case KEY_DOWN:
					selectRow++;
					selectRow%=ROWS;
					break;
				case PG_UP:
					p=p-BLOCK_SIZE;
					break;
				case PG_DOWN:
					p=p+BLOCK_SIZE;
					break;
				case HOME:
					p=home;
					selectRow=0;
					selectCol=0;
					break;
				case 88:
					// uppercase X
					cout << "\nGoodbye\n";
					break;
				case 120:	
					// lowercase x
					cout << "\nGoodbye\n";
					break;	
				case INS:
					p=scan(p,-1);
					break;
				case DEL:
					p=scan(p,1);
					break;
			}
		} else {
			// non arrow/control key
			if ( inp == 'w' || inp == 'W' ) {
				// write (poke)
				write(p,selectRow,selectCol);
			}
		}
	} while (inp != 'x' && inp != 'X');

	return 0;
}

void displayBlock(unsigned char *start, const unsigned char *homeAddr, unsigned int selectRow, unsigned int selectCol) {
	
	HANDLE hConsole;
	hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

	// set default color (white)
	SetConsoleTextAttribute(hConsole,COLOUR_OTHER);

	system ("cls");
	cout << "Block starting at address: " << hex << long(start);
	cout << " ("<< dec << long( fabs(double(start+selectCol+(selectRow*COLS)-homeAddr)) ) << " Bytes from home)";
	cout << endl;
	cout << "--------------------------------------------------------------------------------\n";

	unsigned char chr[ROWS][COLS];
	
	int r=0, c=0;

	// read the block into a 2d array
	for ( int i=0; i < BLOCK_SIZE; i++ ) {
		// next row?
		if ( i>0 && i%COLS==0 ) { r++; c=0; }

		// try to get the byte from this location, otherwise use '?' if it's inaccessible memory
		__try { chr[r][c]=start[i]; } __except ( true ) { chr[r][c]='?'; }

		// next column
		c++;
	}

	// display the array
	for ( r=0; r < ROWS; r++ ) {
		SetConsoleTextAttribute(hConsole,COLOUR_DEFAULT);
		// print row address
		cout << hex << long( start+(COLS*r) ) << " :";

		// print hex values
		for ( c=0; c < COLS; c++ ) {
			cout << " ";  // leading space, not highlighted
			if ( r==selectRow && c==selectCol ) { 
				SetConsoleTextAttribute(hConsole,COLOUR_HIGHLIGHT); // highlight (inverted cyan)
			} else {
				SetConsoleTextAttribute(hConsole,COLOUR_DEFAULT); // white
			}
			cout << setw(2) << setfill('0') << hex << int(chr[r][c]);
			SetConsoleTextAttribute(hConsole,15); // white
		}
		
		// print ascii characters
		cout << " : ";
		for ( c=0; c < COLS; c++ ) {
			if ( r==selectRow && c==selectCol ) 
				SetConsoleTextAttribute(hConsole,COLOUR_HIGHLIGHT); // highlight (inverted cyan)
			else
				SetConsoleTextAttribute(hConsole,COLOUR_DEFAULT); // white
			// unless it's a character that's going to be a trouble maker
			if ( chr[r][c] != NULL && ( chr[r][c] < LOW_INVALID_CHAR || chr[r][c] > HIGH_INVALID_CHAR ) ) {
				cout << chr[r][c]; 
			} else {
				cout << ' ';
			}
		}

		// new line, next row
		cout << endl;
	}

	SetConsoleTextAttribute(hConsole,COLOUR_OTHER); // yellow
	cout << "\n[Arrow Keys] select byte, [PG UP]/[PG DN] read previous/next block"
		 << "\n[INS]/[DEL] Scan up/down, [HOME] starting location, [X] exit, [W] write\n";	
	
	cout << "\nSelected Byte: [";
	if ( chr[selectRow][selectCol] != NULL && (
		 chr[selectRow][selectCol] < LOW_INVALID_CHAR || 
		 chr[selectRow][selectCol] > HIGH_INVALID_CHAR) )
	{
		cout << chr[selectRow][selectCol];
	} else if ( chr[selectRow][selectCol] == NULL )	{
		cout << "NULL";
	} else {
		cout << INVALID_CHAR_NAME[ chr[selectRow][selectCol] - LOW_INVALID_CHAR ];
	}
	cout << "] HEX:" << hex << int(chr[selectRow][selectCol]) << " Decimal: " << dec << int(chr[selectRow][selectCol]) << endl;
	cout << "Address: " << hex << long( start+(selectCol)+(selectRow*COLS) );


	SetConsoleTextAttribute(hConsole,COLOUR_DEFAULT);
}

unsigned char *scan(unsigned char *p, int direction) {
	cout << "\nScanning for accessible memory, this may take... forever.....";
	char chr=NULL;
	bool readOK=false;

	do {
		__try { 
			chr=*p; 
			readOK=true;
		} __except ( true ) {
			p+=(BLOCK_SIZE*direction);
			readOK=false;			
		}
	} while ( !readOK );

	return p;
}

void write(unsigned char *addr, unsigned int rowOffset, unsigned int colOffset)
{
	unsigned int writeVal;

	addr+=colOffset+(rowOffset*COLS);

	cout << "\nEnter byte value (in decimal, 0-255, any invalid value (such as -1) will abort)\nByte Value: ";
	cin >> writeVal;
	
	if ( writeVal >=0 && writeVal <=255 ) {
		__try { 
			*addr=char(writeVal); 
		} __except ( true ) {
			cout << "\nWrite failed\n";
			system("pause");
		}
	} else {
		cout << "\nValue is invalid, aborting.\n";
		system("pause");
	}
}


C/C++改变控制台输出字体的背景和颜色(windows)

  (2014-03-07 11:48:18)
可以用第二种方法改变部分字体的背景和颜色。

1. 全局设置
     会改变整个窗口所有字体的背景和颜色。
     system("color 04");
     第一个数字代表背景色,第二个数字代表前景色。各颜色的代码如下:
0=黑色
1=蓝色
2=绿色
3=湖蓝色
4=红色
5=紫色
6=黄色
7=白色
8=灰色
9=淡蓝色
A=淡绿色
B=淡浅绿色
C=淡红色
D=淡紫色
E=淡黄色
F=亮白色

2. 改变下一个输出字体的背景和颜色
     include
     BOOL SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttributes);
     hConsoleOutput: 设备句柄,通过GetStdHandle(STD_OUTPUT_HANDLE)获取。
     wAttributes: 颜色属性

FOREGROUND_BLUE 字体颜色:蓝 1
FOREGROUND_GREEN 字体颜色:绿 2
FOREGROUND_RED 字体颜色:红 4
FOREGROUND_INTENSITY 前景色高亮显示 8
BACKGROUND_BLUE 背景颜色:蓝 16
BACKGROUND_GREEN 背景颜色:绿 32
BACKGROUND_RED 背景颜色:红 64
BACKGROUND_INTENSITY 背景色高亮显示 128

     也就是说SetConsoleTextAttribute函数是靠一个字节的低四位控制前景色,高四位控制背景色。

例如白底红字可以写成:
      SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),BACKGROUND_INTENSITY |FOREGROUND_INTENSITY | FOREGROUND_RED|BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
也可以写成:
      SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0xFC);

其他的颜色:
White on Black:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY
| FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
Red on Black:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY
|FOREGROUND_RED);
Green on Black:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY
| FOREGROUND_GREEN);
Yellow on Black:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY
|FOREGROUND_RED | FOREGROUND_GREEN);
Blue on Black:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY
|FOREGROUND_BLUE);
Magenta on Black:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY
|FOREGROUND_RED | FOREGROUND_BLUE);
Cyan on Black:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY
|FOREGROUND_GREEN | FOREGROUND_BLUE);
Black on White:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),BACKGROUND_INTENSITY
|FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
Red on White:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),BACKGROUND_INTENSITY
|FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
|FOREGROUND_RED);

例子:
#include
#include

int main()
{
      HANDLE handle;

      HANDLE = GetStdHandle(STD_OUTPUT_HANDLE);
      SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED);//设置为红色
      printf("这是红色\n");
      SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY);//恢复默认的灰色
      printf("这是灰色\n"); 

      getch();
      return 0;
}


你可能感兴趣的:(C语言字体背景颜色变换以及按键探测)