📄 console.h
字号:
void CConsole::_ShowCursor(bool show)
{
CONSOLE_CURSOR_INFO curInfo;
GetConsoleCursorInfo(hOut, &curInfo);
curInfo.bVisible = show;
SetConsoleCursorInfo(hOut, &curInfo);
}
void CConsole::_OutText(char *str, int nch)
{
int x, y;
_GetCursorPos(&x, &y);
_OutTextXY(x, y, str, nch);
}
void CConsole::_OutTextXY(int x, int y, char *str, int nch)
{
_SetCursorPos(x, y);
if (nch<0) nch = strlen(str);
WriteConsole(hOut, str, nch, NULL, NULL);
}
void CConsole::_SaveSettings(void)
{
nSaveColor[0] = _GetBackColor();
nSaveColor[1] = _GetForeColor();
_GetCursorPos(&nSavePos[0], &nSavePos[1]);
CONSOLE_CURSOR_INFO curInfo;
GetConsoleCursorInfo(hOut, &curInfo);
bSaveShow = (curInfo.bVisible>0);
rcSave = rcWindow;
bSaved = true;
}
void CConsole::_LoadSettings(void)
{
if (!bSaved) return;
rcWindow = rcSave;
_SetCursorPos(nSavePos[0], nSavePos[1]);
_SetBackColor(nSaveColor[0]);
_SetForeColor(nSaveColor[1]);
_ShowCursor(bSaveShow);
bSaved = false;
}
void CConsole::_SaveWindow(void)
{
COORD pos = {0, 0};
nMaxCols = rcWindow.Right - rcWindow.Left + 1;
nMaxRows = rcWindow.Bottom - rcWindow.Top + 1;
COORD size = {nMaxCols, nMaxRows};
SMALL_RECT rc = rcWindow;
ReadConsoleOutput(hOut, charInfo, size, pos, &rc);
}
void CConsole::_SaveWindow(CHAR_INFO *buf)
{
COORD pos = {0, 0};
nMaxCols = rcWindow.Right - rcWindow.Left + 1;
nMaxRows = rcWindow.Bottom - rcWindow.Top + 1;
COORD size = {nMaxCols, nMaxRows};
SMALL_RECT rc = rcWindow;
ReadConsoleOutput(hOut, buf, size, pos, &rc);
}
void CConsole::_PutWindow(int absX, int absY)
{
if ((nMaxCols * nMaxRows) <= 0) return;
COORD pos = {0, 0};
COORD size = {nMaxCols, nMaxRows};
SMALL_RECT rc = {absX, absY, absX+nMaxCols-1, absY+nMaxRows-1};
WriteConsoleOutput(hOut, charInfo, size, pos, &rc);
}
void CConsole::_PutWindow(int absX, int absY, CHAR_INFO *buf)
{
if ((nMaxCols * nMaxRows) <= 0) return;
COORD pos = {0, 0};
COORD size = {nMaxCols, nMaxRows};
SMALL_RECT rc = {absX, absY, absX+nMaxCols-1, absY+nMaxRows-1};
WriteConsoleOutput(hOut, buf, size, pos, &rc);
}
unsigned int CConsole::_GetKeyChar(void)
{
INPUT_RECORD keyRec;
DWORD res;
unsigned char ch = 0;
unsigned int vKeyCode = 0;
ReadConsoleInput(hIn, &keyRec, 1, &res);
if (keyRec.EventType == KEY_EVENT){
if (keyRec.Event.KeyEvent.bKeyDown) {
ch = keyRec.Event.KeyEvent.uChar.AsciiChar;
vKeyCode = keyRec.Event.KeyEvent.wVirtualKeyCode;
}
}
if (isprint(ch)) {
vKeyCode = ch<<8;
}
return vKeyCode;
}
int CConsole::_GetMouse(int *mx, int *my, int *state)
{
INPUT_RECORD mouseRec;
DWORD res, flags = 0, btnState = 0;
COORD pos = {0, 0};
int nButton = -1;
ReadConsoleInput(hIn, &mouseRec, 1, &res);
if (mouseRec.EventType == MOUSE_EVENT){
flags = mouseRec.Event.MouseEvent.dwEventFlags;
pos = mouseRec.Event.MouseEvent.dwMousePosition;
btnState = mouseRec.Event.MouseEvent.dwButtonState;
}
if (btnState == FROM_LEFT_1ST_BUTTON_PRESSED) nButton = 1;
if (btnState == RIGHTMOST_BUTTON_PRESSED) nButton = 5;
if (btnState == FROM_LEFT_2ND_BUTTON_PRESSED) nButton = 2;
if (btnState == FROM_LEFT_3RD_BUTTON_PRESSED) nButton = 3;
if (btnState == FROM_LEFT_4TH_BUTTON_PRESSED) nButton = 4;
*state = 0;
if (nButton>=0) *state = 1;
if (flags == DOUBLE_CLICK) *state = 2;
if (flags == MOUSE_MOVED) nButton = 0;
int x = pos.X - rcWindow.Left;
int y = pos.Y - rcWindow.Top;
if (x<0) return -1;
if (y<0) return -1;
*mx =x; *my = y;
return nButton;
}
struct MENUITEM
{
char itemName[100];
char chItem;
int chPos;
int itemPos;
} ;
class CConUI: public CConsole
{
public:
CConUI();
void _SetMainFrameTitle(char *str);
// 设置主框架窗口的标题
void _SetMultiInputTitle(char *str);
// 设置_InputMultiBox的标题
void _SetOptionsTitle(char *str);
// 设置_GetOptions的标题
char _MessageBox(char *caption, char *str, int mode = 0);
// 消息框,caption是消息框的标题,str只能包含\n转义符,mode是不同的配色方案,返回按键字符
// 0: 灰色背景,白色双边框,黑色文本,不显示光标,用于一般信息显示
// 1: 绿色背景,白色双边框,白色文本,不显示光标,用于带有询问的一般信息显示
// 2: 青色背景,黄色双边框,黄色文本,显示光标,用于带有询问的一般警告信息显示,等待输入
// 3: 红色背景,黄色双边框,黄色文本,显示光标,用于带有询问的严重警告信息显示,等待输入
char* _InputBox(char *name, int x, int y, int nchars = 20, bool center = true);
// 在(x, y)处显示一个输入框,name为提示文本,nchars是输入框内能显示的字符个数
// 当按回车键时,返回输入的字符串,否则返回NULL
// 当居中显示时,x,y忽略
bool _InputMultiBox(char **name, int x, int y, int length, char **str, int num, bool center = true);
// 用于指定num个记录的输入, 当最后一个记录按ENTER键后,退出返回true
// 按ESC时,退出返回flase,按TAB键在记录中选择输入
// name为各个记录的提示文本,输入的内容由str返回
// length为输入框的长度
// 当居中显示时,x,y忽略
int _GetOptions(char **str, int x, int y, int num, int *chpos = NULL, bool center = true);
// 返回用户从num个项目中选择一个选项,0表示第一项,依次类推。若没有选择则返回-1
// str指定选项内容,chpos指定相应的str中的选择字符,即当用户按下该字符时表示选中此项。
// 当居中显示时,x,y忽略
void _InitMainFrame( int nMode );
// nMode表示主框架窗口标题栏、底部颜色、背景颜色,边框颜色、边框模式等方案
// nMode 背景颜色 标题栏颜色 底部颜色 边框颜色 边框模式
// 0 深灰(8) 蓝(1)白(15) 灰(7)黑(0) 灰(7) 上单余双
// 1 蓝(1) 灰(7)黑(0) 灰(7)黑(0) 白(15) 上单余双
// 2 绿(2) 蓝(1)白(15) 灰(7)黑(0) 白(15) 上单余双
// 3 深灰(8) 蓝(1)白(15) 灰(7)黑(0) 灰(7) 下单余双
// 4 蓝(1) 灰(7)黑(0) 灰(7)黑(0) 白(15) 下单余双
// 5 绿(2) 蓝(1)白(15) 灰(7)黑(0) 白(15) 下单余双
// 6 深灰(8) 蓝(1)白(15) 灰(7)黑(0) 灰(7) 左右双余单
// 7 蓝(1) 灰(7)黑(0) 灰(7)黑(0) 白(15) 左右双余单
// 8 绿(2) 蓝(1)黑(0) 灰(7)黑(0) 白(15) 左右双余单
private:
int m_nMenuItemNum; // 选择的菜单项
MENUITEM menuItem[40]; // 菜单项
// 下面的颜色用于界面配色
int m_nControlColor[2]; // 控件颜色对
int m_nFrameColor[2]; // 框架颜色对
int m_nMenuColor[3]; // 菜单颜色对
char m_InputChars[256];
char m_strMultiTitle[100];
char m_strOptionsTitle[100];
char m_strMainFrameTitle[100]; // 主框架标题
int m_nCharNum;
char m_MultiInputChars[40][256];
int m_nMultiCharNum[40];
int m_nMultiNum;
int _InputLine(int x, int y, int nlength, int bkcolor, int focolor,
char *str, int *nchars);
//返回0表示OK,-1表示ESC, 1表示TAB, 2表示UP, 3表示DOWN
void _CalCenterWindow(int *x1, int *y1, int *x2, int *y2);
// 重新计算窗口,使得窗口在屏幕居中
};
// CConUI类的实现
CConUI::CConUI()
:m_nCharNum(0), m_nMultiNum(0)
{
strcpy(m_strMultiTitle, " Input ");
strcpy(m_strOptionsTitle, " Select ");
strcpy(m_strMainFrameTitle, " Main "); // 设置默认的主框架标题
m_nFrameColor[0] = 7; m_nFrameColor[1] = 15;
m_nControlColor[0] = 7; m_nControlColor[1] = 0;
m_nMenuColor[0] = 0; m_nMenuColor[1] = 15; m_nMenuColor[2] = 4;
}
void CConUI::_SetMainFrameTitle(char *str)
{
strcpy(m_strMainFrameTitle, str);
}
void CConUI::_SetMultiInputTitle(char *str)
{
strcpy(m_strMultiTitle, str);
}
void CConUI::_SetOptionsTitle(char *str)
{
strcpy(m_strOptionsTitle, str);
}
void CConUI::_InitMainFrame( int nMode )
{
if (nMode<0) nMode = -nMode;
char strBottom[] = "TextMode Interface Designed By DingYouHe, 4/28/2006";
// 保存原来的设置
_SaveSettings();
// 获取控制台窗口大小
int nMaxX, nMaxY;
_GetConwinSize( &nMaxX, &nMaxY );
// 构造颜色方案和边框方案
int nBoxMode, nBoxColor, nBottomColor[2], nTitleColor[2], nBackColor;
nBoxMode = nMode/3 + 3;
int nIndex = nMode % 3;
switch (nIndex) {
case 0:
nBoxColor = 7;
nBottomColor[0] = 7; nBottomColor[1] = 0;
nTitleColor[0] = 1; nTitleColor[1] = 15;
nBackColor = 8;
break;
case 1:
nBoxColor = 15;
nBottomColor[0] = 7; nBottomColor[1] = 0;
nTitleColor[0] = 7; nTitleColor[1] = 0;
nBackColor = 1;
break;
case 2:
nBoxColor = 15;
nBottomColor[0] = 7; nBottomColor[1] = 0;
nTitleColor[0] = 1; nTitleColor[1] = 15;
nBackColor = 2;
break;
}
_DefineWindow( 0, 0, nMaxX, nMaxY );
// 填充整个框架
_SetBackColor( nBackColor );
_FillBox( 0, 0, nMaxX, nMaxY );
// 绘制标题
_SetBackColor(nTitleColor[0]);
_SetForeColor(nTitleColor[1]);
_FillBox( 0, 0, nMaxX, 1 );
_OutTextXY((nMaxX - strlen(m_strMainFrameTitle))/2, 0, m_strMainFrameTitle);
// 绘制底部
_SetBackColor(nBottomColor[0]);
_SetForeColor(nBottomColor[1]);
_FillBox( 0, nMaxY-1, nMaxX, 1 );
_OutTextXY(nMaxX - strlen(strBottom)-10, nMaxY-1, strBottom);
// 绘制边框
_SetBackColor(nBackColor);
_SetForeColor(nBoxColor);
_DrawBox( 0, 1, nMaxX, nMaxY-2, nBoxMode );
// 恢复原来的设置
_LoadSettings();
_DefineWindow( 1, 2, nMaxX-1, nMaxY-3 );
_SetBackColor( nBackColor );
_SetForeColor(15);
}
bool CConUI::_InputMultiBox(char **name, int x, int y, int length, char **str, int num, bool center)
{
if (num>40) num = 40;
CHAR_INFO buf[100*40];
// 计算最长提示文本的字符个数
unsigned int nNameSize = 0;
for (int i=0; i<num; i++) {
if (nNameSize<strlen(name[i])) nNameSize = strlen(name[i]);
m_nMultiCharNum[i] = 0;
}
// 计算所需要的窗口大小
int x1, x2, y1, y2;
x1 = x; y1 = y;
x2 = x1 + nNameSize + length + 4;
y2 = y1 + num*3 + 1;
if (center)
_CalCenterWindow(&x1, &y1, &x2, &y2);
_SaveSettings();
_DefineWindow(x1, y1, x2+1, y2+1); // 重新定义窗口
_SaveWindow(buf);
_DefineWindow(x1+1, y1+1, x2+1, y2+1); // 重新定义窗口
_SetBackColor(8);
_FillBox(0,0, x2-x1+1, y2-y1+1,false); // 阴影
_DefineWindow(x1, y1, x2, y2); // 重新定义窗口
// 绘制窗口
_SetBackColor(m_nFrameColor[0]);
_SetForeColor(m_nFrameColor[1]);
_ClearWindow();
_DrawBox(0, 0, x2-x1+1, y2-y1+1, 2);
int posX, posY;
for (i=1; i<=num; i++) {
int strSize = strlen(name[i-1]);
posX = nNameSize - strSize + 2;
posY = 3*i - 1;
_OutTextXY(posX, posY, name[i-1], strSize);
_DrawBox(nNameSize+2, posY-1, length+1, 3);
}
_OutTextXY(3, 0, m_strMultiTitle);
_LoadSettings();
bool bRes = false;
// 一些初始化
m_nCharNum = 0;
m_nMultiNum = num;
int nMultiPC = 0; // 记录索引
posX = x2 - length - 1;
for (;;)
{
posY = y1 + 2 + nMultiPC * 3;
int nRes = _InputLine(posX, posY, length-1, m_nControlColor[0], m_nControlColor[1],
m_MultiInputChars[nMultiPC], &m_nMultiCharNum[nMultiPC]);
if (nRes == -1) // 按下ESC键,退出
break;
if ((nRes == 0)&&(nMultiPC == (num-1)))
{
bRes = true;
break;
}
if (nRes == 2) //UP
nMultiPC--;
else
nMultiPC++;
if (nMultiPC<0) nMultiPC = num-1;
if (nMultiPC>(num-1)) nMultiPC = 0;
m_nCharNum = m_nMultiCharNum[nMultiPC];
strncpy(m_InputChars, m_MultiInputChars[nMultiPC], m_nCharNum);
}
_PutWindow(x1, y1, buf);
if (bRes) { // 返回字符串
for (i=0; i<num; i++){
int n = m_nMultiCharNum[i];
*str = new char[n+1];
strncpy(*str, m_MultiInputChars[i], n);
(*str)[n] = '\0';
str++;
}
} else
{
for (i=0; i<num; i++){
*str = new char[1];
strcpy(*str, "");
str++;
}
}
return bRes;
}
char CConUI::_MessageBox(char *caption, char *str, int mode)
{
char chRes;
int chPos[40];
unsigned int nNum = 1;
// 记录str中\n字符的位置
chPos[0] = 0;
for (unsigned int i=0; i<strlen(str); i++)
{
if (str[i]=='\n') {
chPos[nNum] = i+1;
nNum++;
}
}
chPos[nNum] = i;
// 计算最长行的字符长度
int nSize = 0;
for (i=0; i<nNum; i++) {
if (nSize < (chPos[i+1] - chPos[i] + 1))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -