#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);
}