#include
void ScrollScreenBuffer(HANDLE, INT);//???
VOID HandleInput(LPSTR szInput);
VOID ChangeConsoleTitle(LPSTR szNewTitle);
VOID GetConsoleInfo(HANDLE hOutput);
VOID ChangeTextColor(HANDLE hStdout, WORD wColor);
VOID ChangeBackgroundColor(HANDLE hConsole);
VOID ChangeUpCaseTextBackgroundColor(HANDLE hStdin, HANDLE hStdout);
void cls(HANDLE hConsole);
VOID UseBlockIO();
VOID ChangeMode(HANDLE hStdin, HANDLE hStdout);
void NewLine();
DWORD UseEvent();
VOID KeyEventProc(KEY_EVENT_RECORD);
VOID MouseEventProc(MOUSE_EVENT_RECORD);
VOID ResizeEventProc(WINDOW_BUFFER_SIZE_RECORD);
HANDLE hStdout;
HANDLE hStdin;
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
int main(int argc, PCHAR argv[]){
LPSTR lpszPrompt = "type a line and press enter,255 max \n q to quit "
"\n i to show console info\n c to change background color \n s to change text color"
"\n t to find upper case character\n b to call useblackio\n u to change console titile"
"\n m to show console event \n r to change mode \n p to clear up console\n";
CHAR chBuffer[256];
DWORD cRead, cWritten, fdwMode, fdwOldMode;
WORD wOldColorAttrs;
//STDIN STDOUT 句柄
hStdin = GetStdHandle(STD_INPUT_HANDLE);
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdin == INVALID_HANDLE_VALUE || hStdout == INVALID_HANDLE_VALUE){
MessageBox(NULL, "获取句柄出错了", "控制台提示", MB_OK);
return 1;
}
//当前字体颜色
if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo)){
MessageBox(NULL, "获取字体颜色错误", "控制台提示", MB_OK);
return 1;
}
wOldColorAttrs = csbiInfo.wAttributes;
//设置字符颜色(红)和背景
ChangeTextColor(hStdout, FOREGROUND_RED | FOREGROUND_INTENSITY);
//输出字符
if (!WriteConsole(
hStdout,//输出句柄
lpszPrompt,//输出字符串
lstrlen(lpszPrompt),//字符串长度
&cWritten,//返回实际输出的长度
NULL//非 overlapped
)){
MessageBox(NULL, "输出字符出错", "控制台提示", MB_OK);
return 1;
}
while (1){
//循环等待用户输入
ZeroMemory(chBuffer, 256);
if (!ReadConsole(
hStdin,//输入控制台句柄
chBuffer,//读入数据的缓冲区
255,//缓冲区大小
&cRead,//实际读到的大小
NULL//非 overlapped
)){
break;
}
HandleInput(chBuffer);
}
}
//处理用户的输入
VOID HandleInput(LPSTR szInput){
switch (szInput[0]){
case 'q'://退出进程
ExitProcess(0);
case 'i'://显示控制台信息
GetConsoleInfo(hStdout);
break;
case 'c'://设置界面背景颜色
ChangeBackgroundColor(hStdout);
break;
case 's'://设置设置文字颜色
ChangeTextColor(hStdout, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
break;
case 't'://设置文字背景颜色
ChangeUpCaseTextBackgroundColor(hStdin, hStdout);
break;
case 'b'://使用 block IO
UseBlockIO();
break;
case 'u'://设置控制台标题
ChangeConsoleTitle(&szInput[2]);
break;
case 'm'://使用事件
UseEvent();
break;
case 'r'://改变模式
ChangeMode(hStdin, hStdout);
break;
case 'p'://清屏
cls(hStdout);
break;
default://其他直接返回
return 1;
}
return 1;
}
//改变控制台查看的标题
VOID ChangeConsoleTitle(LPSTR szNewTitle){
if (!SetConsoleTitle(szNewTitle)){
printf("设置控制台窗口失败\n");
}
}
//获取控制台信息
VOID GetConsoleInfo(HANDLE hOutput){
CONSOLE_FONT_INFO cfi;
DWORD dwProcessList[32];
DWORD dwAttachedProcess;
TCHAR szOutputBuffer[1024];
HWND hConsoleWindows;
DWORD dwWritten;
DWORD i;
CHAR szConsoleTitle[MAX_PATH];
//附属的进程,不考虑多余32个的情况
dwAttachedProcess = GetConsoleProcessList(dwProcessList, 32);
if (dwAttachedProcess == 0){
printf("获取附属进程列表失败\n");
}
//标题
if (!GetConsoleTitle(szConsoleTitle, MAX_PATH)){
printf("设置标题失败\n");
}
//窗口句柄
hConsoleWindows = GetConsoleWindow();
//字体
GetCurrentConsoleFont(hOutput, FALSE, &cfi);
wsprintf(szOutputBuffer, "新附属进程 %u 个: ", dwAttachedProcess);
for (i = 0; i< dwAttachedProcess; i++){
wsprintf(szOutputBuffer + lstrlen(szOutputBuffer), "%u, ", dwProcessList[i]);
}
//构造字符串
wsprintf(szOutputBuffer + lstrlen(szOutputBuffer),
"\n控制台标题是 %s,\n窗口句柄是 0x%.8x\n 字体是 %u, 字体大小是X=%UY=%u",
szConsoleTitle, hConsoleWindows, cfi.nFont, cfi.dwFontSize.X, cfi.dwFontSize.Y);
//显示获取的信息
if (!WriteConsole(hOutput, szOutputBuffer, lstrlen(szOutputBuffer), &dwWritten, NULL)){
printf("获取信息失败\n");
}
}
//修改文字颜色 句柄 新的颜色
VOID ChangeTextColor(HANDLE hStdout, WORD wColor){
//设置文字属性
if (!SetConsoleTextAttribute(hStdout, wColor)){
MessageBox(NULL, "设置文字属性失败", "控制台提示", MB_OK);
return;
}
}
//修改背景颜色
VOID ChangeBackgroundColor(HANDLE hConsole){
COORD coord;
WORD wColor;
DWORD cWritten;
BOOL fSuccess;
coord.X = 0;//第一个cell
coord.Y = 0;//第一行
//背景和前景色
wColor = BACKGROUND_BLUE | BACKGROUND_RED | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
//设置控制台属性
fSuccess = FillConsoleOutputAttribute(
hConsole,//handle句柄
wColor,//颜色
80 * 50,//填充cell数量
coord,//改变属性的第一个cell
&cWritten//实际改变的情况
);
if (!fSuccess){
printf("设置控制台属性失败\n");
}
}
//改变文字背景颜色
VOID ChangeUpCaseTextBackgroundColor(HANDLE hStdin, HANDLE hStdout){
DWORD dwLen, i, dwRead, dwWritten;
DWORD wColors[3];
BOOL fSuccess;
COORD coord;
HANDLE hSreenHandle;
CONSOLE_SCREEN_BUFFER_INFO csbi;
PCHAR lpCharacter = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2048);
coord.X = 0;//起始cell
coord.Y = 0;
//读取outputcharacher
if (!ReadConsoleOutputCharacter(hStdout, lpCharacter, 2047, coord, &dwRead)){
printf("读取outputcharacher错误\n");
}
//获取screenbufferinfo
GetConsoleScreenBufferInfo(hStdout, &csbi);
dwLen = lstrlen(lpCharacter);
//颜色数组
wColors[0] = BACKGROUND_RED;
wColors[1] = BACKGROUND_RED | BACKGROUND_GREEN;
wColors[2] = BACKGROUND_GREEN;
for (i = 0; i< dwLen; i++){
//差债大写字母
if (lpCharacter[i]>= 'A' && lpCharacter[i] <= 'Z'){
//如果是大写,将大写字母开始位置的3个cell文字背景改为3中不同的颜色
coord.X = i / csbi.dwSize.X;
coord.Y = i%csbi.dwSize.Y;
fSuccess = WriteConsoleOutputAttribute(
hStdout,//句柄
wColors,
3,
coord,//起始位置
&dwWritten
);
if (!fSuccess){
printf("改变文字背景颜色失败\n");
}
}
}
}
//清屏
void cls(HANDLE hConsole){
COORD coordScreen = { 0, 0 };//鼠标指针的位置
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
//当前buffer中文字cell数目
if (!GetConsoleScreenBufferInfo(hConsole, &csbi)){
return;
}
dwConSize = csbi.dwSize.X*csbi.dwSize.Y;
//将整个屏幕填充
if (!FillConsoleOutputCharacter(hConsole, (TCHAR)' ', dwConSize, coordScreen, &cCharsWritten)){
return;
}
//获取文字属性
if (!GetConsoleScreenBufferInfo(hConsole, &csbi)){
return;
}
//设置buffer属性
if (!FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten)){
return;
}
//将鼠标指针移到起始位置
SetConsoleCursorPosition(hConsole, coordScreen);
}
//使用BlockIO
VOID UseBlockIO(){
HANDLE hStdout, hNewScreenBuffer;
SMALL_RECT srctReadRect;
SMALL_RECT srctWriteRect;
CHAR_INFO chiBuffer[160];//[2][80]
COORD coordBufSize;
COORD coordBufCoord;
BOOL fSuccess;
//获得句柄
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
//新建buffer
hNewScreenBuffer = CreateConsoleScreenBuffer(
GENERIC_READ | GENERIC_WRITE,//可读可写
0,//不共享
NULL,//默认安全属性
CONSOLE_TEXTMODE_BUFFER,//must be TEXTMODE
NULL
);
if (hStdout == INVALID_HANDLE_VALUE || hNewScreenBuffer == INVALID_HANDLE_VALUE){
printf("创建新的缓存失败 %d\n", GetLastError());
return;
}
//设置屏幕的buffer
if (!SetConsoleActiveScreenBuffer(hNewScreenBuffer)){
printf("设置屏幕的缓存失败 %d\n", GetLastError());
return;
}
//设置源cell矩阵
srctReadRect.Top = 0;//top left row 0 col 0
srctReadRect.Left = 0;
srctReadRect.Bottom = 1;//bot right row 1 col 79
srctReadRect.Right = 79;
//临时buffer大小为2行3列?
coordBufSize.Y = 2;
coordBufSize.X = 80;
//临时buffer的起始位置
coordBufCoord.X = 0;
coordBufCoord.Y = 0;
//从屏幕buffer赋值内容到临时buffer
fSuccess = ReadConsoleOutput(
hStdout,//源
chiBuffer,//目的
coordBufSize,//目的buffer大小
coordBufCoord,//目的起始位置
&srctReadRect//源的起始位置
);
if (!fSuccess){
printf("从屏幕buffer复制内容到临时buffer失败 %d\n", GetLastError());
return;
}
//设置目的cells矩阵
srctWriteRect.Top = 10;//top lt row 10 col 0
srctWriteRect.Left = 0;
srctWriteRect.Bottom = 11;//bot rt row 11 col 79
srctWriteRect.Right = 79;
//从临时buffer向新的屏幕buffer复制
fSuccess = WriteConsoleOutput(hNewScreenBuffer, chiBuffer, coordBufSize, coordBufCoord, &srctWriteRect);
if (!fSuccess){
printf("从临时buffer向新的屏幕buffer复制失败 %d\n", GetLastError());
return;
}
//等一段时间爱你
Sleep(10000);
//恢复
if (!SetConsoleActiveScreenBuffer(hStdout)){
printf("恢复出错%d\n", GetLastError());
return;
}
}
//改变控制台的模式,关闭 ENABLE_LINE_INPUT ENABLE_ECHO_INPUT
VOID ChangeMode(HANDLE hStdin, HANDLE hStdout){
LPSTR lpszPrompt = "mode changeed type any key,or q to quit: ";
CHAR chBuffer[256];
DWORD fdwMode, fdwOldMode;
DWORD cRead, cWritten;
//获取当前模式
if (!GetConsoleMode(hStdin, &fdwOldMode)){
MessageBox(NULL, "获取递签模式失败", "控制台提示", MB_OK);
return;
}
//修改模式并重新设置
fdwMode = fdwOldMode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
if (!SetConsoleMode(hStdin, fdwMode)){
MessageBox(NULL, "设置失败", "控制台提示", MB_OK);
return;
}
//换行
NewLine();
//循环等待输入并处理
while (1){
if (!WriteFile(hStdout, lpszPrompt, lstrlen(lpszPrompt), &cWritten, NULL)){
printf("WriteFile\n");
return;
}
if (!ReadFile(hStdin, chBuffer, 1, &cRead, NULL)){
break;
}
if (chBuffer[0] == '\r'){
NewLine();
} else if (!WriteFile(hStdout, chBuffer, cRead, &cWritten, NULL)){
break;
} else{
NewLine();
}
if (chBuffer[0] == 'q'){
break;//输入q,退出
}
}
//恢复模式
SetConsoleMode(hStdin, fdwOldMode);
}
//新行,滚动屏幕
void NewLine(){
if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo)){
MessageBox(NULL, "GetConsoleScreenBufferInfo", "控制台提示", MB_OK);
return;
}
csbiInfo.dwCursorPosition.X = 0;
if ((csbiInfo.dwSize.Y - 1) == csbiInfo.dwCursorPosition.Y){
//ScrollScreenBuffer(hStdout, 1);
} else{
csbiInfo.dwCursorPosition.Y += 1;
}
if (!SetConsoleCursorPosition(hStdout, csbiInfo.dwCursorPosition)){
MessageBox(NULL, "SetConsoleCursorPosition", "控制台提示", MB_OK);
return;
}
}
DWORD UseEvent(){
CHAR chBuffer[256];
DWORD cRead;
HANDLE hStdin;
DWORD cNumRead, fdwMode, fdwSaveOldMode, i;
INPUT_RECORD irInBuf[128];
//获取标准输入句柄
hStdin = GetStdHandle(STD_INPUT_HANDLE);
if (hStdin == INVALID_HANDLE_VALUE){
printf("GetStdHandle\n");
}
//保存当前的控制台模式
if (!GetConsoleMode(hStdin, &fdwSaveOldMode)){
printf("GetConsoleMode\n");
}
//使窗口响应鼠标输入事件
fdwMode = ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT;
if (!SetConsoleMode(hStdin, fdwMode)){
printf("SetConsoleMode\n");
}
//循环读取输入
while (1){
//等待事件
if (!ReadConsoleInput(
hStdin,//输入句柄
irInBuf,//保存输入的缓冲区
128,//缓冲区大小
&cNumRead//实际读取的大小
)){
printf("ReadConsoleInput\n");
}
//显示事件
for (i = 0; i< cNumRead; i++){
switch (irInBuf[i].EventType){
case KEY_EVENT://键盘输入
KeyEventProc(irInBuf[i].Event.KeyEvent);
break;
case MOUSE_EVENT://鼠标输入
MouseEventProc(irInBuf[i].Event.MouseEvent);
break;
case WINDOW_BUFFER_SIZE_EVENT://RESIZE
ResizeEventProc(irInBuf[i].Event.WindowBufferSizeEvent);
break;
case FOCUS_EVENT://focus事件
case MENU_EVENT://menu事件
break;
default:
printf("unknown event type\n");
break;
}
}
}
return 0;
}
//键盘事件
VOID KeyEventProc(KEY_EVENT_RECORD ker){
CHAR szMsg[256];
wsprintf(szMsg, "KEY_EVENT_RECORD \n char = %c", ker.uChar);
MessageBox(NULL, szMsg, "EVENT", MB_OK);
}
//鼠标事件
VOID MouseEventProc(MOUSE_EVENT_RECORD mer){
CHAR szMsg[256];
wsprintf(szMsg, "MOUSE_EVENT_RECORD\n button state %d\nmouse positionX=%u,Y=%u", mer.dwButtonState, mer.dwMousePosition.X, mer.dwMousePosition.Y);
MessageBox(NULL, szMsg, "EVENT", MB_OK);
if (IDOK == MessageBox(NULL, "Exit?", "EVENT", MB_OKCANCEL)){
ExitProcess(0);
}
}
//重置大小事件
VOID ResizeEventProc(WINDOW_BUFFER_SIZE_RECORD wbsr){
CHAR szMsg[256];
wsprintf(szMsg, "WINDOW_BUFFER_SIZE_RECORD\nX=%u,Y=%u", wbsr.dwSize.X, wbsr.dwSize.Y);
MessageBox(NULL, szMsg, "EVENT", MB_OK);
}