feat: add a new awesome feature

This commit is contained in:
2025-11-04 16:48:53 +08:00
parent 8dee285de8
commit 7b087e296a
22 changed files with 210 additions and 58 deletions
+5 -5
View File
@@ -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);
+18 -2
View File
@@ -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();
}
+3 -3
View File
@@ -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
+58 -20
View File
@@ -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();
}
+32 -1
View File
@@ -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();
}
+1 -1
View File
@@ -358,7 +358,7 @@ bool Table::handleEvent(const ExMessage& msg)
consume = nextButton->handleEvent(msg);
}
if (dirty)
requestRepaint();
requestRepaint(parent);
return consume;
}
+1 -1
View File
@@ -91,7 +91,7 @@ bool TextBox::handleEvent(const ExMessage& msg)
flushmessage(EX_MOUSE | EX_KEY);
}
if (dirty)
requestRepaint();
requestRepaint(parent);
if (click)
click = false;
+18 -2
View File
@@ -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;