first commit
This commit is contained in:
@@ -0,0 +1,62 @@
|
|||||||
|
# conctrl
|
||||||
|
## 简介
|
||||||
|
  这个库提供一系列的函数来简化对Windows控制台窗口的输入输出(主要是输出)控制。通过它,你可以将窗口分割为不同的窗格,你也可以创建分隔线来分隔它们。而不管是窗口、窗格还是分隔线,你可以随时修改它们的大小和位置。
|
||||||
|
|
||||||
|
## 特性
|
||||||
|
  你可以将控制台窗口分割为若干个**窗格**,窗格之间可创建**分割线**来区别它们。每个窗格拥有一个行缓存,包含若干**行**。你可以改变行缓存的大小。
|
||||||
|
|
||||||
|
  你可以动态地为**窗格**增加**行**,仅需要向窗格添加文本,窗格将自动把文本分割为适应的行,改变窗格大小它也将自动更新。
|
||||||
|
|
||||||
|
  你可以为每一**行**设定字符格式,字符格式由Windows的一些<a href="#constant">常量</a>定义。
|
||||||
|
|
||||||
|
## 开发环境
|
||||||
|
  Windows,Visual Studio 2017
|
||||||
|
|
||||||
|
## 说明
|
||||||
|
  需要注意的是,窗格只是逻辑意义上的窗格,它们属于同一个控制台窗口,共享输入缓冲区,因此这个库仅**适用于需要多个窗格用于输出**而不超过1个窗格同时用来输入。
|
||||||
|
|
||||||
|
  构建这个库的初衷是为了方便某些高级语言操作控制台,因此将它的导出函数的参数都设定为简单的数值型和字符串,避免在高级语言中额外定义数据类型,方便使用。
|
||||||
|
|
||||||
|
  此库通过调用Windows API实现,因此仅适用于Windows系统。
|
||||||
|
|
||||||
|
## 缺陷
|
||||||
|
* 对用户输入的控制比较无力
|
||||||
|
* 只能对整行设定字符样式
|
||||||
|
* 其他
|
||||||
|
|
||||||
|
## 使用示例
|
||||||
|
* ### C/C++
|
||||||
|
|
||||||
|
* ### 其他语言
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 函数列表
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 辅助资料
|
||||||
|
<a name="constant"> </a>
|
||||||
|
|
||||||
|
### Windows控制台字符样式常量
|
||||||
|
```C
|
||||||
|
#define FOREGROUND_BLUE 0x0001 // text color contains blue.
|
||||||
|
#define FOREGROUND_GREEN 0x0002 // text color contains green.
|
||||||
|
#define FOREGROUND_RED 0x0004 // text color contains red.
|
||||||
|
#define FOREGROUND_INTENSITY 0x0008 // text color is intensified.
|
||||||
|
#define BACKGROUND_BLUE 0x0010 // background color contains blue.
|
||||||
|
#define BACKGROUND_GREEN 0x0020 // background color contains green.
|
||||||
|
#define BACKGROUND_RED 0x0040 // background color contains red.
|
||||||
|
#define BACKGROUND_INTENSITY 0x0080 // background color is intensified.
|
||||||
|
#define COMMON_LVB_LEADING_BYTE 0x0100 // Leading Byte of DBCS
|
||||||
|
#define COMMON_LVB_TRAILING_BYTE 0x0200 // Trailing Byte of DBCS
|
||||||
|
#define COMMON_LVB_GRID_HORIZONTAL 0x0400 // DBCS: Grid attribute: top horizontal.
|
||||||
|
#define COMMON_LVB_GRID_LVERTICAL 0x0800 // DBCS: Grid attribute: left vertical.
|
||||||
|
#define COMMON_LVB_GRID_RVERTICAL 0x1000 // DBCS: Grid attribute: right vertical.
|
||||||
|
#define COMMON_LVB_REVERSE_VIDEO 0x4000 // DBCS: Reverse fore/back ground attribute.
|
||||||
|
#define COMMON_LVB_UNDERSCORE 0x8000 // DBCS: Underscore.
|
||||||
|
#define COMMON_LVB_SBCSDBCS 0x0300 // SBCS or DBCS flag.
|
||||||
|
```
|
||||||
|
|
||||||
|
## 项目地址
|
||||||
|
[https://github.com/mattuy/conctrl.git](https://github.com/mattuy/conctrl.git)
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#include <string>
|
||||||
|
#include <string.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include "coding.h"
|
||||||
|
|
||||||
|
//将utf8编码的文本转换为ANSI编码(GBK)
|
||||||
|
std::string UTF8ToANSI(const char* str) {
|
||||||
|
//统计字符数
|
||||||
|
int wideCharCount = MultiByteToWideChar(CP_UTF8, 0, str, strlen(str), NULL, 0);
|
||||||
|
if (wideCharCount == 0) {
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
//为Unicode缓冲区申请空间
|
||||||
|
wchar_t* wideCharBufer = (wchar_t*)malloc(sizeof(wchar_t) * wideCharCount);
|
||||||
|
//转换成Unicode
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, str, strlen(str), wideCharBufer, wideCharCount);
|
||||||
|
//转换为ANSI
|
||||||
|
int multiByteCharCount = WideCharToMultiByte(CP_ACP, 0, wideCharBufer, wideCharCount, NULL, 0, NULL, NULL);
|
||||||
|
char* mutiByteCharBuffer = (char*)malloc(sizeof(char) * multiByteCharCount);
|
||||||
|
int result = WideCharToMultiByte(CP_ACP, 0, wideCharBufer, wideCharCount, mutiByteCharBuffer, multiByteCharCount, NULL, NULL);
|
||||||
|
if (!result)
|
||||||
|
return "???";
|
||||||
|
std::string text(mutiByteCharBuffer);
|
||||||
|
free(mutiByteCharBuffer);
|
||||||
|
free(wideCharBufer);
|
||||||
|
return text;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _HEAD_CODING_
|
||||||
|
#define _HEAD_CODING_
|
||||||
|
#include <windows.h>
|
||||||
|
std::string UTF8ToANSI(const char* str);
|
||||||
|
|
||||||
|
#endif // !_HEAD_CODING_
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include "conctrl.h"
|
||||||
|
|
||||||
|
//创建当前控制台窗口对应的控制窗口
|
||||||
|
ConsoleWindow* CreateConsoleWindow(int width, int height) {
|
||||||
|
if (width <= 5 || height <= 5 || width > 32767 || height > 32767)
|
||||||
|
return new(std::nothrow) ConsoleWindow();
|
||||||
|
else
|
||||||
|
return new(std::nothrow) ConsoleWindow(width, height);
|
||||||
|
}
|
||||||
|
//重新设置窗口和缓冲区大小
|
||||||
|
bool ResizeConsoleWindow(ConsoleWindow* window, int width, int height) {
|
||||||
|
if (width <= 5 || height <= 5 || width > 32767 || height > 32767)
|
||||||
|
return false;
|
||||||
|
return window->Resize({ (SHORT)width, (SHORT)height });
|
||||||
|
}
|
||||||
|
//设置控制台窗口标题
|
||||||
|
bool SetConsoleWindowTitle(char* _title, bool utf8) {
|
||||||
|
if (utf8) {
|
||||||
|
std::string title;
|
||||||
|
title = UTF8ToANSI(_title);
|
||||||
|
return SetConsoleTitle(title.c_str());
|
||||||
|
}
|
||||||
|
return SetConsoleTitle(_title);
|
||||||
|
}
|
||||||
|
//创建一个窗格
|
||||||
|
Pannel* CreatePannel(ConsoleWindow* window, int left, int top, int width, int height) {
|
||||||
|
if (left < 0 || top < 0 || width <= 5 || height <= 5
|
||||||
|
|| left > 32767 || top > 32767 || width > 32767 || height > 32767
|
||||||
|
) return NULL;
|
||||||
|
return window->NewPannel({ (SHORT)left, (SHORT)top, (SHORT)width - 1, (SHORT)height - 1 });
|
||||||
|
}
|
||||||
|
//删除窗格
|
||||||
|
void DestroyPannel(ConsoleWindow* window, Pannel* pannel) {
|
||||||
|
window->RemovePannel(pannel);
|
||||||
|
}
|
||||||
|
//设置Pannel行缓存大小
|
||||||
|
bool SetMaxLineCache(Pannel* pannel, int lineCount) {
|
||||||
|
if (lineCount < 0) return false;
|
||||||
|
pannel->maxLineCount = lineCount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//向Pannel中添加文本
|
||||||
|
void AddPannelText(Pannel* pannel, const char* _text, bool utf8, int attribute) {
|
||||||
|
std::string text;
|
||||||
|
if (utf8) text = UTF8ToANSI(_text);
|
||||||
|
else text = _text;
|
||||||
|
pannel->AddText(text, attribute);
|
||||||
|
}
|
||||||
|
//向Pannel中添加行
|
||||||
|
void AddPannelLine(Pannel* pannel, const char* _text, bool utf8, int attribute) {
|
||||||
|
std::string text;
|
||||||
|
if (utf8) text = UTF8ToANSI(_text);
|
||||||
|
else text = _text;
|
||||||
|
pannel->AddLine(text, attribute);
|
||||||
|
}
|
||||||
|
//清空Pannel
|
||||||
|
void ClearPannel(Pannel* pannel) {
|
||||||
|
pannel->Clear();
|
||||||
|
}
|
||||||
|
//移动或改变Pannel大小
|
||||||
|
bool MovePannel(Pannel* pannel, int left, int top, int width, int height) {
|
||||||
|
if(left > 32767 || top > 32767 || width > 32767 || height > 32767) return false;
|
||||||
|
if (left < 0) left = pannel->area.Left;
|
||||||
|
if (top < 0) top = pannel->area.Top;
|
||||||
|
if (width <= 5) width = pannel->area.Right - pannel->area.Left + 1;
|
||||||
|
if (height <= 5) height = pannel->area.Bottom - pannel->area.Top+ 1;
|
||||||
|
pannel->Move({ (SHORT)left, (SHORT)top, (SHORT)width - 1, (SHORT)height - 1});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//向前滚屏
|
||||||
|
bool ScrollPannelBackward(Pannel* pannel, int lineCount) {
|
||||||
|
return pannel->ScrollBackward(lineCount);
|
||||||
|
}
|
||||||
|
//向后滚屏
|
||||||
|
bool ScrollPannelForward(Pannel* pannel, int lineCount) {
|
||||||
|
return pannel->ScrollForward(lineCount);
|
||||||
|
}
|
||||||
|
//滚动到特定行
|
||||||
|
bool ScrollPannelTo(Pannel* pannel, int lineTo) {
|
||||||
|
return pannel->ScrollTo(lineTo);
|
||||||
|
}
|
||||||
|
//将光标设置到窗格的特定位置
|
||||||
|
bool FocusOnPannel(Pannel* pannel, int offsetLeft, int offsetTop) {
|
||||||
|
return pannel->Focus({ (SHORT)offsetLeft, (SHORT)offsetTop});
|
||||||
|
}
|
||||||
|
//创建一条分隔线。
|
||||||
|
Spliter* CreateSpliter(ConsoleWindow* window, int left, int top, int length, bool verticle, int attribute) {
|
||||||
|
if (length <= 0
|
||||||
|
|| left < 0 || left >= window->bufferSize.X
|
||||||
|
|| top < 0 || top >= window->bufferSize.Y
|
||||||
|
) return NULL;
|
||||||
|
return window->NewSpliter({ (SHORT)left, (SHORT)top}, length, verticle, attribute);
|
||||||
|
}
|
||||||
|
//删除分隔线
|
||||||
|
void DestroySpliter(ConsoleWindow* window, Spliter* spliter) {
|
||||||
|
window->RemoveSpliter(spliter);
|
||||||
|
}
|
||||||
|
//移动或重新设定分隔线长度
|
||||||
|
bool MoveSpliter(Spliter* spliter, int left, int top, int len) {
|
||||||
|
if (left < 0 || left > 32767 || top < 0 || top > 32767 || len < 0) return false;
|
||||||
|
spliter->Move({ (SHORT)left, (SHORT)top }, len);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
LIBRARY conctrl
|
||||||
|
EXPORTS
|
||||||
|
|
||||||
|
CreateConsoleWindow
|
||||||
|
ResizeConsoleWindow
|
||||||
|
SetConsoleWindowTitle
|
||||||
|
CreatePannel
|
||||||
|
DestroyPannel
|
||||||
|
SetMaxLineCache
|
||||||
|
AddPannelText
|
||||||
|
AddPannelLine
|
||||||
|
ClearPannel
|
||||||
|
MovePannel
|
||||||
|
ScrollPannelBackward
|
||||||
|
ScrollPannelForward
|
||||||
|
ScrollPannelTo
|
||||||
|
FocusOnPannel
|
||||||
|
CreateSpliter
|
||||||
|
DestroySpliter
|
||||||
|
MoveSpliter
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
// ConsoleController
|
||||||
|
// 2018-11-28
|
||||||
|
// By Mattuy
|
||||||
|
|
||||||
|
#ifndef _HEAD_CONSOLE_CONTROLLER_
|
||||||
|
#define _HEAD_CONSOLE_CONTROLLER_
|
||||||
|
#include "console_window.h"
|
||||||
|
#include "pannel.h"
|
||||||
|
#include "spliter.h"
|
||||||
|
#include "coding.h"
|
||||||
|
/**
|
||||||
|
* 创建控制台控制器
|
||||||
|
* @return value, 指向当前控制台的控制台操作对象的指针,作为其他函数的参数,以通过它控制
|
||||||
|
* 控制台。失败返回0
|
||||||
|
* @param width, 控制台窗口宽度,有效范围(5, 32767),默认80
|
||||||
|
* @param height, 控制台窗口高度,有效范围(5, 32767),默认40
|
||||||
|
*/
|
||||||
|
ConsoleWindow* CreateConsoleWindow(int width = 80, int height = 40);
|
||||||
|
//重新设置窗口和缓冲区大小
|
||||||
|
bool ResizeConsoleWindow(ConsoleWindow* window, int width, int height);
|
||||||
|
/**
|
||||||
|
* 设置控制台窗口标题
|
||||||
|
* @param window, 要设置标题的窗口
|
||||||
|
* @param title, 要设置的标题
|
||||||
|
* @param utf8, 是否utf8编码。UTF-8请设为非0,否则当作ANSI处理
|
||||||
|
*/
|
||||||
|
bool SetConsoleWindowTitle(char* title, bool utf8 = false);
|
||||||
|
/**
|
||||||
|
* 创建一个窗格。
|
||||||
|
* @return value, 指向一个窗格的指针
|
||||||
|
* @param window, 窗格所属窗口
|
||||||
|
* @param left, 窗格相对窗口的水平偏移,有效范围(5, 32767)
|
||||||
|
* @param top, 窗格相对窗口的竖直偏移,有效范围(5, 32767)
|
||||||
|
* @param width, 窗格的宽度,有效范围(5, 32767)
|
||||||
|
* @param height, 窗格的高度,有效范围(5, 32767)
|
||||||
|
*/
|
||||||
|
Pannel* CreatePannel(ConsoleWindow* window, int left, int top, int width, int height);
|
||||||
|
//删除窗格
|
||||||
|
void DestroyPannel(ConsoleWindow* window, Pannel* pannel);
|
||||||
|
//设置窗格行缓存大小(行数)
|
||||||
|
bool SetlMaxLineCache(Pannel* pannel, int lineCount);
|
||||||
|
/**
|
||||||
|
* 向Pannel中添加文本。如果行缓冲区中上一行不是换行符结尾或调用【AddPannelLine】函数添加的,新
|
||||||
|
* 文本将合并到上一行。原文本属性也会被覆盖。
|
||||||
|
* @param window, 窗格所属窗口
|
||||||
|
* @param text, 要添加的字符串
|
||||||
|
* @param utf8, 是否utf8编码。仅支持ANSI编码和UTF-8编码,并且UTF-8编码也将被转换为ANSI
|
||||||
|
* 编码。默认为false
|
||||||
|
* @param attribute, 行文本属性,由Windows定义的控制台常量,默认黑底白字
|
||||||
|
*/
|
||||||
|
void AddPannelText(Pannel* pannel, const char* text, bool utf8 = false, int attribute = 7);
|
||||||
|
//与AddText唯一的不同是,如果字符串不是以换行符结尾,将自动插入换行符
|
||||||
|
void AddPannelLine(Pannel* pannel, const char* text, bool utf8 = false, int attribute = 7);
|
||||||
|
//清空Pannel。这将同时清除pannel的行缓冲区
|
||||||
|
void ClearPannel(Pannel* pannel);
|
||||||
|
//移动或改变Pannel大小,参数同【CreatePannel】。如果参数分量无效,该分量将不会改变
|
||||||
|
bool MovePannel(Pannel* pannel, int left, int top, int width, int height);
|
||||||
|
/**
|
||||||
|
* 向前滚屏。
|
||||||
|
* @return value, 如果滚动前已触顶返回false,否则返回true
|
||||||
|
* @param pannel, 要滚动的窗格
|
||||||
|
* @param lineCount, 要滚动的行数,如果小于0滚动一屏(相对窗格)
|
||||||
|
*/
|
||||||
|
bool ScrollPannelBackward(Pannel* pannel, int lineCount);
|
||||||
|
//向后滚屏。
|
||||||
|
bool ScrollPannelForward(Pannel* pannel, int lineCount);
|
||||||
|
//滚动到特定行。如果行号小于0滚到最后,否则如果行号无效返回false
|
||||||
|
bool ScrollPannelTo(Pannel* pannel, int lineTo);
|
||||||
|
/**
|
||||||
|
* 将光标设置到窗格的特定位置。
|
||||||
|
* @return value, 如果offset超出窗格范围则设置失败
|
||||||
|
* @param pannel, 要设置光标所在的窗格
|
||||||
|
* @param offsetLeft, 光标相对窗格左上角的水平偏移,默认为0
|
||||||
|
* @param offsetTop, 光标相对窗格左上角的垂直偏移,默认为0
|
||||||
|
*/
|
||||||
|
bool FocusOnPannel(Pannel* pannel, int offsetLeft = 0, int offsetTop = 0);
|
||||||
|
/**
|
||||||
|
* 创建一条分隔线。
|
||||||
|
* @return value, 指向一条分隔线的指针
|
||||||
|
* @param window, 窗格所属的窗口
|
||||||
|
* @param left, 分隔线相对窗口的水平偏移,有效范围(5, 32767)
|
||||||
|
* @param top, 分隔线相对窗口的竖直偏移,有效范围(5, 32767)
|
||||||
|
* @param length, 分割线的长度或宽度。是前者还是后者取决于@param verticle
|
||||||
|
* @param verticle, 是水平分隔线还是竖直分隔线。0为水平,非0为竖直
|
||||||
|
* @param attribute, 分割线的文本属性,由Windows定义的控制台常量,默认黑底白字
|
||||||
|
*/
|
||||||
|
Spliter* CreateSpliter(ConsoleWindow* window, int left, int top, int length, bool verticle, int attribute = 7);
|
||||||
|
//删除分隔线
|
||||||
|
void DestroySpliter(Spliter* spliter);
|
||||||
|
/**
|
||||||
|
* 移动或重新设定分隔线的长度
|
||||||
|
* @param left, 相对窗格的水平偏移,如果小于0则不改变
|
||||||
|
* @param top, 相对窗口的垂直偏移,如果小于0则不改变
|
||||||
|
* @param len, 新的长度/高度。如果小于0则不改变
|
||||||
|
*/
|
||||||
|
bool MoveSpliter(int left, int top, int len);
|
||||||
|
#endif // !_HEAD_CONSOLE_CONTROLLER_
|
||||||
+18
-17
@@ -18,6 +18,24 @@
|
|||||||
<Platform>x64</Platform>
|
<Platform>x64</Platform>
|
||||||
</ProjectConfiguration>
|
</ProjectConfiguration>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="coding.cpp" />
|
||||||
|
<ClCompile Include="conctrl.cpp" />
|
||||||
|
<ClCompile Include="console_window.cpp" />
|
||||||
|
<ClCompile Include="pannel.cpp" />
|
||||||
|
<ClCompile Include="spliter.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="coding.h" />
|
||||||
|
<ClInclude Include="conctrl.h" />
|
||||||
|
<ClInclude Include="console_window.h" />
|
||||||
|
<ClInclude Include="pannel.h" />
|
||||||
|
<ClInclude Include="spliter.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="conctrl.def" />
|
||||||
|
<None Include="README.md" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<VCProjectVersion>15.0</VCProjectVersion>
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
<ProjectGuid>{4830BECE-AD04-4FE9-AED7-74A4492BBF32}</ProjectGuid>
|
<ProjectGuid>{4830BECE-AD04-4FE9-AED7-74A4492BBF32}</ProjectGuid>
|
||||||
@@ -114,23 +132,6 @@
|
|||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="C:\Users\Master\OneDrive\Code\ConsoleController\coding.h" />
|
|
||||||
<ClInclude Include="C:\Users\Master\OneDrive\Code\ConsoleController\conctrl.h" />
|
|
||||||
<ClInclude Include="C:\Users\Master\OneDrive\Code\ConsoleController\console_window.h" />
|
|
||||||
<ClInclude Include="C:\Users\Master\OneDrive\Code\ConsoleController\pannel.h" />
|
|
||||||
<ClInclude Include="C:\Users\Master\OneDrive\Code\ConsoleController\spliter.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="C:\Users\Master\OneDrive\Code\ConsoleController\coding.cpp" />
|
|
||||||
<ClCompile Include="C:\Users\Master\OneDrive\Code\ConsoleController\conctrl.cpp" />
|
|
||||||
<ClCompile Include="C:\Users\Master\OneDrive\Code\ConsoleController\console_window.cpp" />
|
|
||||||
<ClCompile Include="C:\Users\Master\OneDrive\Code\ConsoleController\pannel.cpp" />
|
|
||||||
<ClCompile Include="C:\Users\Master\OneDrive\Code\ConsoleController\spliter.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="C:\Users\Master\OneDrive\Code\ConsoleController\conctrl.def" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
|||||||
@@ -15,41 +15,44 @@
|
|||||||
</Filter>
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="C:\Users\Master\OneDrive\Code\ConsoleController\coding.h">
|
<ClCompile Include="coding.cpp">
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="C:\Users\Master\OneDrive\Code\ConsoleController\conctrl.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="C:\Users\Master\OneDrive\Code\ConsoleController\pannel.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="C:\Users\Master\OneDrive\Code\ConsoleController\spliter.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="C:\Users\Master\OneDrive\Code\ConsoleController\console_window.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="C:\Users\Master\OneDrive\Code\ConsoleController\conctrl.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="C:\Users\Master\OneDrive\Code\ConsoleController\pannel.cpp">
|
<ClCompile Include="conctrl.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="C:\Users\Master\OneDrive\Code\ConsoleController\spliter.cpp">
|
<ClCompile Include="console_window.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="C:\Users\Master\OneDrive\Code\ConsoleController\coding.cpp">
|
<ClCompile Include="pannel.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="C:\Users\Master\OneDrive\Code\ConsoleController\console_window.cpp">
|
<ClCompile Include="spliter.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="C:\Users\Master\OneDrive\Code\ConsoleController\conctrl.def">
|
<ClInclude Include="coding.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="conctrl.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="pannel.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="spliter.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="console_window.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="conctrl.def">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="README.md">
|
||||||
<Filter>Resource Files</Filter>
|
<Filter>Resource Files</Filter>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
#include "console_window.h"
|
||||||
|
|
||||||
|
ConsoleWindow::ConsoleWindow(SHORT width, SHORT height) {
|
||||||
|
this->bufferSize = { width, height };
|
||||||
|
InitWindow();
|
||||||
|
}
|
||||||
|
ConsoleWindow::~ConsoleWindow() {
|
||||||
|
for (size_t i = 0; i < this->pannels.size(); i++) delete pannels.at(i);
|
||||||
|
for (size_t i = 0; i < this->spliters.size(); i++) delete spliters.at(i);
|
||||||
|
}
|
||||||
|
//初始化
|
||||||
|
bool ConsoleWindow::InitWindow() {
|
||||||
|
this->hInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
this->hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
this->hError = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
if (!this->hInput || !this->hOutput || !this->hError)
|
||||||
|
return false;
|
||||||
|
this->Resize(this->bufferSize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//重新设定窗口缓冲区大小
|
||||||
|
bool ConsoleWindow::Resize(COORD size) {
|
||||||
|
//记录原来的窗口信息
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||||
|
GetConsoleScreenBufferInfo(this->hOutput, &info);
|
||||||
|
//设置缓冲区大小
|
||||||
|
//先将窗口设置得小一点,因为设置的缓冲区大小必须大于窗口大小
|
||||||
|
SMALL_RECT rect = { 0, 0, 5, 5 };
|
||||||
|
if (!SetConsoleWindowInfo(this->hOutput, true, &rect))
|
||||||
|
return false;
|
||||||
|
if (!SetConsoleScreenBufferSize(hOutput, { size.X, size.Y })) {
|
||||||
|
SetConsoleWindowInfo(this->hOutput, true, &info.srWindow); //还原窗口
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//设置窗口大小
|
||||||
|
rect = { 0, 0, size.X - 1, size.Y - 1 };
|
||||||
|
SetConsoleWindowInfo(this->hOutput, true, &rect);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//创建窗格
|
||||||
|
Pannel* ConsoleWindow::NewPannel(SMALL_RECT rect) {
|
||||||
|
Pannel* pannel = new Pannel(this, rect);
|
||||||
|
if(pannel) this->pannels.push_back(pannel);
|
||||||
|
return pannel;
|
||||||
|
}
|
||||||
|
//创建分割线
|
||||||
|
Spliter* ConsoleWindow::NewSpliter(COORD pos, SHORT len, bool verticle, WORD attr) {
|
||||||
|
Spliter* spliter = new Spliter(this, pos, len, verticle, attr);
|
||||||
|
if (spliter) this->spliters.push_back(spliter);
|
||||||
|
return spliter;
|
||||||
|
}
|
||||||
|
//移除窗格
|
||||||
|
void ConsoleWindow::RemovePannel(Pannel* pannel) {
|
||||||
|
for (size_t i = 0; i < this->pannels.size(); i++) {
|
||||||
|
if (this->pannels.at(i) == pannel) {
|
||||||
|
delete this->pannels.at(i);
|
||||||
|
this->pannels.erase(this->pannels.begin() + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//移除分割线
|
||||||
|
void ConsoleWindow::RemoveSpliter(Spliter* spliter) {
|
||||||
|
for (size_t i = 0; i < this->spliters.size(); i++) {
|
||||||
|
if (this->spliters.at(i) == spliter) {
|
||||||
|
delete this->spliters.at(i);
|
||||||
|
this->spliters.erase(this->spliters.begin() + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef _HEAD_CONSOLE_WINDOW_
|
||||||
|
#define _HEAD_CONSOLE_WINDOW_
|
||||||
|
#include <windows.h>
|
||||||
|
#include <vector>
|
||||||
|
#include "pannel.h"
|
||||||
|
#include "spliter.h"
|
||||||
|
|
||||||
|
class ConsoleWindow {
|
||||||
|
public:
|
||||||
|
//控制台句柄
|
||||||
|
HANDLE hInput;
|
||||||
|
HANDLE hOutput;
|
||||||
|
HANDLE hError;
|
||||||
|
//缓冲区大小
|
||||||
|
COORD bufferSize;
|
||||||
|
ConsoleWindow(SHORT width = 80, SHORT height = 40);
|
||||||
|
~ConsoleWindow();
|
||||||
|
//初始化控制台窗口参数
|
||||||
|
bool InitWindow();
|
||||||
|
//设置窗口大小
|
||||||
|
bool Resize(COORD size);
|
||||||
|
//创建窗格
|
||||||
|
Pannel* NewPannel(SMALL_RECT rect);
|
||||||
|
//创建分割线
|
||||||
|
Spliter* NewSpliter(COORD pos, SHORT len, bool verticle, WORD attr = 2);
|
||||||
|
//移除窗格
|
||||||
|
void RemovePannel(Pannel* pannel);
|
||||||
|
//移除分割线
|
||||||
|
void RemoveSpliter(Spliter* spliter);
|
||||||
|
private:
|
||||||
|
//窗格
|
||||||
|
std::vector<Pannel*> pannels;
|
||||||
|
//分割线
|
||||||
|
std::vector<Spliter*> spliters;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,217 @@
|
|||||||
|
#include "console_window.h"
|
||||||
|
#include "pannel.h"
|
||||||
|
|
||||||
|
Pannel::Pannel(ConsoleWindow* _controller, SMALL_RECT rect) {
|
||||||
|
this->window = _controller;
|
||||||
|
this->area = rect;
|
||||||
|
this->from = -1; //默认打印最新行
|
||||||
|
this->maxLineCount = 4096;
|
||||||
|
}
|
||||||
|
//设置最大行数
|
||||||
|
void Pannel::SetMaxLine(SHORT lineCount) {
|
||||||
|
if (lineCount < 0) lineCount = 0;
|
||||||
|
this->maxLineCount = lineCount;
|
||||||
|
if (this->lines.size() > (size_t)maxLineCount) {
|
||||||
|
std::vector<Line>::iterator from = this->lines.begin() + this->lines.size() - maxLineCount;
|
||||||
|
std::vector<Line>::iterator to = this->lines.begin();
|
||||||
|
do {
|
||||||
|
*(to++) = *(from++);
|
||||||
|
} while (from != this->lines.end());
|
||||||
|
} //移除超出行
|
||||||
|
}
|
||||||
|
//清空文本缓存
|
||||||
|
void Pannel::Clear() {
|
||||||
|
COORD coord;
|
||||||
|
coord.X = this->area.Left;
|
||||||
|
coord.Y = this->area.Top;
|
||||||
|
this->clearScreen();
|
||||||
|
this->lines.clear();
|
||||||
|
this->from = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//改变窗口大小
|
||||||
|
void Pannel::Move(SMALL_RECT rect) {
|
||||||
|
if (rect.Right - rect.Left == this->area.Right - this->area.Left || !this->lines.size()) {
|
||||||
|
this->area = rect;
|
||||||
|
this->Flush();
|
||||||
|
return;
|
||||||
|
} //不改变宽度或内容为空
|
||||||
|
this->clearScreen();
|
||||||
|
this->area = rect;
|
||||||
|
//统计'真'行,即自然分行的行
|
||||||
|
std::vector<Line> newLines;
|
||||||
|
newLines.push_back(this->lines.front());
|
||||||
|
for (size_t i = 1; i < this->lines.size(); i++) {
|
||||||
|
if (isTrueLine(newLines.back())) newLines.push_back(this->lines.at(i));
|
||||||
|
else newLines.at(newLines.size() - 1).text += this->lines.at(i).text;
|
||||||
|
}
|
||||||
|
this->lines.clear();
|
||||||
|
for (size_t i = 0; i < newLines.size(); i++) {
|
||||||
|
std::vector<std::string> textLines = splitToLines(newLines.at(i).text);
|
||||||
|
for (size_t j = 0; j < textLines.size(); j++) {
|
||||||
|
Line line;
|
||||||
|
line.attribute = newLines.at(i).attribute;
|
||||||
|
line.text = textLines.at(j);
|
||||||
|
this->lines.push_back(line);
|
||||||
|
}
|
||||||
|
} //重新分割文本行
|
||||||
|
this->Flush();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 向窗格添加文本
|
||||||
|
* @return value, 成功返回true, 否则返回false
|
||||||
|
* @param text, 要写入的文本
|
||||||
|
* @param attribute, 文本属性,详见 FORGROUND_*和BACKGROUND_* 常量
|
||||||
|
*/
|
||||||
|
void Pannel::AddText(std::string text, int attribute) {
|
||||||
|
//将要添加的文本与最后一行拼接。否则每次调用本函数将直接写到新行
|
||||||
|
if (this->lines.size() > 0 && this->isTrueLine(lines.back())) {
|
||||||
|
text = this->lines.back().text + text;
|
||||||
|
lines.pop_back();
|
||||||
|
}
|
||||||
|
//将文本分割成文本行,加入到行数组中
|
||||||
|
std::vector<std::string> textLines = splitToLines(text);
|
||||||
|
int toDeleteCount = (this->lines.size() + textLines.size()) - this->maxLineCount;
|
||||||
|
for (int i = 0; i < toDeleteCount; i++) {
|
||||||
|
this->lines.erase(this->lines.begin());
|
||||||
|
} //移动数组,删除超出最大范围的文本行
|
||||||
|
for (size_t i = 0; i < textLines.size(); i++) {
|
||||||
|
Line line;
|
||||||
|
line.text = textLines.at(i);
|
||||||
|
line.attribute = attribute;
|
||||||
|
this->lines.push_back(line);
|
||||||
|
} //加入新的文本行
|
||||||
|
this->Flush();
|
||||||
|
}
|
||||||
|
//添加行
|
||||||
|
void Pannel::AddLine(std::string text, int attribute) {
|
||||||
|
if (text.size() && !this->isTrueLine(text)) text += '\n';
|
||||||
|
this->AddText(text, attribute);
|
||||||
|
};
|
||||||
|
|
||||||
|
//刷新显示
|
||||||
|
void Pannel::Flush() {
|
||||||
|
int lineCount = this->area.Bottom - this->area.Top + 1; //窗格可显示行数(去除边框)
|
||||||
|
int charCount = this->area.Right - this->area.Left + 1; //每行可显示字符数(去除边框)
|
||||||
|
//如果窗格尺寸太小无法显示字符
|
||||||
|
if (this->lines.size() == 0
|
||||||
|
|| lineCount <= 0
|
||||||
|
|| charCount <= 0)
|
||||||
|
return;
|
||||||
|
this->clearScreen(); //清屏
|
||||||
|
if (this->lines.size() == 0) return; //空缓冲区
|
||||||
|
//获取迭代起点
|
||||||
|
std::vector<Line>::iterator iter;
|
||||||
|
if (this->lines.size() <= lineCount) {
|
||||||
|
iter = this->lines.begin();
|
||||||
|
} //显示所有行
|
||||||
|
else if (this->from < 0 || this->from >= this->lines.size()) {
|
||||||
|
iter = this->lines.end() - lineCount;
|
||||||
|
} //显示最后一屏
|
||||||
|
else {
|
||||||
|
iter = this->lines.begin() + this->from;
|
||||||
|
} //显示特定屏
|
||||||
|
//写文本行
|
||||||
|
COORD lineStart = { 0, 0 };
|
||||||
|
for (size_t i = 0; i < lineCount; i++) {
|
||||||
|
DWORD writtenCount;
|
||||||
|
//获取除去换行符的字符长度
|
||||||
|
int length = iter->text.size();
|
||||||
|
length = isTrueLine(*iter) ? length - 1 : length;
|
||||||
|
lineStart = { area.Left, area.Top + SHORT(i)}; //开始写的位置
|
||||||
|
FillConsoleOutputAttribute(this->window->hOutput, iter->attribute, charCount, lineStart, &writtenCount);
|
||||||
|
WriteConsoleOutputCharacter(this->window->hOutput, iter->text.c_str(), length, lineStart, &writtenCount);
|
||||||
|
if (++iter == this->lines.end()) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//向前滚动
|
||||||
|
bool Pannel::ScrollBackward(int lineCount) {
|
||||||
|
int to = this->from;
|
||||||
|
if (this->from == 0 || lineCount < 0) return false;
|
||||||
|
else if (this->from > 0) to -= lineCount;
|
||||||
|
else to = this->lines.size() - lineCount - 1;
|
||||||
|
return ScrollTo(to < 0 ? 0 : to);
|
||||||
|
}
|
||||||
|
//向后滚动
|
||||||
|
bool Pannel::ScrollForward(int lineCount) {
|
||||||
|
int to = this->from;
|
||||||
|
if (this->from < 0 || lineCount < 0) return false;
|
||||||
|
else to += lineCount;
|
||||||
|
return ScrollTo(to < this->lines.size() ? to : -1);
|
||||||
|
}
|
||||||
|
//滚到
|
||||||
|
bool Pannel::ScrollTo(int line) {
|
||||||
|
if (line >= this->lines.size()) return false;
|
||||||
|
int to = line < 0 ? -1 : line;
|
||||||
|
if (this->from != to) {
|
||||||
|
this->from = to;
|
||||||
|
this->Flush();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//聚焦
|
||||||
|
bool Pannel::Focus(COORD _coord){
|
||||||
|
if (_coord.X < 0 || _coord.Y < 0
|
||||||
|
|| _coord.X > this->area.Right - this->area.Left
|
||||||
|
|| _coord.Y > this->area.Bottom - this->area.Top) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
COORD coord;
|
||||||
|
coord.X = this->area.Left + _coord.X;
|
||||||
|
coord.Y = this->area.Top + _coord.Y;
|
||||||
|
return SetConsoleCursorPosition(this->window->hOutput, coord);
|
||||||
|
}
|
||||||
|
|
||||||
|
//将文本分割为若干行。
|
||||||
|
std::vector<std::string> Pannel::splitToLines(std::string _text) {
|
||||||
|
int charCount = this->area.Right - this->area.Left + 1;
|
||||||
|
if (charCount <= 0) {
|
||||||
|
charCount = 0x7FFFFFFF;
|
||||||
|
} //不断行,仅自然换行
|
||||||
|
std::vector<std::string> textLines; //分割结果集
|
||||||
|
//得到文本的字符数组
|
||||||
|
const char* text = _text.c_str();
|
||||||
|
int start = 0; //行扫描开始位置
|
||||||
|
std::string line = ""; //当前扫描行
|
||||||
|
do {
|
||||||
|
int i;
|
||||||
|
line = "";
|
||||||
|
for (i = 0; i < charCount; i++) {
|
||||||
|
if (!text[start + i]) break; //文本结尾
|
||||||
|
if (text[start + i] == '\r' || text[start + i] == '\n') {
|
||||||
|
line += "\r\n";
|
||||||
|
break;
|
||||||
|
} //自然换行的行尾保留换行符
|
||||||
|
line += text[i + start];
|
||||||
|
} //扫描一行(已计算边框)
|
||||||
|
//过滤换行符
|
||||||
|
start += i;
|
||||||
|
if (text[start] == '\r')
|
||||||
|
start++;
|
||||||
|
if (text[start] == '\n')
|
||||||
|
start++;
|
||||||
|
textLines.push_back(line);
|
||||||
|
} while (text[start]);
|
||||||
|
return textLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
//判断是否自然分行
|
||||||
|
bool Pannel::isTrueLine(std::string line) {
|
||||||
|
if (!line.size()) return false;
|
||||||
|
else if (line.back() == '\n') return true;
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
bool Pannel::isTrueLine(Line line) {
|
||||||
|
return this->isTrueLine(line.text);
|
||||||
|
}
|
||||||
|
//清屏
|
||||||
|
void Pannel::clearScreen() {
|
||||||
|
DWORD written;
|
||||||
|
for (SHORT i = 0; i < this->area.Bottom - this->area.Top + 1; i++) {
|
||||||
|
COORD coord = { this->area.Left, this->area.Top + i };
|
||||||
|
FillConsoleOutputCharacter(this->window->hOutput, ' ', this->area.Right - this->area.Left + 1, coord, &written);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
#ifndef _HEAD_PANNEL_
|
||||||
|
#define _HEAD_PANNEL_
|
||||||
|
|
||||||
|
class ConsoleWindow;
|
||||||
|
|
||||||
|
//声明一行
|
||||||
|
struct Line {
|
||||||
|
WORD attribute;
|
||||||
|
std::string text;
|
||||||
|
};
|
||||||
|
//定义窗格
|
||||||
|
class Pannel {
|
||||||
|
public:
|
||||||
|
SHORT maxLineCount; //最大保存文本行数
|
||||||
|
SMALL_RECT area; //窗格区域(包含边框)
|
||||||
|
Pannel(ConsoleWindow* window, SMALL_RECT rect);
|
||||||
|
//设置最大缓存行数
|
||||||
|
void SetMaxLine(SHORT lineCount);
|
||||||
|
//清空窗格文本
|
||||||
|
void Clear();
|
||||||
|
//移动窗格和重新设置大小
|
||||||
|
void Move(SMALL_RECT rect);
|
||||||
|
//向窗格中加入文本
|
||||||
|
void AddText(std::string text, int attribute = 7);
|
||||||
|
//向窗格中加入文本行
|
||||||
|
void AddLine(std::string text, int attribute = 7);
|
||||||
|
//从特定行开始打印一屏。若this.from无效则打印最后一屏
|
||||||
|
void Flush();
|
||||||
|
//向前滚动,当前已到达最前页返回false,否则返回true
|
||||||
|
bool ScrollBackward(int lineCount);
|
||||||
|
//向后滚动,当前已到达最后页返回false,否则返回true
|
||||||
|
bool ScrollForward(int lineCount);
|
||||||
|
//滚动到某一行,行号无效则滚动到最后
|
||||||
|
bool ScrollTo(int line);
|
||||||
|
//将光标定位到此窗格的相对位置
|
||||||
|
bool Focus(COORD coord);
|
||||||
|
private:
|
||||||
|
size_t from; //从这一行开始显示
|
||||||
|
ConsoleWindow* window; //所属的控制台窗口
|
||||||
|
std::vector<Line> lines; //窗格文本行,自动拆分
|
||||||
|
//将文本分割为若干行。至少保证返回一行
|
||||||
|
std::vector<std::string> splitToLines(std::string text);
|
||||||
|
//判断是否自然分行
|
||||||
|
bool isTrueLine(std::string line);
|
||||||
|
bool isTrueLine(Line line);
|
||||||
|
//清屏
|
||||||
|
void clearScreen();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !_HEAD_PANNEL_
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#include "spliter.h"
|
||||||
|
#include "console_window.h"
|
||||||
|
|
||||||
|
Spliter::Spliter(ConsoleWindow* window, COORD pos, SHORT len, bool verticle, WORD attr) {
|
||||||
|
this->window = window;
|
||||||
|
this->position = pos;
|
||||||
|
this->length = len;
|
||||||
|
this->verticle = verticle;
|
||||||
|
this->attribute = attr;
|
||||||
|
this->draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spliter::Clear() {
|
||||||
|
this->draw(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//移动或重置长度
|
||||||
|
void Spliter::Move(COORD _position, SHORT len) {
|
||||||
|
this->position = _position;
|
||||||
|
this->length = len;
|
||||||
|
this->draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
//绘制或清除
|
||||||
|
void Spliter::draw(bool clear) {
|
||||||
|
DWORD written;
|
||||||
|
COORD curPosition = this->position;
|
||||||
|
//设定填充字
|
||||||
|
const char* spliter;
|
||||||
|
if (clear) spliter = " ";
|
||||||
|
else spliter = this->verticle ? "│" : "─";
|
||||||
|
//取步进方向
|
||||||
|
SHORT* direct = this->verticle ? &curPosition.Y : &curPosition.X;
|
||||||
|
//画分割线
|
||||||
|
for (SHORT i = 0; i < this->length; i++) {
|
||||||
|
FillConsoleOutputAttribute(this->window->hOutput, this->attribute, 2, curPosition, &written);
|
||||||
|
WriteConsoleOutputCharacter(this->window->hOutput, spliter, 2, curPosition, &written);
|
||||||
|
this->verticle ? curPosition.Y += 2 : curPosition.X += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef _HEAD_HRIZEN_
|
||||||
|
#define _HEAD_HRIZEN_
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
class ConsoleWindow;
|
||||||
|
|
||||||
|
//分割线
|
||||||
|
class Spliter {
|
||||||
|
public:
|
||||||
|
WORD attribute; //字符样式
|
||||||
|
COORD position; //位置
|
||||||
|
SHORT length; //宽度/高度
|
||||||
|
Spliter(ConsoleWindow* window, COORD pos, SHORT len, bool verticle, WORD attr = 7);
|
||||||
|
//从屏幕清除
|
||||||
|
void Clear();
|
||||||
|
//移动或重新设置长度
|
||||||
|
void Move(COORD position, SHORT len);
|
||||||
|
private:
|
||||||
|
//绘制或清除
|
||||||
|
void draw(bool clear = false);
|
||||||
|
ConsoleWindow* window; //所属窗口
|
||||||
|
bool verticle; //水平或者垂直分割线
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !_HEAD_HRIZEN_
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include "conctrl.h"
|
||||||
|
int main() {
|
||||||
|
ConsoleWindow* window = CreateConsoleWindow(80, 40);
|
||||||
|
Pannel* writePannel = window->CreatePannel({ 0, 0, 79, 24 });
|
||||||
|
Pannel* messagePannel = window->CreatePannel({ 0, 26, 79, 39 });
|
||||||
|
Spliter* spliter = window->CreateSpliter({ 0, 25 }, 80, false, FOREGROUND_GREEN);
|
||||||
|
messagePannel->AddLine("hello world.");
|
||||||
|
writePannel->Focus({ 0,0 });
|
||||||
|
getchar();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user