feat: add a new awesome feature

This commit is contained in:
Ysm-04
2025-10-27 14:59:29 +08:00
parent 95149238e2
commit dcf13895da
26 changed files with 2666 additions and 439 deletions

View File

@@ -19,6 +19,12 @@
******************************************************************************/
#pragma once
#include "Control.h"
#include"label.h"
#define DISABLEDCOLOUR RGB(96, 96, 96) //禁用状态颜色
#define TEXTMARGINS_X 6
#define TEXTMARGINS_Y 4
class Button : public Control
{
@@ -27,6 +33,12 @@ class Button : public Control
bool click; // 是否被点击
bool hover; // 是否被悬停
std::string cutText; // 切割后的文本
bool needCutText = true; // 是否需要切割文本
bool isUseCutText = false; // 是否使用切割文本
int padX = TEXTMARGINS_X; // 文本最小左右内边距
int padY = TEXTMARGINS_Y; // 文本最小上下内边距
COLORREF buttonTrueColor; // 按钮被点击后的颜色
COLORREF buttonFalseColor; // 按钮未被点击的颜色
COLORREF buttonHoverColor; // 按钮被鼠标悬停的颜色
@@ -50,6 +62,24 @@ class Button : public Control
int oldtext_height = -1;
int text_width = 0;
int text_height = 0;
// === Tooltip ===
bool tipEnabled = false; // 是否启用
bool tipVisible = false; // 当前是否显示
bool tipFollowCursor = false; // 是否跟随鼠标
bool tipUserOverride = false; // 是否用户自定义了tip文本
int tipDelayMs = 1000; // 延时(毫秒)
int tipOffsetX = 12; // 相对鼠标偏移
int tipOffsetY = 18;
ULONGLONG tipHoverTick = 0; // 开始悬停的时间戳
int lastMouseX = 0; // 最新鼠标位置(用于定位)
int lastMouseY = 0;
std::string tipTextClick; //NORMAL 模式下用
std::string tipTextOn; // click==true 时用
std::string tipTextOff; // click==false 时用
Label tipLabel; // 直接复用Label作为提示
public:
StellarX::ControlText textStyle; // 按钮文字样式
@@ -72,7 +102,6 @@ public:
//绘制按钮
void draw() override;
//按钮事件处理
bool handleEvent(const ExMessage& msg) override;
//设置回调函数
@@ -131,11 +160,31 @@ public:
int getButtonWidth() const;
//获取按钮高度
int getButtonHeight() const;
//获取按钮横坐标
int getButtonX() const;
//获取按钮纵坐标
int getButtonY() const;
public:
// === Tooltip API===
//设置是否启用提示框
void enableTooltip(bool on) { tipEnabled = on; if (!on) tipVisible = false; }
//设置提示框延时
void setTooltipDelay(int ms) { tipDelayMs = (ms < 0 ? 0 : ms); }
//设置提示框是否跟随鼠标
void setTooltipFollowCursor(bool on) { tipFollowCursor = on; }
//设置提示框位置偏移
void setTooltipOffset(int dx, int dy) { tipOffsetX = dx; tipOffsetY = dy; }
//设置提示框样式
void setTooltipStyle(COLORREF text, COLORREF bk, bool transparent)
{
tipLabel.setTextColor(text);
tipLabel.setTextBkColor(bk);
tipLabel.setTextdisap(transparent);
}
//设置提示框文本
void setTooltipText(const std::string& s){ tipTextClick = s; tipUserOverride = true; }
void setTooltipTextsForToggle(const std::string& onText, const std::string& offText)
{
tipTextOn = onText;
tipTextOff = offText;
tipUserOverride = true;
}
private:
//初始化按钮
void initButton(const std::string text, StellarX::ButtonMode mode, StellarX::ControlShape shape, COLORREF ct, COLORREF cf, COLORREF ch);
@@ -143,10 +192,13 @@ private:
bool isMouseInCircle(int mouseX, int mouseY, int x, int y, int radius);
//判断鼠标是否在椭圆按钮内
bool isMouseInEllipse(int mouseX, int mouseY, int x, int y, int width, int height);
//检查是否对话框是否可见
bool IsVisible() const override { return false; }
//获取对话框类型
bool model() const override { return false; }
void cutButtonText();
// 统一隐藏&恢复背景
void hideTooltip();
// 根据当前 click 状态选择文案
void refreshTooltipTextForState();
};

View File

@@ -2,8 +2,8 @@
* @类: Canvas
* @摘要: 画布容器控件,用于分组和管理子控件
* @描述:
* 作为其他控件的父容器,提供统一的背景和边框样式。
* 负责将事件传递给子控件并管理它们的绘制顺序。
* 作为其他控件的父容器,提供统一的背景和边框样式。
* 负责将事件传递给子控件并管理它们的绘制顺序。
*
* @特性:
* - 支持四种矩形形状(普通、圆角,各有边框和无边框版本)
@@ -14,7 +14,7 @@
* @使用场景: 用于分组相关控件、实现复杂布局或作为对话框基础
* @所属框架: 星垣(StellarX) GUI框架
* @作者: 我在人间做废物
******************************************************************************/
*******************************************************************************/
#pragma once
#include "Control.h"
@@ -24,22 +24,17 @@ class Canvas : public Control
protected:
std::vector<std::unique_ptr<Control>> controls;
StellarX::ControlShape shape = StellarX::ControlShape::RECTANGLE; //容器形状
StellarX::FillMode canvasFillMode = StellarX::FillMode::Solid; //容器填充模式
StellarX::LineStyle canvasLineStyle = StellarX::LineStyle::Solid; //线
int canvaslinewidth = 1; //线宽
StellarX::ControlShape shape = StellarX::ControlShape::RECTANGLE; //容器形状
StellarX::FillMode canvasFillMode = StellarX::FillMode::Solid; //容器填充模式
StellarX::LineStyle canvasLineStyle = StellarX::LineStyle::Solid; //线型
int canvaslinewidth = 1; //线
COLORREF canvasBorderClor = RGB(0, 0, 0);//边框颜色
COLORREF canvasBorderClor = RGB(0, 0, 0); //边框颜色
COLORREF canvasBkClor = RGB(255,255,255); //背景颜色
void clearAllControls(); // 清除所有子控件
//检查是否对话框是否可见
bool IsVisible() const override { return false; }
//获取对话框类型
bool model() const override { return false; }
// 清除所有子控件
void clearAllControls();
public:
Canvas();
Canvas(int x, int y, int width, int height);
@@ -49,7 +44,6 @@ public:
bool handleEvent(const ExMessage& msg) override;
//添加控件
void addControl(std::unique_ptr<Control> control);
//设置容器样式
void setShape(StellarX::ControlShape shape);
//设置容器填充模式
@@ -62,6 +56,9 @@ public:
void setCanvasLineStyle(StellarX::LineStyle style);
//设置线段宽度
void setLinewidth(int width);
private:
//用来检查对话框是否模态,此控件不做实现
bool model() const override { return false; };
};

View File

@@ -16,6 +16,16 @@
* @作者: 我在人间做废物
******************************************************************************/
#pragma once
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#endif
#ifndef WINVER
#define WINVER _WIN32_WINNT
#endif
#include <windows.h>
#include <vector>
#include <memory>
#include <easyx.h>
@@ -24,13 +34,19 @@
#include <string>
#include <functional>
#include "CoreTypes.h"
class Control
{
protected:
int x, y; // 左上角坐标
int width, height; // 控件尺寸
bool dirty = true; // 是否重绘
bool show = true; // 是否显示
/* == 背景快照 == */
IMAGE* saveBkImage = nullptr;
int saveBkX = 0, saveBkY = 0; // 快照保存起始坐标
int saveWidth = 0, saveHeight = 0; // 快照保存尺寸
bool hasSnap = false; // 当前是否持有有效快照
StellarX::RouRectangle rouRectangleSize; // 圆角矩形椭圆宽度和高度
@@ -40,7 +56,6 @@ protected:
COLORREF* currentBorderColor = new COLORREF(); // 边框颜色
LINESTYLE* currentLineStyle = new LINESTYLE(); // 保存当前线型
public:
Control(const Control&) = delete;
Control& operator=(const Control&) = delete;
Control(Control&&) = default;
@@ -48,25 +63,31 @@ public:
Control() : x(0), y(0), width(100), height(100) {}
Control(int x, int y, int width, int height)
: x(x), y(y), width(width), height(height) {
}
: x(x), y(y), width(width), height(height) {}
public:
virtual ~Control() {
virtual ~Control()
{
delete currentFont;
delete currentColor;
delete currentBkColor;
delete currentBorderColor;
delete currentLineStyle;
currentFont = nullptr;
currentFont = nullptr;
currentColor = nullptr;
currentBkColor = nullptr;
currentBorderColor = nullptr;
currentLineStyle = nullptr;
}
protected:
void saveBackground(int x, int y, int w, int h);
void restBackground(); // putimage 回屏
void discardBackground(); // 释放快照(窗口重绘/尺寸变化后必须作废)
public:
//释放快照重新保存,在尺寸变化时更新背景快照避免尺寸变化导致显示错位
void updateBackground();
// 获取位置和尺寸
int getX() const { return x; }
int getY() const { return y; }
@@ -74,16 +95,25 @@ protected:
int getHeight() const { return height; }
int getRight() const { return x + width; }
int getBottom() const { return y + height; }
void setX(int x) { this->x = x; dirty = true; }
void setY(int y) { this->y = y; dirty = true; }
void setWidth(int width) { this->width = width; dirty = true; }
void setHeight(int height) { this->height = height; dirty = true; }
public:
//设置是否重绘
void setDirty(bool dirty) { this->dirty = dirty; }
virtual void draw() = 0;
virtual bool handleEvent(const ExMessage& msg) = 0;//返回true代表事件已消费
//用来检查非模态对话框是否可见,其他控件不用实现
virtual bool IsVisible() const = 0;
//设置是否显示
void setShow(bool show) { this->show = show; }
//检查控件是否可见
bool IsVisible() const { return show; };
//用来检查对话框是否模态,其他控件不用实现
virtual bool model()const = 0;
protected:
void saveStyle();
void restoreStyle();

View File

@@ -111,7 +111,7 @@ namespace StellarX
* @使用示例:
* LineStyle var = LineStyle::Solid;
*/
enum class LineStyle
enum class LineStyle
{
Solid = PS_SOLID, // 实线
Dash = PS_DASH, // 虚线
@@ -251,7 +251,7 @@ namespace StellarX
};
// 消息框类型
enum class MessageBoxType
enum class MessageBoxType
{
OK, // 只有确定按钮
OKCancel, // 确定和取消按钮
@@ -262,7 +262,7 @@ namespace StellarX
};
// 消息框返回值
enum class MessageBoxResult
enum class MessageBoxResult
{
OK = 1, // 确定按钮
Cancel = 2, // 取消按钮
@@ -272,4 +272,51 @@ namespace StellarX
Retry = 4, // 重试按钮
Ignore = 5 // 忽略按钮
};
#if 0 //布局管理器相关 —待实现—
/*
*
*@枚举名称: LayoutKind
* @功能描述 : 定义布局管理类型
*
*@详细说明 :
* 根据布局管理类型,控件可以有不同的布局方式。
* 用户可以在具体情况下设置布局管理类型。
*
* @取值说明 :
* Absolute不管保持子控件自己的坐标向后兼容
* HBox 水平方向排队;支持固定宽、权重分配、对齐、拉伸。
* VBox 竖直方向排队;同上。
* Grid网格按行列摆支持固定/自适应/权重行列;支持跨行/跨列;单元内对齐/拉伸。
*
*/
// 布局类型
enum class LayoutKind
{
Absolute = 1,
HBox,
VBox,
Grid,
Flow,
Stack
};
// 布局参数
struct LayoutParams
{
// 边距左、右、上、下
int marginL = 0, marginR = 0, marginT = 0, marginB = 0;
// 固定尺寸(>=0 强制;-1 用控件当前尺寸)
int fixedW = -1, fixedH = -1;
// 主轴权重HBox=宽度、VBox=高度、Grid见下
float weight = 0.f;
// 对齐(非拉伸时生效)
enum Align { Start = 0, Center = 1, End = 2, Stretch = 3 };
int alignX = Start; // HBox: 次轴=YVBox: 次轴=XGrid: 单元内
int alignY = Start; // Grid 控制单元内垂直HBox / VBox通常只用 alignX
// Grid 专用(可先不做)
int gridRow = 0, gridCol = 0, rowSpan = 1, colSpan = 1;
// Flow 专用(可先不做)
int flowBreak = 0; // 1=强制换行
};
#endif
}

View File

@@ -20,7 +20,7 @@
#pragma once
#include"StellarX.h"
#define closeButtonWidth 20 //关闭按钮宽度
#define closeButtonWidth 23 //关闭按钮宽度
#define closeButtonHeight 20 //关闭按钮高度 同时作为对话框标题栏高度
#define functionButtonWidth 70 //按钮宽度
#define functionButtonHeight 30 //按钮高度
@@ -39,10 +39,6 @@ class Dialog : public Canvas
int buttonNum = 0; // 按钮数量
int BorderWidth = 2; //边框宽度
IMAGE* saveBkImage = nullptr; // 用于保存背景图像
int saveBkX = 0, saveBkY = 0; // 保存背景的位置
int saveBkWidth = 0, saveBkHeight = 0; // 保存背景的尺寸
StellarX::MessageBoxType type = StellarX::MessageBoxType::OK; //对话框类型
std::string titleText = "提示"; //标题文本
std::unique_ptr<Label> title = nullptr; //标题标签
@@ -54,7 +50,6 @@ class Dialog : public Canvas
bool needsInitialization = true; //是否需要初始化
bool close = false; //是否关闭
bool modal = true; //是否模态
bool isVisible = false; //是否可见
COLORREF backgroundColor = RGB(240, 240, 240); //背景颜色
COLORREF borderColor = RGB(100, 100, 100); //边框颜色
@@ -68,10 +63,10 @@ class Dialog : public Canvas
StellarX::MessageBoxResult result = StellarX::MessageBoxResult::Cancel; // 对话框结果
public:
bool shouldClose = false; //是否应该关闭
bool isCleaning = false; //是否正在清理
bool pendingCleanup = false; //延迟清理
public:
StellarX::ControlText textStyle; // 字体样式
// 清理方法声明
void performDelayedCleanup();
@@ -81,6 +76,8 @@ public:
void SetResultCallback(std::function<void(StellarX::MessageBoxResult)> cb);
//获取对话框消息,用以去重
std::string GetCaption() const;
//获取对话框消息,用以去重
std::string GetText() const;
public:
@@ -100,13 +97,9 @@ public:
void SetModal(bool modal);
// 设置对话框结果
void SetResult(StellarX::MessageBoxResult result);
// 获取对话框结果
StellarX::MessageBoxResult GetResult() const;
// 获取模态属性
bool getModal() const;
// 检查是否可见
bool IsVisible() const override;
//获取对话框类型
bool model() const override;
@@ -114,6 +107,9 @@ public:
void Show();
// 关闭对话框
void Close();
//初始化
void setInitialization(bool init);
private:
// 初始化按钮
@@ -128,8 +124,7 @@ private:
void getTextSize();
//初始化对话框尺寸
void initDialogSize();
// 初始化对话框
void initializeDialog();
// 清除所有控件

View File

@@ -28,13 +28,13 @@ namespace StellarX
{
public:
// 模态:阻塞直到关闭,返回结果
static MessageBoxResult ShowModal(Window& wnd,
static MessageBoxResult showModal(Window& wnd,
const std::string& text,
const std::string& caption = "提示",
MessageBoxType type = MessageBoxType::OK);
// 非模态:立即返回,通过回调异步获取结果
static void ShowAsync(Window& wnd,
static void showAsync(Window& wnd,
const std::string& text,
const std::string& caption = "提示",
MessageBoxType type = MessageBoxType::OK,

View File

@@ -22,20 +22,20 @@
* @包含顺序:
* 1. CoreTypes.h - 基础类型定义
* 2. Control.h - 控件基类
* 3. 其他具体控件头文件
* 3. ...其他具体控件头文件
* 4. Dialog继承自 CanvasDialog 为可包含子控件的对话框容器)
* 5.MessageBox对话框工厂提供便捷的模态/非模态调用方式
* 5. MessageBox对话框工厂提供便捷的模态/非模态调用方式
******************************************************************************/
#pragma once
#include "CoreTypes.h"
#include "Control.h"
#include"Button.h"
#include"Canvas.h"
#include"Window.h"
#include"Button.h"
#include"Label.h"
#include"TextBox.h"
#include"Canvas.h"
#include"Table.h"
#include"Dialog.h"
#include"MessageBox.h"

View File

@@ -30,6 +30,8 @@ class Label : public Control
//标签事件处理(标签无事件)不实现具体代码
bool handleEvent(const ExMessage& msg) override { return false; }
//用来检查对话框是否模态,此控件不做实现
bool model() const override { return false; };
public:
StellarX::ControlText textStyle; //标签文本样式
public:
@@ -37,6 +39,7 @@ public:
Label(int x, int y, std::string text = "标签",COLORREF textcolor = BLACK, COLORREF bkColor= RGB(255,255,255));
void draw() override;
void hide();
//设置标签背景是否透明
void setTextdisap(bool key);
//设置标签文本颜色
@@ -45,13 +48,6 @@ public:
void setTextBkColor(COLORREF color);
//设置标签文本
void setText(std::string text);
private:
//检查是否对话框是否可见
bool IsVisible() const override { return false; }
//获取对话框类型
bool model() const override { return false; }
};

View File

@@ -34,8 +34,6 @@ private:
std::vector<int> colWidths; // 每列的宽度
std::vector<int> lineHeights; // 每行的高度
IMAGE* saveBkImage = nullptr;
int rowsPerPage = 5; // 每页显示的行数
int currentPage = 1; // 当前页码
int totalPages = 1; // 总页数
@@ -67,11 +65,9 @@ private:
void drawHeader(); //绘制表头
void drawPageNum(); //绘制页码信息
void drawButton(); //绘制翻页按钮
//检查是否对话框是否可见
bool IsVisible() const override { return false; }
//获取对话框类型
bool model() const override { return false; }
private:
//用来检查对话框是否模态,此控件不做实现
bool model() const override { return false; };
public:
StellarX::ControlText textStyle; // 文本样式

View File

@@ -29,11 +29,6 @@ class TextBox : public Control
COLORREF textBoxBkClor = RGB(255, 255, 255); //背景颜色
COLORREF textBoxBorderClor = RGB(0,0,0); //边框颜色
//检查是否对话框是否可见
bool IsVisible() const override { return false; }
//获取对话框类型
bool model() const override { return false; }
public:
StellarX::ControlText textStyle; //文本样式
@@ -56,6 +51,9 @@ public:
//获取文本
std::string getText() const;
private:
//用来检查对话框是否模态,此控件不做实现
bool model() const override { return false; };
};

View File

@@ -24,10 +24,17 @@ class Window
int width; //窗口宽度
int height; //窗口高度
int windowMode = NULL; //窗口模式
// --- 尺寸变化去抖用 ---
int pendingW;
int pendingH;
bool needResizeDirty = false;
HWND hWnd = NULL; //窗口句柄
std::string headline; //窗口标题
COLORREF wBkcolor = BLACK; //窗口背景
IMAGE* background = nullptr; //窗口背景图片
std::string bkImageFile; //窗口背景图片文件名
std::vector<std::unique_ptr<Control>> controls; //控件管理
std::vector<std::unique_ptr<Control>> dialogs; //对话框管理
@@ -43,9 +50,8 @@ public:
void draw();
void draw(std::string pImgFile);
//事件循环
void runEventLoop();
int runEventLoop();
//设置窗口背景图片
void setBkImage(std::string pImgFile);
//设置窗口背景颜色
void setBkcolor(COLORREF c);
@@ -56,7 +62,7 @@ public:
//添加对话框
void addDialog(std::unique_ptr<Control> dialogs);
//检查是否已有对话框显示用于去重,防止工厂模式调用非模态对话框,多次打开污染对话框背景快照
bool hasNonModalDialogWithCaption(const std::string& caption) const;
bool hasNonModalDialogWithCaption(const std::string& caption, const std::string& message) const;
//获取窗口句柄
HWND getHwnd() const;