Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cc08187ced | |||
| c10e72b3fe | |||
| 6218ba54e3 | |||
| 7b087e296a | |||
| 8dee285de8 | |||
| d16b9bc226 | |||
| 270c6f5293 |
29
.github/workflows/mirror-to-gitcode.yml
vendored
Normal file
29
.github/workflows/mirror-to-gitcode.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: Mirror to GitCode
|
||||
on:
|
||||
push:
|
||||
branches: [ "**" ] # 任意分支推送触发
|
||||
create:
|
||||
tags: [ "*" ] # 新建 tag 触发
|
||||
workflow_dispatch: # 支持手动触发
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
mirror:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # 必须拿全历史+所有 tag
|
||||
- name: Push --mirror to GitCode
|
||||
env:
|
||||
GITCODE_USER: ${{ secrets.GITCODE_USER }}
|
||||
GITCODE_TOKEN: ${{ secrets.GITCODE_TOKEN }}
|
||||
run: |
|
||||
set -e
|
||||
git config --global user.name "mirror-bot"
|
||||
git config --global user.email "mirror-bot@users.noreply.github.com"
|
||||
# 如果你的命名空间不是个人用户,而是组织,请把 ${GITCODE_USER} 换成组织名
|
||||
git remote add gitcode https://${GITCODE_USER}:${GITCODE_TOKEN}@gitcode.com/${GITCODE_USER}/StellarX.git
|
||||
git push --prune --mirror gitcode
|
||||
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
[中文文档](CHANGELOG.md)
|
||||
|
||||
## [v2.2.1] - 2025-11-04
|
||||
|
||||
==This release is a hotfix for v2.2.0==
|
||||
|
||||
### ✅ Fixed
|
||||
|
||||
- The `TabControl` class overrode the base class's `setDirty` method to ensure synchronized update status between the tab and its page list.
|
||||
- The `Canvas` container, special container `TabControl`, and dialog `Dialog` overrode the `requestRepaint` method. When control bubbling propagates upward, the parent pointer is passed. Repaint requests now only bubble up one level to the parent and no longer propagate to the root. Furthermore, the entire parent container is no longer repainted; instead, the parent container repaints only the dirtied child controls, avoiding flickering caused by frequent repaints of the entire container.
|
||||
- The `saveBackground` and `restoreBackground` methods were overridden in `Dialog` to ensure no border remnants remain after the dialog is closed.
|
||||
|
||||
### ⚙️ Changed
|
||||
|
||||
- Completely disabled copy and move semantics for the `Control` class:
|
||||
`Control(const Control&) = delete;`
|
||||
`Control& operator=(const Control&) = delete;`
|
||||
`Control(Control&&) = delete;`
|
||||
`Control& operator=(Control&&) = delete;`
|
||||
|
||||
## [v2.2.0] - 2025-11-02
|
||||
|
||||
**Highlights**: Officially introduces the TabControl, enhances control show/hide and layout responsiveness, and refines the text styling mechanism; fixes several UI details to improve stability.
|
||||
|
||||
21
CHANGELOG.md
21
CHANGELOG.md
@@ -7,6 +7,27 @@ StellarX 项目所有显著的变化都将被记录在这个文件中。
|
||||
|
||||
[English document](CHANGELOG.en.md)
|
||||
|
||||
## [v2.2.1] - 2025 - 11 - 4
|
||||
|
||||
==此版本为v2.2.0的修复版本==
|
||||
|
||||
### ✅ 修复
|
||||
|
||||
- `TabControl`类重写了基类的`setDirty`方法保证页签+页列表同步更新
|
||||
|
||||
状态
|
||||
|
||||
- `Canvas`容器和特殊容器`TabControl`以及对话框`Dialog`重写`requestRepaint`方法,控件向上冒泡时传递父指针,请求重绘时只向上到父一级,不再传递到根。并且不再重绘整个父容器,而是由父容器重绘标脏的子控件,避免了频繁真个容器重绘导致的频闪
|
||||
|
||||
- `Dialog`中重写了`saveBackground`和`restBackground`方法,保证对话框关闭后不会有边框残留
|
||||
|
||||
### ⚙️ 变更
|
||||
|
||||
- 彻底禁用`Control`的移动构造`Control(const Control&) = delete;`
|
||||
`Control& operator=(const Control&) = delete;`
|
||||
`Control(Control&&) = delete;`
|
||||
`Control& operator=(Control&&) = delete;`
|
||||
|
||||
## [v2.2.0] - 2025-11-02
|
||||
|
||||
**重点**:正式引入选项卡控件(TabControl),增强控件显隐与布局响应能力,并完善文本样式机制;修复若干UI细节问题以提升稳定性。
|
||||
|
||||
13
README.en.md
13
README.en.md
@@ -7,8 +7,8 @@
|
||||

|
||||
[](https://github.com/Ysm-04/StellarX)
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
@@ -25,7 +25,14 @@ This is a **teaching-grade and tooling-grade** framework that helps developers u
|
||||
|
||||
------
|
||||
|
||||
## 🆕 What’s new in v2.2.0
|
||||
## **🆕 v2.2.1 (Hotfix for v2.2.0)**
|
||||
|
||||
- Addressed a flickering issue that occurred when using the Canvas and TabControl containers.
|
||||
- Fixed issues where border remnants and functional buttons could persist after closing a Dialog.
|
||||
|
||||
For details, please refer to the [CHANGELOG.en](CHANGELOG.en.md).
|
||||
|
||||
## What’s new in v2.2.0
|
||||
|
||||
- **New TabControl for multi-page tabbed UIs:** With `TabControl`, it’s easy to create a tabbed layout. Tabs can be arranged on the top, bottom, left, or right, and clicking switches the displayed page. Suitable for settings panels and multi-view switching.
|
||||
- **Enhanced control show/hide and resize responsiveness:** All controls now share a unified interface (`setIsVisible`) to toggle visibility. When a container control is hidden, its child controls automatically hide/show with it. Meanwhile, we introduce `onWindowResize` for controls to respond to window size changes so elements update in sync after resizing, eliminating artifacts or misalignment.
|
||||
|
||||
23
README.md
23
README.md
@@ -2,13 +2,18 @@
|
||||
|
||||
[English document](README.en.md)
|
||||
|
||||
> 本仓库为 **StellarX** 主仓:开发与 Issue/PR 均在 GitHub 进行。
|
||||
> GitCode 仅为只读镜像:如需反馈请到 GitHub:https://github.com/Ysm-04/StellarX
|
||||
|
||||
[](https://gitcode.com/Ysm-04/StellarX)
|
||||
|
||||
------
|
||||
|
||||

|
||||
[](https://github.com/Ysm-04/StellarX)
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
@@ -25,7 +30,17 @@
|
||||
|
||||
---
|
||||
|
||||
## 🆕 v2.2.0 有何变化
|
||||
## 🆕v2.2.1(v2.2.0修复版)
|
||||
|
||||
- 解决了使用Canvas和TabControl容器时,出现频闪问题
|
||||
|
||||
- 修复了Dialog对话框关闭时概率出边边框残留和功能按钮残留问题
|
||||
|
||||
详情参考[更新日志](CHANGELOG.md)
|
||||
|
||||
|
||||
|
||||
## V2.2.0 有何变化
|
||||
|
||||
- **新增 TabControl 控件,实现多页面选项卡界面:** 通过 `TabControl` 可以轻松创建选项卡式布局,支持页签在上下左右排列、点击切换显示不同内容页面。适用于设置面板、多视图切换等场景。
|
||||
- **控件显隐与布局响应能力增强:** 现在所有控件都可以使用统一接口动态隐藏或显示(`setIsVisible`),容器控件隐藏时其内部子控件会自动随之隐藏/显示。与此同时,引入控件对窗口尺寸变化的响应机制(`onWindowResize`),窗口拉伸后界面各元素可协调更新,杜绝拉伸过程中出现残影或错位。
|
||||
@@ -289,5 +304,5 @@ MIT(见 `LICENSE`)。
|
||||
## 📞 支持与反馈
|
||||
|
||||
- 查看 [examples/](examples/)
|
||||
- 查阅 [更新日志](CHANGELOG.md / CHANGELOG.en.md)
|
||||
- 查阅 [更新日志](CHANGELOG.md)[CHANGELOG](CHANGELOG.en.md)
|
||||
- 在 GitHub 提交 Issue
|
||||
@@ -60,6 +60,7 @@ public:
|
||||
void setIsVisible(bool visible) override;
|
||||
void setDirty(bool dirty) override;
|
||||
void onWindowResize() override;
|
||||
void requestRepaint(Control* parent)override;
|
||||
//获取子控件列表
|
||||
std::vector<std::unique_ptr<Control>>& getControls() { return controls; }
|
||||
private:
|
||||
|
||||
@@ -61,8 +61,8 @@ protected:
|
||||
|
||||
Control(const Control&) = delete;
|
||||
Control& operator=(const Control&) = delete;
|
||||
Control(Control&&) = default;
|
||||
Control& operator=(Control&&) = default;
|
||||
Control(Control&&) = delete;
|
||||
Control& operator=(Control&&) = delete;
|
||||
|
||||
Control() : localx(0),x(0), localy(0),y(0), localWidth(100),width(100),height(100), localHeight(100) {}
|
||||
Control(int x, int y, int width, int height)
|
||||
@@ -85,14 +85,15 @@ public:
|
||||
discardBackground();
|
||||
}
|
||||
protected:
|
||||
virtual void requestRepaint();
|
||||
//向上请求重绘
|
||||
virtual void requestRepaint(Control* parent);
|
||||
//根控件/无父时触发重绘
|
||||
virtual void onRequestRepaintAsRoot();
|
||||
protected:
|
||||
//保存背景快照
|
||||
void saveBackground(int x, int y, int w, int h);
|
||||
virtual void saveBackground(int x, int y, int w, int h);
|
||||
// putimage 回屏
|
||||
void restBackground();
|
||||
virtual void restBackground();
|
||||
// 释放快照(窗口重绘/尺寸变化后必须作废)
|
||||
void discardBackground();
|
||||
public:
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#pragma once
|
||||
#include"StellarX.h"
|
||||
|
||||
#define closeButtonWidth 23 //关闭按钮宽度
|
||||
#define closeButtonWidth 30 //关闭按钮宽度
|
||||
#define closeButtonHeight 20 //关闭按钮高度 同时作为对话框标题栏高度
|
||||
#define functionButtonWidth 70 //按钮宽度
|
||||
#define functionButtonHeight 30 //按钮高度
|
||||
@@ -29,7 +29,7 @@
|
||||
#define buttonAreaHeight 50 //按钮区域高度
|
||||
#define titleToTextMargin 10 //标题到文本的距离
|
||||
#define textToBorderMargin 10 //文本到边框的距离
|
||||
|
||||
#define BorderWidth 3 //边框宽度
|
||||
class Dialog : public Canvas
|
||||
{
|
||||
Window& hWnd; //窗口引用
|
||||
@@ -37,7 +37,6 @@ class Dialog : public Canvas
|
||||
int textWidth = 0; //文本宽度
|
||||
int textHeight = 0; //文本高度
|
||||
int buttonNum = 0; // 按钮数量
|
||||
int BorderWidth = 2; //边框宽度
|
||||
|
||||
StellarX::MessageBoxType type = StellarX::MessageBoxType::OK; //对话框类型
|
||||
std::string titleText = "提示"; //标题文本
|
||||
@@ -124,11 +123,14 @@ private:
|
||||
void getTextSize();
|
||||
//初始化对话框尺寸
|
||||
void initDialogSize();
|
||||
|
||||
void saveBackground(int x, int y, int w, int h)override;
|
||||
|
||||
void restBackground()override;
|
||||
|
||||
|
||||
// 清除所有控件
|
||||
void clearControls();
|
||||
//创建对话框按钮
|
||||
std::unique_ptr<Button> createDialogButton(int x, int y, const std::string& text);
|
||||
void requestRepaint(Control* parent) override;
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
/*******************************************************************************
|
||||
* @文件: StellarX.h
|
||||
* @摘要: 星垣(StellarX) GUI框架 - 主包含头文件
|
||||
* @版本: v2.2.0
|
||||
* @版本: v2.2.1
|
||||
* @描述:
|
||||
* 一个为Windows平台打造的轻量级、模块化C++ GUI框架。
|
||||
* 基于EasyX图形库,提供简洁易用的API和丰富的控件。
|
||||
|
||||
@@ -62,5 +62,7 @@ public:
|
||||
int count() const;
|
||||
//通过页签文本返回索引
|
||||
int indexOf(const std::string& tabText) const;
|
||||
void setDirty(bool dirty) override;
|
||||
void requestRepaint(Control* parent)override;
|
||||
};
|
||||
|
||||
|
||||
@@ -22,10 +22,8 @@
|
||||
class Label : public Control
|
||||
{
|
||||
std::string text; //标签文本
|
||||
COLORREF textBkColor; //标签背景颜色
|
||||
bool textBkDisap = false; //标签背景是否透明
|
||||
|
||||
|
||||
COLORREF textBkColor; //标签背景颜色
|
||||
bool textBkDisap = false; //标签背景是否透明
|
||||
|
||||
//标签事件处理(标签无事件)不实现具体代码
|
||||
bool handleEvent(const ExMessage& msg) override { return false; }
|
||||
|
||||
@@ -76,6 +76,8 @@ public:
|
||||
COLORREF getBkcolor() const;
|
||||
//获取窗口背景图片
|
||||
IMAGE* getBkImage() const;
|
||||
//获取窗口背景图片文件名
|
||||
std::string getBkImageFile() const;
|
||||
//获取控件管理
|
||||
std::vector<std::unique_ptr<Control>>& getControls();
|
||||
|
||||
|
||||
@@ -275,7 +275,6 @@ void Button::draw()
|
||||
restoreStyle();//恢复默认字体样式和颜色
|
||||
dirty = false; //标记按钮不需要重绘
|
||||
|
||||
|
||||
}
|
||||
// 处理鼠标事件,检测点击和悬停状态
|
||||
// 根据按钮模式和形状进行不同的处理
|
||||
@@ -417,9 +416,11 @@ bool Button::handleEvent(const ExMessage& msg)
|
||||
|
||||
// 如果需要重绘,立即执行
|
||||
if (dirty)
|
||||
requestRepaint();
|
||||
if(tipEnabled && tipVisible)
|
||||
requestRepaint(parent);
|
||||
|
||||
if (tipEnabled && tipVisible)
|
||||
tipLabel.draw();
|
||||
|
||||
return consume;
|
||||
}
|
||||
|
||||
@@ -554,7 +555,7 @@ void Button::setButtonClick(BOOL click)
|
||||
flushmessage(EX_MOUSE | EX_KEY);
|
||||
}
|
||||
if (dirty)
|
||||
requestRepaint();
|
||||
requestRepaint(parent);
|
||||
}
|
||||
|
||||
|
||||
@@ -684,7 +685,6 @@ void Button::hideTooltip()
|
||||
|
||||
void Button::refreshTooltipTextForState()
|
||||
{
|
||||
if (!tipUserOverride) return;
|
||||
if (tipUserOverride) return; // 用户显式设置过 tipText,保持不变
|
||||
if(mode==StellarX::ButtonMode::NORMAL)
|
||||
tipLabel.setText(tipTextClick);
|
||||
|
||||
@@ -27,8 +27,9 @@ void Canvas::draw()
|
||||
setfillcolor(canvasBkClor);//设置填充色
|
||||
setfillstyle((int)canvasFillMode);//设置填充模式
|
||||
setlinestyle((int)canvasLineStyle, canvaslinewidth);
|
||||
|
||||
if ((saveBkX != this->x) || (saveBkY != this->y) || (!hasSnap) || (saveWidth != this->width) || (saveHeight != this->height) || !saveBkImage)
|
||||
saveBackground(this->x, this->y, this->width, this->height);
|
||||
saveBackground(x, y, width, height);
|
||||
// 恢复背景(清除旧内容)
|
||||
restBackground();
|
||||
//根据画布形状绘制
|
||||
@@ -69,7 +70,7 @@ bool Canvas::handleEvent(const ExMessage& msg)
|
||||
consumed |= it->get()->handleEvent(msg);
|
||||
if (it->get()->isDirty()) anyDirty = true;
|
||||
}
|
||||
if (anyDirty) requestRepaint();
|
||||
if (anyDirty) requestRepaint(parent);
|
||||
return consumed;
|
||||
}
|
||||
|
||||
@@ -159,5 +160,20 @@ void Canvas::onWindowResize()
|
||||
ch->onWindowResize();
|
||||
}
|
||||
|
||||
void Canvas::requestRepaint(Control* parent)
|
||||
{
|
||||
if (this == parent)
|
||||
{
|
||||
for (auto& control : controls)
|
||||
if (control->isDirty() && control->IsVisible())
|
||||
{
|
||||
control->draw();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
onRequestRepaintAsRoot();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -77,9 +77,9 @@ void Control::restoreStyle()
|
||||
setfillstyle(BS_SOLID);//恢复填充
|
||||
}
|
||||
|
||||
void Control::requestRepaint()
|
||||
void Control::requestRepaint(Control* parent)
|
||||
{
|
||||
if (parent) parent->requestRepaint(); // 向上冒泡
|
||||
if (parent) parent->requestRepaint(parent); // 向上冒泡
|
||||
else onRequestRepaintAsRoot(); // 到根控件/窗口兜底
|
||||
}
|
||||
|
||||
@@ -93,9 +93,9 @@ void Control::onRequestRepaintAsRoot()
|
||||
|
||||
void Control::saveBackground(int x, int y, int w, int h)
|
||||
{
|
||||
|
||||
if (w <= 0 || h <= 0) return;
|
||||
saveBkX = x; saveBkY = y; saveWidth = w; saveHeight = h;
|
||||
|
||||
if (saveBkImage)
|
||||
{
|
||||
//尺寸变了才重建,避免反复 new/delete
|
||||
|
||||
@@ -34,21 +34,19 @@ void Dialog::draw()
|
||||
if (dirty && show)
|
||||
{
|
||||
// 保存当前绘图状态
|
||||
saveStyle();
|
||||
|
||||
|
||||
if ((saveBkX != this->x) || (saveBkY != this->y) || (!hasSnap) || (saveWidth != this->width) || (saveHeight != this->height) || !saveBkImage)
|
||||
saveBackground(this->x, this->y, this->width, this->height);
|
||||
saveStyle();
|
||||
|
||||
Canvas::setBorderColor(this->borderColor);
|
||||
Canvas::setLinewidth(this->BorderWidth);
|
||||
Canvas::setLinewidth(BorderWidth);
|
||||
Canvas::setCanvasBkColor(this->backgroundColor);
|
||||
Canvas::setShape(StellarX::ControlShape::ROUND_RECTANGLE);
|
||||
|
||||
if ((saveBkX != this->x) || (saveBkY != this->y) || (!hasSnap) || (saveWidth != this->width) || (saveHeight != this->height) || !saveBkImage)
|
||||
saveBackground(this->x, this->y, this->width, this->height);
|
||||
//设置所有控件为脏状态
|
||||
for(auto& c :this->controls)
|
||||
c->setDirty(true);
|
||||
|
||||
/*for(auto& c :this->controls)
|
||||
c->setDirty(true);*/
|
||||
restBackground();
|
||||
Canvas::draw();
|
||||
|
||||
//绘制消息文本
|
||||
@@ -88,12 +86,12 @@ bool Dialog::handleEvent(const ExMessage& msg)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// 如果正在清理或标记为待清理,则不处理事件
|
||||
if (pendingCleanup || isCleaning)
|
||||
return false;
|
||||
// 模态对话框:点击对话框外部区域时,发出提示音(\a)并吞噬该事件,不允许操作背景内容。
|
||||
if (modal && msg.message == WM_LBUTTONUP &&
|
||||
if (modal && msg.message == WM_LBUTTONUP &&
|
||||
(msg.x < x || msg.x > x + width || msg.y < y || msg.y > y + height))
|
||||
{
|
||||
std::cout << "\a" << std::endl;
|
||||
@@ -170,10 +168,11 @@ void Dialog::Show()
|
||||
shouldClose = false;
|
||||
|
||||
if (modal)
|
||||
{
|
||||
{
|
||||
// 模态对话框需要阻塞当前线程直到对话框关闭
|
||||
while (show && !close)
|
||||
{
|
||||
|
||||
// 处理消息
|
||||
ExMessage msg;
|
||||
if (peekmessage(&msg, EX_MOUSE | EX_KEY))
|
||||
@@ -191,14 +190,13 @@ void Dialog::Show()
|
||||
// 重绘
|
||||
if (dirty)
|
||||
{
|
||||
requestRepaint();
|
||||
requestRepaint(parent);
|
||||
FlushBatchDraw();
|
||||
}
|
||||
|
||||
// 避免CPU占用过高
|
||||
Sleep(10);
|
||||
}
|
||||
|
||||
// 模态对话框关闭后执行清理
|
||||
if (pendingCleanup && !isCleaning)
|
||||
performDelayedCleanup();
|
||||
@@ -218,9 +216,7 @@ void Dialog::Close()
|
||||
close = true;
|
||||
dirty = true;
|
||||
pendingCleanup = true; // 只标记需要清理,不立即执行
|
||||
auto& c = hWnd.getControls();
|
||||
for(auto& control:c)
|
||||
control->setDirty(true);
|
||||
|
||||
|
||||
// 工厂模式下非模态触发回调 返回结果
|
||||
if (resultCallback&& !modal)
|
||||
@@ -461,6 +457,7 @@ void Dialog::initCloseButton()
|
||||
StellarX::ControlShape::B_RECTANGLE
|
||||
);
|
||||
but.get()->setButtonFalseColor(this->backgroundColor);
|
||||
but.get()->enableTooltip(false);
|
||||
but->setOnClickListener([this]() {
|
||||
this->SetResult(StellarX::MessageBoxResult::Cancel);
|
||||
this->hWnd.dialogClose = true;
|
||||
@@ -586,6 +583,31 @@ void Dialog::initDialogSize()
|
||||
initCloseButton(); // 初始化关闭按钮
|
||||
}
|
||||
|
||||
void Dialog::saveBackground(int x, int y, int w, int h)
|
||||
{
|
||||
if (w <= 0 || h <= 0) return;
|
||||
saveBkX = x; saveBkY = y; saveWidth = w; saveHeight = h;
|
||||
if (saveBkImage)
|
||||
{
|
||||
//尺寸变了才重建,避免反复 new/delete
|
||||
if (saveBkImage->getwidth() != w || saveBkImage->getheight() != h)
|
||||
{
|
||||
delete saveBkImage; saveBkImage = nullptr;
|
||||
}
|
||||
}
|
||||
if (!saveBkImage) saveBkImage = new IMAGE(w + BorderWidth*2, h + BorderWidth*2);
|
||||
|
||||
SetWorkingImage(nullptr); // ★抓屏幕
|
||||
getimage(saveBkImage, x - BorderWidth, y - BorderWidth, w + BorderWidth*2, h+ BorderWidth*2);
|
||||
hasSnap = true;
|
||||
}
|
||||
void Dialog::restBackground()
|
||||
{
|
||||
if (!hasSnap || !saveBkImage) return;
|
||||
// 直接回贴屏幕(与抓取一致)
|
||||
SetWorkingImage(nullptr);
|
||||
putimage(saveBkX - BorderWidth, saveBkY - BorderWidth,saveBkImage);
|
||||
}
|
||||
|
||||
// 延迟清理策略:由于对话框绘制时保存了背景快照,必须在对话框隐藏后、
|
||||
// 所有控件析构前恢复背景,否则会导致背景图像被错误覆盖。
|
||||
@@ -596,20 +618,22 @@ void Dialog::performDelayedCleanup()
|
||||
|
||||
isCleaning = true;
|
||||
|
||||
// 清除所有控件
|
||||
auto& c = hWnd.getControls();
|
||||
for (auto& control : c)
|
||||
control->setDirty(true);
|
||||
|
||||
controls.clear();
|
||||
|
||||
// 重置指针
|
||||
closeButton = nullptr;
|
||||
title.reset();
|
||||
|
||||
// 释放背景图像资源
|
||||
if (saveBkImage && hasSnap)
|
||||
{
|
||||
restBackground();
|
||||
FlushBatchDraw();
|
||||
discardBackground();
|
||||
}
|
||||
|
||||
// 重置状态
|
||||
needsInitialization = true;
|
||||
pendingCleanup = false;
|
||||
@@ -655,4 +679,18 @@ std::unique_ptr<Button> Dialog::createDialogButton(int x, int y, const std::stri
|
||||
return btn;
|
||||
}
|
||||
|
||||
void Dialog::requestRepaint(Control* parent)
|
||||
{
|
||||
if (this == parent)
|
||||
{
|
||||
for (auto& control : controls)
|
||||
if (control->isDirty()&&control->IsVisible())
|
||||
{
|
||||
control->draw();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
onRequestRepaintAsRoot();
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ bool TabControl::handleEvent(const ExMessage& msg)
|
||||
break;
|
||||
}
|
||||
if (dirty)
|
||||
requestRepaint();
|
||||
requestRepaint(parent);
|
||||
return consume;
|
||||
}
|
||||
|
||||
@@ -347,4 +347,35 @@ int TabControl::indexOf(const std::string& tabText) const
|
||||
return idx;
|
||||
}
|
||||
|
||||
void TabControl::setDirty(bool dirty)
|
||||
{
|
||||
this->dirty = dirty;
|
||||
for (auto& c : controls)
|
||||
{
|
||||
c.first->setDirty(dirty);
|
||||
c.second->setDirty(dirty);
|
||||
}
|
||||
}
|
||||
|
||||
void TabControl::requestRepaint(Control* parent)
|
||||
{
|
||||
if (this == parent)
|
||||
{
|
||||
for (auto& control : controls)
|
||||
{
|
||||
if (control.first->isDirty() && control.first->IsVisible())
|
||||
{
|
||||
control.first->draw();
|
||||
break;
|
||||
}
|
||||
else if (control.second->isDirty()&&control.second->IsVisible())
|
||||
{
|
||||
control.second->draw();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
onRequestRepaintAsRoot();
|
||||
}
|
||||
|
||||
@@ -358,7 +358,7 @@ bool Table::handleEvent(const ExMessage& msg)
|
||||
consume = nextButton->handleEvent(msg);
|
||||
}
|
||||
if (dirty)
|
||||
requestRepaint();
|
||||
requestRepaint(parent);
|
||||
return consume;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ bool TextBox::handleEvent(const ExMessage& msg)
|
||||
flushmessage(EX_MOUSE | EX_KEY);
|
||||
}
|
||||
if (dirty)
|
||||
requestRepaint();
|
||||
requestRepaint(parent);
|
||||
|
||||
if (click)
|
||||
click = false;
|
||||
|
||||
@@ -69,7 +69,14 @@ void Window::draw(std::string imagePath)
|
||||
hWnd = initgraph(width, height, windowMode);
|
||||
SetWindowText(hWnd, headline.c_str());
|
||||
loadimage(background, imagePath.c_str(), width, height, true);
|
||||
putimage(0, 0, background);
|
||||
if(background)
|
||||
putimage(0, 0, background);
|
||||
else
|
||||
{
|
||||
// 设置背景色并清屏
|
||||
setbkcolor(wBkcolor);
|
||||
cleardevice();
|
||||
}
|
||||
// 同样应用可拉伸样式
|
||||
LONG style = GetWindowLong(hWnd, GWL_STYLE);
|
||||
style |= WS_THICKFRAME | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
|
||||
@@ -78,7 +85,11 @@ void Window::draw(std::string imagePath)
|
||||
|
||||
// 绘制控件(含对话框)到窗口
|
||||
BeginBatchDraw();
|
||||
for (auto& control : controls) control->draw();
|
||||
for (auto& control : controls)
|
||||
{
|
||||
control->setDirty(true);
|
||||
control->draw();
|
||||
}
|
||||
for (auto& dlg : dialogs) dlg->draw();
|
||||
EndBatchDraw();
|
||||
}
|
||||
@@ -328,6 +339,11 @@ IMAGE* Window::getBkImage() const
|
||||
return this->background;
|
||||
}
|
||||
|
||||
std::string Window::getBkImageFile() const
|
||||
{
|
||||
return this->bkImageFile;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Control>>& Window::getControls()
|
||||
{
|
||||
return this->controls;
|
||||
|
||||
Reference in New Issue
Block a user