mirror of
https://github.com/MeowLynxSea/ceditor.git
synced 2025-07-09 10:54:37 +00:00
add TextArea class
This commit is contained in:
parent
ca4d37ce3b
commit
e432c9c95d
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -51,7 +51,8 @@
|
|||||||
"text_encoding": "cpp",
|
"text_encoding": "cpp",
|
||||||
"typeinfo": "cpp",
|
"typeinfo": "cpp",
|
||||||
"variant": "cpp",
|
"variant": "cpp",
|
||||||
"cassert": "cpp"
|
"cassert": "cpp",
|
||||||
|
"cstdarg": "cpp"
|
||||||
},
|
},
|
||||||
"Codegeex.RepoIndex": true
|
"Codegeex.RepoIndex": true
|
||||||
}
|
}
|
4
.vscode/tasks.json
vendored
4
.vscode/tasks.json
vendored
@ -3,7 +3,7 @@
|
|||||||
{
|
{
|
||||||
"type": "cppbuild",
|
"type": "cppbuild",
|
||||||
"label": "C/C++: g++.exe 生成活动文件",
|
"label": "C/C++: g++.exe 生成活动文件",
|
||||||
"command": "c:\\mingw64\\bin\\g++.exe",
|
"command": "e:\\mingw64\\bin\\g++.exe",
|
||||||
"args": [
|
"args": [
|
||||||
"-fdiagnostics-color=always",
|
"-fdiagnostics-color=always",
|
||||||
"-g",
|
"-g",
|
||||||
@ -12,7 +12,7 @@
|
|||||||
"${fileDirname}\\${fileBasenameNoExtension}.exe"
|
"${fileDirname}\\${fileBasenameNoExtension}.exe"
|
||||||
],
|
],
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "c:\\mingw64\\bin"
|
"cwd": "e:\\mingw64\\bin"
|
||||||
},
|
},
|
||||||
"problemMatcher": [
|
"problemMatcher": [
|
||||||
"$gcc"
|
"$gcc"
|
||||||
|
@ -4,17 +4,21 @@
|
|||||||
#include "BaseComponent.h"
|
#include "BaseComponent.h"
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <conio.h>
|
||||||
#include "../utils/RichText.h"
|
#include "../utils/RichText.h"
|
||||||
|
|
||||||
class TextArea : public BaseComponent {
|
class TextArea : public BaseComponent {
|
||||||
private:
|
private:
|
||||||
RichText text;
|
RichText text;
|
||||||
int viewLeft = 0, viewTop = 0; // 视图左上角坐标
|
int viewLeft = 0, viewTop = 0;
|
||||||
|
std::vector<RichText> lines;
|
||||||
|
int maxLineWidth = 0;
|
||||||
|
RichText title;
|
||||||
|
|
||||||
int findnth(std::string str, std::string target, int n){
|
int findnth(std::string str, std::string target, int n){
|
||||||
if(n == 0) return -1;
|
if(n == 0) return -1;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
unsigned int begin=0;
|
size_t begin = 0;
|
||||||
while((begin = str.find(target, begin)) != std::string::npos){
|
while((begin = str.find(target, begin)) != std::string::npos){
|
||||||
count++;
|
count++;
|
||||||
begin += target.length();
|
begin += target.length();
|
||||||
@ -23,110 +27,158 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TextArea(int top, int left, int width, int height) : BaseComponent(top, left, width, height){
|
|
||||||
text = RichText();
|
|
||||||
}
|
|
||||||
TextArea(int top, int left, int width, int height, const RichText& text) : BaseComponent(top, left, width, height){
|
|
||||||
this->text = text;
|
|
||||||
}
|
|
||||||
~TextArea() override {}
|
|
||||||
|
|
||||||
void setText(const RichText& text) {
|
void setText(const RichText& text) {
|
||||||
this->text = text;
|
this->text = text;
|
||||||
|
|
||||||
|
lines.clear();
|
||||||
|
RichText line;
|
||||||
|
maxLineWidth = 0;
|
||||||
|
for(auto part : text.getParts()) {
|
||||||
|
if(part.text.find('\n') == std::string::npos) {
|
||||||
|
line += part;
|
||||||
|
// printf("Add: %s\n", part.text.c_str());
|
||||||
|
} else {
|
||||||
|
size_t begin = 0;
|
||||||
|
while((begin = part.text.find('\n', begin)) != std::string::npos) {
|
||||||
|
line += StringPart(part.text.substr(0, begin), part.color);
|
||||||
|
// printf("Add: %s\n", part.text.substr(0, begin).c_str());
|
||||||
|
lines.push_back(line);
|
||||||
|
if(maxLineWidth < line.length()) {
|
||||||
|
maxLineWidth = line.length();
|
||||||
|
}
|
||||||
|
// printf("Push: %s\n", line.plainText().c_str());
|
||||||
|
line = RichText();
|
||||||
|
part.text = part.text.substr(begin + 1);
|
||||||
|
// printf("Rest: %s\n", part.text.c_str());
|
||||||
|
}
|
||||||
|
line += part;
|
||||||
|
// printf("Add: %s\n", part.text.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(line.length() > 0) {
|
||||||
|
lines.push_back(line);
|
||||||
|
if(maxLineWidth < line.length()) {
|
||||||
|
maxLineWidth = line.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RichText getText() {
|
RichText getText() {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextArea(int top, int left, int width, int height) : BaseComponent(top, left, width, height){
|
||||||
|
setText(RichText());
|
||||||
|
}
|
||||||
|
TextArea(int top, int left, int width, int height, const RichText& text) : BaseComponent(top, left, width, height){
|
||||||
|
setText(text);
|
||||||
|
}
|
||||||
|
~TextArea() override {}
|
||||||
|
|
||||||
void draw() override {
|
void draw() override {
|
||||||
//使用渲染边框,超出屏幕边缘的区域不渲染
|
|
||||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
//获得缓冲区信息
|
//获得缓冲区信息
|
||||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||||
GetConsoleScreenBufferInfo(hConsole, &csbi);
|
GetConsoleScreenBufferInfo(hConsole, &csbi);
|
||||||
//绘制边框到缓冲区
|
//清空区域
|
||||||
for(int i = 0; i < height && top + i < csbi.dwSize.Y; i++) {
|
for(int i = 0; i < height && top + i < csbi.dwSize.Y; i++) {
|
||||||
|
for(int j = 0; j < width && left + j < csbi.dwSize.X; j++) {
|
||||||
|
SetConsoleCursorPosition(hConsole, {static_cast<short>(left + j), static_cast<short>(top + i)});
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//绘制边框到缓冲区
|
||||||
|
for(int i = 1; i < height - 1 && top + i < csbi.dwSize.Y - 1; i++) {
|
||||||
if(left >= 0) {
|
if(left >= 0) {
|
||||||
SetConsoleCursorPosition(hConsole, {static_cast<short>(left - 1), static_cast<short>(top + i - 1)});
|
SetConsoleCursorPosition(hConsole, {static_cast<short>(left - 1), static_cast<short>(top + i - 1)});
|
||||||
printf("|");
|
putchar('|');
|
||||||
}
|
}
|
||||||
if(left + width - 1 < csbi.dwSize.X) {
|
if(left + width - 1 < csbi.dwSize.X) {
|
||||||
SetConsoleCursorPosition(hConsole, {static_cast<short>(left + width - 2), static_cast<short>(top + i - 1)});
|
SetConsoleCursorPosition(hConsole, {static_cast<short>(left + width - 2), static_cast<short>(top + i - 1)});
|
||||||
printf("|");
|
putchar('|');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(int i = 0; i < width && left + i < csbi.dwSize.X; i++) {
|
for(int i = 0; i < width && left + i < csbi.dwSize.X; i++) {
|
||||||
if(top >= 0) {
|
if(top >= 0) {
|
||||||
SetConsoleCursorPosition(hConsole, {static_cast<short>(left + i - 1), static_cast<short>(top - 1)});
|
SetConsoleCursorPosition(hConsole, {static_cast<short>(left + i - 1), static_cast<short>(top - 1)});
|
||||||
printf("-");
|
putchar('-');
|
||||||
}
|
}
|
||||||
if(top + height - 1 < csbi.dwSize.Y) {
|
if(top + height - 1 < csbi.dwSize.Y) {
|
||||||
SetConsoleCursorPosition(hConsole, {static_cast<short>(left + i - 1), static_cast<short>(top + height - 2)});
|
SetConsoleCursorPosition(hConsole, {static_cast<short>(left + i - 1), static_cast<short>(top + height - 2)});
|
||||||
printf("-");
|
putchar('-');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//绘制文本到缓冲区,保证不超出边框
|
|
||||||
// int textWidth = 0, i = 0;
|
|
||||||
// while(textWidth <= width - 2 && left + textWidth + 2 < csbi.dwSize.X && i < text.size()) {
|
|
||||||
// auto part = text.getParts()[i];
|
|
||||||
// SetConsoleCursorPosition(hConsole, {static_cast<short>(left + textWidth), static_cast<short>(top)});
|
|
||||||
// SetConsoleTextAttribute(hConsole, BackgroundColorToWinColor(getBackColor(part.color)) | FrontColorToWinColor(getFrontColor(part.color)));
|
|
||||||
// if(left + textWidth + part.text.length() + 2 < csbi.dwSize.X && textWidth + part.text.length() <= width - 2) {
|
|
||||||
// printf("%s", part.text.c_str());
|
|
||||||
// } else {
|
|
||||||
// printf("%s", part.text.substr(0, std::min(csbi.dwSize.X - left - textWidth - 2, width - 2 - textWidth)).c_str());
|
|
||||||
// }
|
|
||||||
// textWidth += text.getParts()[i].text.length();
|
|
||||||
// i++;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 根据换行预处理文本
|
//绘制标题
|
||||||
std::vector<RichText> lines;
|
SetConsoleCursorPosition(hConsole, {static_cast<short>(left + 1), static_cast<short>(top - 1)});
|
||||||
RichText line;
|
for(auto part : title.getParts()) {
|
||||||
for(auto part : text.getParts()) {
|
SetConsoleTextAttribute(hConsole, BackgroundColorToWinColor(getBackColor(part.color)) | FrontColorToWinColor(getFrontColor(part.color)));
|
||||||
if(part.text.find('\n') == std::string::npos) {
|
printf("%s", part.text.c_str());
|
||||||
line += part;
|
|
||||||
} else {
|
|
||||||
unsigned int begin = 0;
|
|
||||||
while((begin = part.text.find('\n', begin)) != std::string::npos) {
|
|
||||||
line += StringPart(part.text.substr(0, begin), part.color);
|
|
||||||
lines.push_back(line);
|
|
||||||
line = RichText();
|
|
||||||
part.text = part.text.substr(begin + 1);
|
|
||||||
}
|
|
||||||
line += part;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = viewTop; i < viewTop + height - 2 && i < lines.size(); i++) {
|
for(int i = viewTop; i < viewTop + height - 2 && i < lines.size(); i++) {
|
||||||
line = lines[i];
|
RichText drawTarget = lines[i].substr(viewLeft, std::min(width - 2, csbi.dwSize.X - left - 2));
|
||||||
RichText drawTarget = line.substr(viewLeft, width - 2);
|
SetConsoleCursorPosition(hConsole, {static_cast<short>(left), static_cast<short>(top + i - viewTop)});
|
||||||
int textWidth = 0, ite = 0;
|
for(auto part : drawTarget.getParts()) {
|
||||||
while(textWidth <= width - 2 && left + textWidth + 2 < csbi.dwSize.X && ite < text.size()) {
|
|
||||||
auto part = line.getParts()[i];
|
|
||||||
SetConsoleCursorPosition(hConsole, {static_cast<short>(left + textWidth), static_cast<short>(top)});
|
|
||||||
SetConsoleTextAttribute(hConsole, BackgroundColorToWinColor(getBackColor(part.color)) | FrontColorToWinColor(getFrontColor(part.color)));
|
SetConsoleTextAttribute(hConsole, BackgroundColorToWinColor(getBackColor(part.color)) | FrontColorToWinColor(getFrontColor(part.color)));
|
||||||
if(left + textWidth + part.text.length() + 2 < csbi.dwSize.X && textWidth + part.text.length() <= width - 2) {
|
|
||||||
printf("%s", part.text.c_str());
|
printf("%s", part.text.c_str());
|
||||||
} else {
|
|
||||||
printf("%s", part.text.substr(0, std::min(csbi.dwSize.X - left - textWidth - 2, width - 2 - textWidth)).c_str());
|
|
||||||
}
|
|
||||||
textWidth += part.text.length();
|
|
||||||
ite++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetConsoleTextAttribute(hConsole, BackgroundColorToWinColor(COLOR_BLACK) | FrontColorToWinColor(COLOR_WHITE));
|
SetConsoleTextAttribute(hConsole, BackgroundColorToWinColor(COLOR_BLACK) | FrontColorToWinColor(COLOR_WHITE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setViewTop(int top) {
|
||||||
|
this->viewTop = top;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getViewTop() {
|
||||||
|
return this->viewTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setViewLeft(int left) {
|
||||||
|
this->viewLeft = left;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getViewLeft() {
|
||||||
|
return this->viewLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
void moveLeft() {
|
||||||
|
if(viewLeft > 0) {
|
||||||
|
viewLeft--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void moveRight() {
|
||||||
|
if(viewLeft < maxLineWidth - width + 2) {
|
||||||
|
viewLeft++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void moveUp() {
|
||||||
|
if(viewTop > 0) {
|
||||||
|
viewTop--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void moveDown() {
|
||||||
|
if(viewTop < lines.size() - height + 2) {
|
||||||
|
viewTop++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void onKeyPress(int key) override {
|
void onKeyPress(int key) override {
|
||||||
//不处理按键
|
//不处理按键
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setTitle(const RichText& title) {
|
||||||
|
this->title = title;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,23 +1,79 @@
|
|||||||
#include "BaseComponent.h"
|
#include "BaseComponent.h"
|
||||||
#include "TextArea.h"
|
#include "TextArea.h"
|
||||||
#include "../utils/RichText.h"
|
#include "../utils/RichText.h"
|
||||||
|
#include <conio.h>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
RichText richText;
|
RichText richText;
|
||||||
richText = "Hello, World";
|
richText = "Hello, World";
|
||||||
richText += StringPart(" with colors!", COLOR_RED);
|
richText += StringPart(" with colors!\n", COLOR_RED);
|
||||||
richText += " And more text.";
|
richText += "And more text.\n";
|
||||||
richText += StringPart(" And more more more text.", COLOR_GREEN);
|
richText += StringPart("And more more more text.", COLOR_GREEN);
|
||||||
richText += " And more more more more more text.";
|
richText += " And more more more more more text.\n";
|
||||||
richText += StringPart(" And more more more more more more text.", COLOR_BLUE);
|
richText += StringPart("And more more more more more more text.", COLOR_BLUE);
|
||||||
richText += " And more more more more more more more text.";
|
richText += " And more more more more more more more text.\n";
|
||||||
richText += StringPart(" And more more more more more more more more text.", COLOR_YELLOW);
|
richText += StringPart("And more more more more more more more more text.\n", COLOR_YELLOW);
|
||||||
richText += " And more more more more more more more more more text.";
|
richText += "And more more more more more more more more more text.\n";
|
||||||
richText += StringPart(" And more more more more more more more more more more text.", COLOR_CYAN);
|
richText += StringPart("And more more more more more more more more more more text.\n", COLOR_CYAN);
|
||||||
|
|
||||||
TextArea textArea(3, 3, 40, 5, richText);
|
TextArea textArea(3, 3, 64, 7, richText);
|
||||||
|
|
||||||
|
// 创建后台缓冲区
|
||||||
|
HANDLE hBackBuffer = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
|
||||||
|
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
|
// 清空后台缓冲区
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||||
|
GetConsoleScreenBufferInfo(hConsole, &csbi);
|
||||||
|
DWORD dwBytesWritten;
|
||||||
|
FillConsoleOutputCharacter(hBackBuffer, ' ', csbi.dwSize.X * csbi.dwSize.Y, {0, 0}, &dwBytesWritten);
|
||||||
|
FillConsoleOutputAttribute(hBackBuffer, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, {0, 0}, &dwBytesWritten);
|
||||||
|
CONSOLE_CURSOR_INFO cci;
|
||||||
|
cci.bVisible = false;
|
||||||
|
cci.dwSize = 1;
|
||||||
|
SetConsoleCursorInfo(hBackBuffer, &cci);
|
||||||
|
SetConsoleCursorInfo(hConsole, &cci);
|
||||||
|
|
||||||
|
textArea.setTitle(RichText("TextArea Demo", COLOR_RED));
|
||||||
textArea.draw();
|
textArea.draw();
|
||||||
|
|
||||||
printf("\n");
|
while(true) {
|
||||||
|
if (_kbhit()) {SetConsoleActiveScreenBuffer(hBackBuffer);
|
||||||
|
char opt = _getch();
|
||||||
|
textArea.setText(richText + StringPart("Last Key: " + std::to_string(opt), COLOR_CYAN));
|
||||||
|
switch(opt) {
|
||||||
|
case 72:
|
||||||
|
textArea.moveUp();
|
||||||
|
break;
|
||||||
|
case 80:
|
||||||
|
textArea.moveDown();
|
||||||
|
break;
|
||||||
|
case 75:
|
||||||
|
textArea.moveLeft();
|
||||||
|
break;
|
||||||
|
case 77:
|
||||||
|
textArea.moveRight();
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
SetConsoleActiveScreenBuffer(hConsole);
|
||||||
|
CloseHandle(hBackBuffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 清空后台缓冲区
|
||||||
|
FillConsoleOutputCharacter(hBackBuffer, ' ', csbi.dwSize.X * csbi.dwSize.Y, {0, 0}, &dwBytesWritten);
|
||||||
|
FillConsoleOutputAttribute(hBackBuffer, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, {0, 0}, &dwBytesWritten);
|
||||||
|
|
||||||
|
// 在后台缓冲区中绘制
|
||||||
|
textArea.draw();
|
||||||
|
|
||||||
|
// 切换到后台缓冲区,显示绘制的内容
|
||||||
|
SetConsoleActiveScreenBuffer(hConsole);
|
||||||
|
}
|
||||||
|
Sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -55,18 +55,11 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//绘制文本到缓冲区,保证不超出边框
|
//绘制文本到缓冲区,保证不超出边框
|
||||||
int textWidth = 0, i = 0;
|
RichText drawTarget = text.substr(0, std::min(width - 2, csbi.dwSize.X - left - 2));
|
||||||
while(textWidth <= width - 2 && left + textWidth + 2 < csbi.dwSize.X && i < text.size()) {
|
SetConsoleCursorPosition(hConsole, {static_cast<short>(left), static_cast<short>(top)});
|
||||||
auto part = text.getParts()[i];
|
for(auto part : drawTarget.getParts()) {
|
||||||
SetConsoleCursorPosition(hConsole, {static_cast<short>(left + textWidth), static_cast<short>(top)});
|
|
||||||
SetConsoleTextAttribute(hConsole, BackgroundColorToWinColor(getBackColor(part.color)) | FrontColorToWinColor(getFrontColor(part.color)));
|
SetConsoleTextAttribute(hConsole, BackgroundColorToWinColor(getBackColor(part.color)) | FrontColorToWinColor(getFrontColor(part.color)));
|
||||||
if(left + textWidth + part.text.length() + 2 < csbi.dwSize.X && textWidth + part.text.length() <= width - 2) {
|
|
||||||
printf("%s", part.text.c_str());
|
printf("%s", part.text.c_str());
|
||||||
} else {
|
|
||||||
printf("%s", part.text.substr(0, std::min(csbi.dwSize.X - left - textWidth - 2, width - 2 - textWidth)).c_str());
|
|
||||||
}
|
|
||||||
textWidth += part.text.length();
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SetConsoleTextAttribute(hConsole, BackgroundColorToWinColor(COLOR_BLACK) | FrontColorToWinColor(COLOR_WHITE));
|
SetConsoleTextAttribute(hConsole, BackgroundColorToWinColor(COLOR_BLACK) | FrontColorToWinColor(COLOR_WHITE));
|
||||||
|
@ -43,6 +43,18 @@ public:
|
|||||||
RichText() {
|
RichText() {
|
||||||
parts.push_back({""});
|
parts.push_back({""});
|
||||||
}
|
}
|
||||||
|
// 构造函数,初始化为一段指定文本和颜色的文本
|
||||||
|
RichText(const std::string& text, const MColor& color) {
|
||||||
|
parts.push_back({text, color});
|
||||||
|
}
|
||||||
|
// 构造函数,初始化为一段指定文本的文本
|
||||||
|
RichText(const std::string& text) {
|
||||||
|
parts.push_back({text});
|
||||||
|
}
|
||||||
|
// 构造函数,初始化为一段指定文本和颜色的文本
|
||||||
|
RichText(const StringPart& part) {
|
||||||
|
parts.push_back(part);
|
||||||
|
}
|
||||||
|
|
||||||
// 重载运算符=
|
// 重载运算符=
|
||||||
RichText& operator=(const RichText& other) {
|
RichText& operator=(const RichText& other) {
|
||||||
|
Loading…
Reference in New Issue
Block a user