实现语言:C++
项目名称:UI.h
项目类型:控制台应用
项目版本:2022-8-14 V1
开发环境:Visual Studio 2022 Community 17.3.0 & Easyx 2022-6-10
前段时间我研究了C#,就想把C#窗体应用中的控件搬到C++上,于是就有了这篇文章。
这个代码只要是懂一点Easyx的应该都看得懂(因为Easyx本身并不难),并且我还在里面加了一些注释,应该大部分人阅读起来都是没问题的。
UI.h
/***************************************************************
* *
* UI.h *
* UI Library for C++ Base on Easyx. *
* Version : 2022-8-14 V1 *
* https://easyx.cn *
* https://blog.csdn.net/qq_43546083?spm=1000.2115.3001.5343 *
* *
***************************************************************/
#pragma once
#if __has_include()
#include
namespace UI {
/**** 按钮 ****/
class Button {
public:
/**** 控件左上角的x坐标 ****/
int x = -1,
/**** 控件左上角的y坐标 ****/
y = -1;
/**** 控件的宽度 ****/
int width = -1,
/**** 控件的高度 ****/
height = -1;
/**** 控件所显示的文本 ****/
LPCTSTR text = L"";
/**** 控件显示的文本高度 ****/
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;
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 == -1 || y == -1 || width == -1 || height == -1) || !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();
}
};
/**** 文本(该控件为自动调整大小) ****/
class Label {
private:
int width, height;
public:
/**** 控件左上角的x坐标 ****/
int x = -1,
/**** 控件左上角的y坐标 ****/
y = -1;
/**** 控件所显示的文本 ****/
LPCTSTR text = L"";
/**** 控件显示的文本高度 ****/
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;
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();
}
};
/**** 勾选框(该控件为自动大小) ****/
class CheckBox {
private:
//勾选框=按钮+文本
Button* button;
Label* label;
public:
/**** 控件左上角的x坐标 ****/
int x = -1,
/**** 控件左上角的y坐标 ****/
y = -1;
/**** 控件所显示的文本 ****/
LPCTSTR text = L"";
/**** 是否已被勾选 ****/
bool state = false;
/**** 构造函数,初始化控件左上角的坐标与显示的文本 ****/
CheckBox(int x, int y, LPCTSTR text) {
this->x = x;
this->y = y;
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 == -1 || button->y == -1 || button->width == -1 || button->height == -1) || (label->x == -1 || label->y == -1) || !(button->visible && label->visible)) {
//未初始化控件或当前控件不可见
return false;
}
if (button->click(m)) {
state = !state;
button->text = state ? L"√" : L"";
reload();
}
return true;
}
/**** 刷新插件(显示状态下) ****/
void reload() {
button->reload();
label->reload();
}
~CheckBox()
{
delete button;
delete label;
}
};
/**** 复式勾选框(最多15项,该控件为自动大小) ****/
class CheckedListBox {
public:
//复式勾选框=多个勾选框
CheckBox* checkbox[15] = { nullptr };
/**** 项数 ****/
int num = 0;
/**** 构造函数,初始化控件左上角的坐标与显示的文本 ****/
CheckedListBox(int x, int y, int num, LPCTSTR text[]) {
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 + i * 20, text[i]);
}
}
CheckedListBox(int num, CheckBox checkbox[]) {
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 = -1;
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(checkbox[0]->x - 5, checkbox[0]->y - 5, checkbox[0]->x + maxlen + 25, checkbox[0]->y + num * 20 + 3);
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()
{
delete[] &checkbox;
}
};
}
#else
#error 请先安装Easyx库,下载地址:https://easyx.cn
#endif
在这里,为了让大家简单了解一下这些类使用的方法,给了一段参考代码:
text.cpp
#include "UI.h"
int main() {
initgraph(640,480);
settextcolor(BLACK);
setbkcolor(RGB(240, 240, 240));
setlinecolor(BLACK);
setfillcolor(RGB(230, 230, 230));
cleardevice();
LPCTSTR text[3] = { L"这是",L"一个",L"Checked List Box" };
UI::Button button(5, 5, 200, 60, L"这是一个Button");
UI::CheckBox checkbox(5, 70, L"这是一个Check Box");
UI::CheckedListBox checkedlistbox(5, 155, 3, text);
UI::Label label1(5, 95, L"这是一个Label"), label2(5, 115, L"这是一个彩蛋", 32);
button.show();
checkbox.show();
checkedlistbox.show();
label1.show();
ExMessage m;
while (true) {
m = getmessage(EM_MOUSE);
checkbox.check(m);
checkedlistbox.check(m);
if (checkbox.state == true)label2.show();
else label2.hide();
if (button.click(m)){
if (label1.visible)label1.hide();
else label1.show();
}
}
return 0;
}
运行效果:
UI.h 2022-8-14版本 效果
好了,今天就到这里了。如果大家有对这篇文章有不懂或有建议可以告诉我。拜拜!