Refine dialog lifecycle cleanup

This commit is contained in:
Codex
2026-04-09 04:45:05 +08:00
parent 97710db9e3
commit 241a564095
2 changed files with 42 additions and 79 deletions
+41 -74
View File
@@ -163,80 +163,63 @@ void Dialog::Show()
show = true;
dirty = true;
needsInitialization = true;
close = false;
shouldClose = false;
hWnd.dialogOpen = true;// 通知窗口有对话框打开
if (modal)
{
// 模态对话框需要阻塞当前线程直到对话框关闭
if (modal)
// 记录当前窗口客户区尺寸,供轮询对比
RECT rc0;
GetClientRect(hWnd.getHwnd(), &rc0);
int lastW = rc0.right - rc0.left;
int lastH = rc0.bottom - rc0.top;
while (show)
{
// 记录当前窗口客户区尺寸,供轮询对比
RECT rc0;
GetClientRect(hWnd.getHwnd(), &rc0);
int lastW = rc0.right - rc0.left;
int lastH = rc0.bottom - rc0.top;
// ① 轮询窗口尺寸(不依赖 WM_SIZE)
RECT rc;
GetClientRect(hWnd.getHwnd(), &rc);
const int cw = rc.right - rc.left;
const int ch = rc.bottom - rc.top;
while (show && !close)
if (cw != lastW || ch != lastH)
{
// ① 轮询窗口尺寸(不依赖 WM_SIZE)
RECT rc;
GetClientRect(hWnd.getHwnd(), &rc);
const int cw = rc.right - rc.left;
const int ch = rc.bottom - rc.top;
lastW = cw;
lastH = ch;
SX_LOGD("Resize") <<SX_T("模态对话框检测到窗口大小变化:(", "Modal dialog detected window size change: (") << cw << "x" << ch << ")";
if (cw != lastW || ch != lastH)
{
lastW = cw;
lastH = ch;
SX_LOGD("Resize") <<SX_T("模态对话框检测到窗口大小变化:(", "Modal dialog detected window size change: (") << cw << "x" << ch << ")";
// 通知父窗口:有新尺寸 → 标记 needResizeDirty
hWnd.scheduleResizeFromModal(cw, ch);
// 通知父窗口:有新尺寸 → 标记 needResizeDirty
hWnd.scheduleResizeFromModal(cw, ch);
// 立即统一收口:父窗重绘 背景+普通控件(不会画到这只模态)
hWnd.pumpResizeIfNeeded();
// 立即统一收口:父窗重绘 背景+普通控件(不会画到这只模态)
hWnd.pumpResizeIfNeeded();
// 这只模态只重新居中,不参与拉伸;背景快照需要在新位置重抓。
recenterInHostWindow();
}
// ② 处理这只对话框的鼠标/键盘(沿用原来 EX_MOUSE | EX_KEY
ExMessage msg;
if (peekmessage(&msg, EX_MOUSE | EX_KEY))
{
handleEvent(msg);
if (shouldClose)
{
Close();
break;
}
}
// ③ 最后一笔:只画这只模态,保证永远在最上层
if (dirty)
{
BeginBatchDraw();
this->draw(); // 注意:不要 requestRepaint(parent),只画自己
EndBatchDraw();
dirty = false;
}
Sleep(10);
// 这只模态只重新居中,不参与拉伸;背景快照需要在新位置重抓。
recenterInHostWindow();
}
if (pendingCleanup && !isCleaning)
performDelayedCleanup();
}
else
{
// 非模态仍由主循环托管
dirty = true;
// ② 处理这只对话框的鼠标/键盘(沿用原来 EX_MOUSE | EX_KEY
ExMessage msg;
if (peekmessage(&msg, EX_MOUSE | EX_KEY))
{
handleEvent(msg);
if (!show)
break;
}
// ③ 最后一笔:只画这只模态,保证永远在最上层
if (dirty)
{
BeginBatchDraw();
this->draw(); // 注意:不要 requestRepaint(parent),只画自己
EndBatchDraw();
dirty = false;
}
Sleep(10);
}
// 模态对话框关闭后执行清理
if (pendingCleanup && !isCleaning)
performDelayedCleanup();
}
@@ -250,7 +233,6 @@ void Dialog::Close()
if (!show) return;
show = false;
close = true;
dirty = true;
pendingCleanup = true; // 只标记需要清理,不立即执行
@@ -259,20 +241,6 @@ void Dialog::Close()
resultCallback(this->result);
}
void Dialog::setInitialization(bool init)
{
if (init)
{
// 窗口缩放后的重建不能再回贴旧快照;父窗口接下来会做一次完整重绘。
invalidateBackgroundSnapshot();
invalidateLayout(true);
}
else
{
needsInitialization = false;
}
}
void Dialog::recenterInHostWindow()
{
if (!show)
@@ -713,7 +681,6 @@ void Dialog::performDelayedCleanup()
needsInitialization = true;
pendingCleanup = false;
isCleaning = false;
shouldClose = false;
}
void Dialog::SetResultCallback(std::function<void(StellarX::MessageBoxResult)> cb)
+1 -5
View File
@@ -45,8 +45,7 @@ class Dialog : public Canvas
std::string message; //提示信息
std::vector<std::string> lines; //消息内容按行分割
bool needsInitialization = true; //是否需要初始化
bool close = false; //是否关闭
bool needsInitialization = true; // 是否需要根据当前内容重新初始化布局和内部按钮
bool modal = true; //是否模态
COLORREF backgroundColor = RGB(240, 240, 240); //背景颜色
@@ -60,7 +59,6 @@ class Dialog : public Canvas
StellarX::MessageBoxResult result = StellarX::MessageBoxResult::Cancel; // 对话框结果
bool shouldClose = false; //是否应该关闭
bool isCleaning = false; //是否正在清理
bool pendingCleanup = false; //延迟清理
public:
@@ -103,8 +101,6 @@ public:
void Show();
// 关闭对话框
void Close();
//初始化
void setInitialization(bool init); // 历史接口:当前语义更接近“请求重新布局/重建”
// 宿主窗口变化时仅重新居中,不拉伸 Dialog 自身
void recenterInHostWindow();