Series Article Directory
Introduction
Implementation language: C++
Project name: UI.h
Project Type: Console App
Project version: 2022-8-14 V2
Development environment: Visual Studio 2022 Community 17.3.1 & Easyx 2022-6-10
Project Introduction
In the last article, someone made some suggestions, and I modified the code today based on his suggestions.
The problem he said is that the LPCTSTR type cannot be copied directly (shallow copy), because it is a pointer, and a deep copy is used.
To this end, I changed the original members of the LPCTSTR type to LPTSTR type, and changed the shallow copy to a deep copy (using the lstrcpy function). Don't look at it seems that it has only been changed a little, but in fact I have been groping for a long time... Because there is no detailed LPCTSTR type tutorial on the Internet...
update history
- 2022-8-18 Optimize existing controls
- 2022-8-14 Optimize the existing controls, change the init() initialization function to a constructor; add a check box (Checked List Box)
- 2022-8-13 Added Check Box, Optimized Button and Text
- 2022-8-7 Complete button (Button) and text (Label)
- 2022-8-5 Create UI.h
code
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
I won't show the effect and sample code today, you can read my last article . Bye-Bye!