系列文章目录
【C++】基于Easyx的UI库(2022-8-14 V1)
简介
实现语言:C++
项目名称:UI.h
项目类型:控制台应用
项目版本:2022-8-14 V2
开发环境:Visual Studio 2022 Community 17.3.1 & Easyx 2022-6-10
项目介绍
上篇文章中,有人提出了一些建议,我今天就就他的建议修改了代码。
他说的问题在于LPCTSTR类型,不能直接拷贝(浅拷贝),因为它是一个指针,要用深拷贝。
为此,我将原来几个是LPCTSTR类型的成员改为了LPTSTR类型,并将浅拷贝改为了深拷贝(使用的是lstrcpy函数)。不要看看似只改了一点点,实则我摸索了好久……因为网上根本没有详细的LPCTSTR类型的教程……
更新历史
- 2022-8-18 优化已有的控件
- 2022-8-14 优化已有的控件,将init()初始化函数改为构造函数;增加复选框(Checked List Box)
- 2022-8-13 增加单选框(Check Box),优化按钮(Button)和文本(Label)
- 2022-8-7 完成按钮(Button)和文本(Label)
- 2022-8-5 创建UI.h
代码
UI.h
/***************************************************************
* *
* UI.h *
* UI Library for C++ Base on Easyx. *
* 基于 Easyx 的 C++ UI 库 *
* Version : 2022-8-14 V2 *
* 版本:2022-8-14 V2 *
* https://easyx.cn *
* https://blog.csdn.net/qq_43546083?spm=1000.2115.3001.5343 *
* *
***************************************************************/
#pragma once
#if __has_include(<graphics.h>)
#include <graphics.h>
namespace UI {
/**** 按钮 ****/
class Button {
public:
/**** 控件左上角的x坐标 ****/
int x = 0,
/**** 控件左上角的y坐标 ****/
y = 0;
/**** 控件的宽度 ****/
int width = 0,
/**** 控件的高度 ****/
height = 0;
/**** 控件所显示的文本 ****/
LPTSTR text = new wchar_t[1024];
/**** 控件显示的文本高度 ****/
int size = 16;
/**** 控件是否可见,可见为true,否则为false ****/
bool visible = false;
/**** 构造函数,初始化控件左上角的坐标、宽度、高度、显示的文本与文本的高度(默认为16) ****/
Button(int x, int y, int width, int height, LPCTSTR text, int size = 16) {
this->x = x;
this->y = y;
this->width = width;
this->height = height;
lstrcpy(this->text, text);
this->size = size;
return;
}
/**** 显示控件,成功返回true,出现异常返回false ****/
bool show() {
if (visible) {
//当前控件可见
return false;
}
int temp = getbkmode();
setbkmode(TRANSPARENT);
LOGFONT* temp1 = new LOGFONT();
LOGFONT* temp2 = new LOGFONT();
gettextstyle(temp1);
gettextstyle(temp2);
temp2->lfHeight = size;
settextstyle(temp2);
if (width - textwidth(text) <= 0 || height - textheight(text) <= 0) {
//文字过大
settextstyle(temp1);
return false;
}
fillrectangle(x, y, x + width - 1, y + height - 1);
outtextxy(x + (width - textwidth(text)) / 2, y + (height - textheight(text)) / 2, text);
settextstyle(temp1);
setbkmode(temp);
delete temp1;
delete temp2;
visible = true;
return true;
}
/**** 隐藏控件 ****/
void hide() {
COLORREF temp = getfillcolor();
setfillcolor(getbkcolor());
solidrectangle(x, y, x + width - 1, y + height - 1);
setfillcolor(temp);
visible = false;
return;
}
/**** 判断按钮是否被按下,被按下返回true,没有按下或出现异常返回false ****/
bool click(ExMessage m) {
if ((x == 0 || y == 0 || width == 0 || height == 0) || !visible) {
//未初始化控件或当前控件不可见
return false;
}
return m.message == WM_LBUTTONUP && (m.x >= x && m.x <= x + width - 1) && (m.y >= y && m.y <= y + height - 1);
}
/**** 刷新插件(显示状态下) ****/
void reload() {
visible = false;
show();
}
~Button()
{
text = nullptr;
delete[] text;
}
};
/**** 文本(该控件为自动调整大小) ****/
class Label {
private:
int width, height;
public:
/**** 控件左上角的x坐标 ****/
int x = 0,
/**** 控件左上角的y坐标 ****/
y = 0;
/**** 控件所显示的文本 ****/
LPTSTR text = new wchar_t[1024];
/**** 控件显示的文本高度 ****/
int size = 16;
/**** 控件是否可见,可见为true,否则为false ****/
bool visible = false;
/**** 构造函数,初始化控件左上角的坐标、显示的文本与文本的高度(默认为16) ****/
Label(int x, int y, LPCTSTR text, int size = 16) {
this->x = x;
this->y = y;
lstrcpy(this->text, text);
this->size = size;
width = 0;
height = 0;
return;
}
/**** 显示控件,成功返回true,出现异常返回false ****/
bool show() {
if (visible) {
//当前控件可见
return false;
}
int temp = getbkmode();
setbkmode(TRANSPARENT);
LOGFONT* temp1 = new LOGFONT();
LOGFONT* temp2 = new LOGFONT();
gettextstyle(temp1);
gettextstyle(temp2);
temp2->lfHeight = size;
settextstyle(temp2);
outtextxy(x, y, text);
width = textwidth(text);
height = textheight(text);
settextstyle(temp1);
delete temp1;
delete temp2;
setbkmode(temp);
visible = true;
return true;
}
/**** 隐藏控件 ****/
void hide() {
COLORREF temp = getfillcolor();
setfillcolor(getbkcolor());
solidrectangle(x, y, x + width - 1, y + height - 1);
setfillcolor(temp);
visible = false;
return;
}
/**** 刷新插件(显示状态下) ****/
void reload() {
visible = false;
show();
}
~Label()
{
text = nullptr;
delete[] text;
}
};
/**** 勾选框(该控件为自动大小) ****/
class CheckBox {
private:
//勾选框=按钮+文本
Button* button;
Label* label;
public:
/**** 控件左上角的x坐标 ****/
int x = 0,
/**** 控件左上角的y坐标 ****/
y = 0;
/**** 控件所显示的文本 ****/
LPTSTR text = new wchar_t[1024];
/**** 是否已被勾选 ****/
bool state = false;
/**** 构造函数,初始化控件左上角的坐标与显示的文本 ****/
CheckBox(int x, int y, LPCTSTR text) {
this->x = x;
this->y = y;
lstrcpy(this->text, text);
button = new Button(x, y, 18, 18, L"");
label = new Label(x + 20, y, text, 18);
return;
}
/**** 显示控件,成功返回true,出现异常返回false ****/
bool show() {
if (!button->show() || !label->show()) {
hide();
return false;
}
return true;
}
/**** 隐藏控件 ****/
void hide() {
button->hide();
label->hide();
return;
}
/**** 控件是否被勾选,按下则切换效果,出现异常返回false ****/
bool check(ExMessage m) {
if ((button->x == 0 || button->y == 0 || button->width == 0 || button->height == 0) || (label->x == 0 || label->y == 0) || !(button->visible && label->visible)) {
//未初始化控件或当前控件不可见
return false;
}
if (button->click(m)) {
state = !state;
state ? lstrcpy(button->text, L"√") : lstrcpy(button->text, L"");
reload();
}
return true;
}
/**** 刷新插件(显示状态下) ****/
void reload() {
button->reload();
label->reload();
}
~CheckBox()
{
text = nullptr;
button = nullptr;
label = nullptr;
delete[] text;
delete button;
delete label;
}
};
/**** 复选框(最多15项,该控件为自动大小) ****/
class CheckedListBox {
public:
//复选框=多个勾选框
CheckBox* checkbox[15] = { nullptr };
/**** 控件左上角的x坐标 ****/
int x = 0,
/**** 控件左上角的y坐标 ****/
y = 0;
/**** 项数 ****/
int num = 0;
/**** 构造函数,初始化控件左上角的坐标与显示的文本 ****/
CheckedListBox(int x, int y, int num, LPCTSTR text[]) {
this->x = x;
this->y = y;
if (num > 15) {
MessageBox(0, L"项数过多!", L"UI.h", MB_OK | MB_ICONSTOP);
return;
}
this->num = num;
for (int i = 0; i < num; i++) {
checkbox[i] = new CheckBox(x + 5, y + 5 + i * 20, text[i]);
}
}
CheckedListBox(int num, CheckBox checkbox[]) {
this->x = checkbox[0].x - 5;
this->y = checkbox[0].y - 5;
if (num > 15) {
MessageBox(0, L"项数过多!", L"UI.h", MB_OK | MB_ICONSTOP);
return;
}
this->num = num;
for (int i = 0; i < num; i++) {
this->checkbox[i] = &checkbox[i];
}
}
/**** 显示控件,成功返回true,出现异常返回false ****/
bool show() {
int maxlen = 0;
for (int i = 0; i < num; i++) {
maxlen = max(maxlen, textwidth(checkbox[i]->text));
if (!checkbox[i]->show()) {
for (int j = 0; j < i; j++) {
checkbox[j]->hide();
return false;
}
}
}
rectangle(x, y, x + maxlen + 30, y + num * 20 + 8);
return true;
}
/**** 隐藏控件 ****/
void hide() {
for (int i = 0; i < num; i++) checkbox[i]->hide();
}
/**** 控件是否被勾选,按下则切换效果,出现异常返回false ****/
bool check(ExMessage m) {
for (int i = 0; i < num; i++) {
if (!checkbox[i]->check(m))return false;
}
return true;
}
/**** 刷新插件(显示状态下) ****/
void relad() {
for (int i = 0; i < num; i++)checkbox[i]->reload();
return;
}
~CheckedListBox()
{
for (int i = 0; i < num; i++) {
checkbox[i] = nullptr;
delete checkbox[i];
}
}
};
}
#else
#error 请先安装Easyx库,下载地址:https://easyx.cn
#endif
今天就不再展示效果和示例代码了,可以看我的上一篇文章。拜拜!