实现语言:C++
项目名称:UI.h
项目类型:控制台应用
项目版本:2022-8-14
开发环境: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 *
- * 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版本 效果
好了,今天就到这里了。如果大家有对这篇文章有不懂或有建议可以告诉我。拜拜!