feat: add a new awesome feature
This commit is contained in:
+5
-5
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -358,7 +358,7 @@ bool Table::handleEvent(const ExMessage& msg)
|
||||
consume = nextButton->handleEvent(msg);
|
||||
}
|
||||
if (dirty)
|
||||
requestRepaint();
|
||||
requestRepaint(parent);
|
||||
return consume;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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
@@ -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