在windows里面,用户界面包括控制台(Console)形式的和窗口(Window)形式的。控制台形式的界面我们也是经常接触的,不就是那个黑色的框框吗?但是我们并没有直接使用Windows API,通常我们调用printf来输出、scanf来输入。实际上,这个c语言函数也是通过Windows API来实现的。不信的话,可以打开crtdll.dll查看里面的字符串。
关于Console的API不是很多,主要包括,获取控制台句柄,控制台输入输出,控制台样式设置。下面逐一介绍:
1) HANDLE WINAPI GetStdHandle(_in_ DWORD nStdHandle);
根据参数获取句柄。标准输入句柄为STD_INPUT_HANDLE,标准输出句柄为STD_OUTPUT_HANDLE,或者设置为错误句柄STD_ERROR_HANDLE。
2) BOOL WINAPI WriteConsole(
_in_ HANDLE hConsoleOutput, // 标准输出句柄
_in_ const VOID* lpBuffer, // 输出内容缓冲区指针
_in_ DWORD nNumberOfCahrsToWrite, // 缓冲区内容大小
_out_ LPDWORD lpNumberOfCharsWriten // 实际输出字符数
LPVOID lpReseverd); // 保留参数,置为NULL即可
3) BOOL WINAPI ReadConsole(
_in_ HANDLE hConsoleInput, // 标准输入句柄
_out_ LPVOID lpBuffer, // 保存读入字符的缓冲区指针
_in DWORD nNumberOfCharsToRead, // 缓冲区大小
out_ LPDWORD lpNumberOfCharsRead, // 实际读入字符
_in_opt_ LPVOID pInoutControl // 输入控制在,这是一个指向CONSOLE_READCONSOLE_CONTROL结构体的指针,可置为NULL
);
4) BOOL WINAPI GetConsoleScreenBufferInfo
_In_ HANDLE hConsoleOutput, // 标准输出句柄
_Out_ PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo // CONSOLE_SCREEN_BUFFER_INFO结构体指针,用于保存控制台字体颜色等信息,这个可以用来恢复初始设置,即先获取保存控制台信息,在之后修改后还可以通过这个变量来恢复设置
);
CONSOLE_SCREEN_BUFFER_INFO结构体定义如下:
typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
COORD dwSize;
COORD dwCursorPosition;
WORD wAttributes;
SMALL_RECT srWindow;
COORD dwMaximumWindowSize;
} CONSOLE_SCREEN_BUFFER_INFO;
5) BOOL WINAPI SetConsoleTextAttribute(
_In_ HANDLE hConsoleOutput, // 标准输出句柄
_In_ WORD wAttributes // 文字属性的组合,前景色、背景色等
);
比如设置前景色红色,颜色加强:
SetConsoleTextAttribute(hStdout, FOREGROUND_RED | FOREGROUND_INTENSITY)
注意几种颜色组合会变成其他颜色
6) BOOL WINAPI FillConsoleOutputAttribute(
_In_ HANDLE hConsoleOutput, // 输出句柄
_In_ WORD wAttribute, // 颜色
_In_ DWORD nLength, // 填充单元格数量
_In_ COORD dwWriteCoord, // 填充坐标
_Out_ LPDWORD lpNumberOfAttrsWritten // 实际改变情况
);
7) 其他
GetConsoleTitle/SetConsoleTitle 获取/设置控制台标题
FillConsoleOutputAttribute 设置文字单元的属性,从Fill一词可以看出,这个是填充效果
FillConsoleOutputCharacter 填充字符
SetConsoleCursorPosition 设置光标位置
获取、设置字体等。
更多用法请参考msdn:
示例:
#include <stdio.h>
#include <Windows.h>
int main(int argc, char** argv){
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); // 获取输出句柄
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); // 获取输入句柄
CONSOLE_SCREEN_BUFFER_INFO backInfo;
GetConsoleScreenBufferInfo(hStdout, &backInfo); // 保存原始信息
DWORD dwSize;
// 设置颜色
WriteConsoleA(hStdout, "I'm tkorays.\n", 13, &dwSize, NULL); // 未设置字体颜色,内容为ASCII编码
SetConsoleTextAttribute(hStdout, FOREGROUND_RED | FOREGROUND_INTENSITY);
WriteConsole(hStdout, L"hello\n", 6, &dwSize, NULL); // 设置颜色后输出,UNICODE编码
SetConsoleTextAttribute(hStdout, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
system("pause"); // 暂停下,看前面的效果
LPWSTR lpChar = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2048);
COORD coord; // 相对坐标
coord.X = 0;
coord.Y = 0;
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hStdout, &csbi); // 获取此时屏幕缓存
ReadConsoleOutputCharacter(hStdout, lpChar, 2047, coord, &dwSize); // 获取屏幕缓存
// 颜色数组,用于后面设置
WORD wColors[3];
wColors[0] = BACKGROUND_BLUE | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN;
wColors[1] = BACKGROUND_RED | BACKGROUND_GREEN;
wColors[2] = BACKGROUND_GREEN;
// 修改屏幕缓存
DWORD dwLen;
for (size_t i = 0; i < dwSize; i++){
// 屏幕中的小写字母改变样式
if (lpChar[i] >= 'a'&&lpChar[i] <= 'z'){
// 计算字符坐标
coord.Y = i / csbi.dwSize.X;
coord.X = i%csbi.dwSize.X;
WriteConsoleOutputAttribute(hStdout, wColors, 1, coord, &dwLen);
}
}
// 恢复原始字体颜色
SetConsoleTextAttribute(hStdout, backInfo.wAttributes);
return 0;
}
结果:
运行到system("pause");处:
修改小写字母样式后: