diff --git a/Button.cpp b/Button.cpp index ea8f03e..b766731 100644 --- a/Button.cpp +++ b/Button.cpp @@ -314,7 +314,7 @@ bool Button::handleEvent(const ExMessage& msg) } if (hover != oldHover) { - SX_LOGD("Button") << SX_T("悬停变化: ","hover change: ") << "id=" << id + SX_LOG_TRACE("Button") << SX_T("悬停变化: ","hover change: ") << "id=" << id << " text= " << text << " " << (oldHover ? 1 : 0) << "->" << (hover ? 1 : 0); } @@ -396,7 +396,7 @@ bool Button::handleEvent(const ExMessage& msg) // 到点就显示 if (GetTickCount64() - tipHoverTick >= (ULONGLONG)tipDelayMs) { - SX_LOGD("Button") << SX_T("提示信息显示: ","tooltip show:")<<" id = " << id <full draw: id=") << id << " dirty=" << (dirty ? 1 : 0) @@ -435,7 +435,7 @@ void Canvas::requestRepaint(Control* parent) return; } - SX_LOGD("Dirty") << SX_T("Canvas 请求局部重绘:id=", "Canvas::requestRepaint(partial): id=") << id; + SX_LOG_TRACE("Dirty") << SX_T("Canvas 请求局部重绘:id=", "Canvas::requestRepaint(partial): id=") << id; for (auto& control : controls) if (control->isDirty() && control->IsVisible()) @@ -444,7 +444,7 @@ void Canvas::requestRepaint(Control* parent) return; } - SX_LOGD("Dirty") << SX_T("Canvas 请求根级重绘:id=", "Canvas::requestRepaint(root): id=") << id; + SX_LOG_TRACE("Dirty") << SX_T("Canvas 请求根级重绘:id=", "Canvas::requestRepaint(root): id=") << id; onRequestRepaintAsRoot(); } diff --git a/Control.cpp b/Control.cpp index 62c62d3..e4fa405 100644 --- a/Control.cpp +++ b/Control.cpp @@ -139,7 +139,7 @@ void Control::requestRepaint(Control* parent) return; } - SX_LOGD("Dirty") << SX_T("请求重绘:id=","requestRepaint: id=") << id << " parent=" << (parent ? parent->getId() : "null"); + SX_LOG_TRACE("Dirty") << SX_T("请求重绘:id=","requestRepaint: id=") << id << " parent=" << (parent ? parent->getId() : "null"); if (parent) parent->requestRepaint(parent); // 交给容器处理(容器可局部重绘) else onRequestRepaintAsRoot(); // 根兜底 @@ -147,7 +147,7 @@ void Control::requestRepaint(Control* parent) void Control::onRequestRepaintAsRoot() { - SX_LOGI("Dirty") + SX_LOG_TRACE("Dirty") << SX_T("触发根重绘:id=", "onRequestRepaintAsRoot: id=") << id << SX_T("(从根节点开始重画)", " (root repaint)"); diff --git a/Dialog.cpp b/Dialog.cpp index 61e99b7..050de99 100644 --- a/Dialog.cpp +++ b/Dialog.cpp @@ -102,27 +102,19 @@ bool Dialog::handleEvent(const ExMessage& msg) void Dialog::SetTitle(const std::string& title) { this->titleText = title; - if (this->title) - { - this->title->setText(title); - } - dirty = true; + invalidateLayout(true); } void Dialog::SetMessage(const std::string& message) { this->message = message; - splitMessageLines(); - getTextSize(); - dirty = true; + invalidateLayout(true); } void Dialog::SetType(StellarX::MessageBoxType type) { this->type = type; - // 重新初始化按钮 - initButtons(); - dirty = true; + invalidateLayout(true); } void Dialog::SetModal(bool modal) @@ -255,9 +247,11 @@ void Dialog::setInitialization(bool init) { if (init) { - initDialogSize(); - saveBackground((x - BorderWidth), (y - BorderWidth), (width + 2 * BorderWidth), (height + 2 * BorderWidth)); - this->dirty = true; + invalidateLayout(true); + } + else + { + needsInitialization = false; } } @@ -547,8 +541,8 @@ void Dialog::getTextSize() settextstyle(textStyle.nHeight, textStyle.nWidth, textStyle.lpszFace, textStyle.nEscapement, textStyle.nOrientation, textStyle.nWeight, textStyle.bItalic, textStyle.bUnderline, textStyle.bStrikeOut); - int tempHeight = 0; - int tempWidth = 0; + this->textHeight = 0; + this->textWidth = 0; for (auto& text : lines) { int w = textwidth(LPCTSTR(text.c_str())); @@ -558,13 +552,27 @@ void Dialog::getTextSize() if (this->textWidth < w) this->textWidth = w; } - + restoreStyle(); } + +void Dialog::invalidateLayout(bool clearChildren) +{ + if (clearChildren) + clearControls(); + + this->textWidth = 0; + this->textHeight = 0; + this->buttonNum = 0; + this->needsInitialization = true; + this->dirty = true; +} + // 计算逻辑:对话框宽度取【文本区域最大宽度】和【按钮区域总宽度】中的较大值。 // 对话框高度 = 标题栏 + 文本区 + 按钮区 + 各种间距。 void Dialog::initDialogSize() { + this->textStyle.nHeight = 20; splitMessageLines(); // 分割消息行 getTextSize(); // 获取文本最大尺寸 @@ -591,9 +599,17 @@ void Dialog::initDialogSize() // 计算文本区域宽度(包括边距) int textAreaWidth = textWidth + textToBorderMargin * 2; + saveStyle(); + settextstyle(textStyle.nHeight, textStyle.nWidth, textStyle.lpszFace, + textStyle.nEscapement, textStyle.nOrientation, textStyle.nWeight, + textStyle.bItalic, textStyle.bUnderline, textStyle.bStrikeOut); + int titleAreaWidth = textwidth(LPCTSTR(titleText.c_str())) + textToBorderMargin * 2 + closeButtonWidth + buttonMargin; + restoreStyle(); - // 对话框宽度取两者中的较大值,并确保最小宽度 + // 对话框宽度取文本、标题和按钮区域中的较大值,并确保最小宽度 this->width = buttonAreaWidth > textAreaWidth ? buttonAreaWidth : textAreaWidth; + if (titleAreaWidth > this->width) + this->width = titleAreaWidth; this->width = this->width > 200 ? this->width : 200; // 计算对话框高度 @@ -608,9 +624,6 @@ void Dialog::initDialogSize() this->x = (hWnd.getWidth() - this->width) / 2; this->y = (hWnd.getHeight() - this->height) / 2; - //this->textStyle.nWidth = 10; - this->textStyle.nHeight = 20; - initButtons(); // 初始化按钮 initTitle(); // 初始化标题标签 initCloseButton(); // 初始化关闭按钮 diff --git a/Dialog.h b/Dialog.h index 4f83fdc..d285fb4 100644 --- a/Dialog.h +++ b/Dialog.h @@ -117,6 +117,8 @@ private: void splitMessageLines(); // 获取文本大小 void getTextSize(); + // 标记需要重新布局并按需清空旧控件 + void invalidateLayout(bool clearChildren); //初始化对话框尺寸 void initDialogSize(); void addControl(std::unique_ptr control); diff --git a/MessageBox.cpp b/MessageBox.cpp index e611872..7cf602e 100644 --- a/MessageBox.cpp +++ b/MessageBox.cpp @@ -9,7 +9,6 @@ namespace StellarX SX_LOGI("MessageBox") << "show: Message=" << dlg.GetText() << " modal=" << (dlg.model() ? 1 : 0); - dlg.setInitialization(true); dlg.Show(); return dlg.GetResult(); } @@ -28,7 +27,6 @@ namespace StellarX SX_LOGI("MessageBox") << "show: Message=" << dlg->GetText() << " modal=" << (dlg->model() ? 1 : 0); Dialog* dlgPtr = dlg.get(); - dlgPtr->setInitialization(true); // 设置回调 if (onResult) dlgPtr->SetResultCallback(std::move(onResult)); @@ -36,4 +34,4 @@ namespace StellarX wnd.addDialog(std::move(dlg)); dlgPtr->Show(); } -} \ No newline at end of file +} diff --git a/Table.cpp b/Table.cpp index fa28256..7d81a2b 100644 --- a/Table.cpp +++ b/Table.cpp @@ -1,5 +1,31 @@ #include "Table.h" #include "SxLog.h" + +namespace +{ + std::vector NormalizeTableRow(std::vector row, size_t headerCount) + { + if (headerCount == 0) + return row; + + if (row.size() > headerCount) + row.resize(headerCount); + else if (row.size() < headerCount) + row.resize(headerCount, ""); + + return row; + } + + int CalculateTotalPages(size_t rowCount, int rowsPerPage) + { + if (rowsPerPage < 1) + rowsPerPage = 1; + + const int total = static_cast((rowCount + static_cast(rowsPerPage) - 1) / static_cast(rowsPerPage)); + return total > 0 ? total : 1; + } +} + // 绘制表格的当前页 // 使用双循环绘制行和列,考虑分页偏移 void Table::drawTable() @@ -449,25 +475,37 @@ void Table::setHeaders(std::initializer_list headers) this->headers.clear(); for (auto& lis : headers) this->headers.push_back(lis); + + if (!this->headers.empty()) + { + for (auto& row : this->data) + row = NormalizeTableRow(std::move(row), this->headers.size()); + } + + totalPages = CalculateTotalPages(this->data.size(), rowsPerPage); + if (currentPage > totalPages) + currentPage = totalPages; + SX_LOGI("Table") << SX_T("设置表头:id=","setHeaders: id=") << id << SX_T("总数="," count=") << (int)this->headers.size(); isNeedCellSize = true; // 标记需要重新计算单元格尺寸 isNeedDrawHeaders = true; // 标记需要重新绘制表头 + isNeedButtonAndPageNum = true; dirty = true; } void Table::setData(std::vector data) { - while (data.size() < headers.size()) - data.push_back(""); + data = NormalizeTableRow(std::move(data), headers.size()); this->data.push_back(data); - totalPages = ((int)this->data.size() + rowsPerPage - 1) / rowsPerPage; - if (totalPages < 1) - totalPages = 1; + totalPages = CalculateTotalPages(this->data.size(), rowsPerPage); + if (currentPage > totalPages) + currentPage = totalPages; isNeedCellSize = true; + isNeedButtonAndPageNum = true; dirty = true; SX_LOGI("Table") @@ -480,24 +518,22 @@ void Table::setData(std::vector data) void Table::setData(std::initializer_list> data) { - for (auto lis : data) - if (lis.size() < headers.size()) - { - for (size_t i = lis.size(); i < headers.size(); i++) - lis.push_back(""); - this->data.push_back(lis); - } - else - this->data.push_back(lis); + int addedRows = 0; + for (auto row : data) + { + this->data.push_back(NormalizeTableRow(std::move(row), headers.size())); + ++addedRows; + } - totalPages = ((int)this->data.size() + rowsPerPage - 1) / rowsPerPage; - if (totalPages < 1) - totalPages = 1; + totalPages = CalculateTotalPages(this->data.size(), rowsPerPage); + if (currentPage > totalPages) + currentPage = totalPages; isNeedCellSize = true; // 标记需要重新计算单元格尺寸 + isNeedButtonAndPageNum = true; dirty = true; SX_LOGI("Table") - << SX_T("新增Data:id=", "appendRow: id=") << id - << SX_T(" 本行列数=", " cols=") << (int)data.size() + << SX_T("新增多行Data:id=", "appendRows: id=") << id + << SX_T(" 新增行数=", " addedRows=") << addedRows << SX_T(" 数据总行数=", " totalRows=") << (int)this->data.size() << SX_T(" 总页数=", " totalPages=") << totalPages; @@ -509,10 +545,11 @@ void Table::setRowsPerPage(int rows) this->rowsPerPage = rows; if (this->rowsPerPage < 1) this->rowsPerPage = 1; - totalPages = ((int)data.size() + rowsPerPage - 1) / rowsPerPage; - if (totalPages < 1) - totalPages = 1; + totalPages = CalculateTotalPages(data.size(), rowsPerPage); + if (currentPage > totalPages) + currentPage = totalPages; isNeedCellSize = true; // 标记需要重新计算单元格尺寸 + isNeedButtonAndPageNum = true; dirty = true; } @@ -581,7 +618,7 @@ void Table::clearData() { this->data.clear(); this->currentPage = 1; - this->totalPages = 1; + this->totalPages = CalculateTotalPages(this->data.size(), rowsPerPage); isNeedCellSize = true; // 标记需要重新计算单元格尺寸 isNeedButtonAndPageNum = true;// 标记需要重新计算翻页按钮和页码信息 dirty = true; diff --git a/Window.cpp b/Window.cpp index f3f9e7a..aaa9ee1 100644 --- a/Window.cpp +++ b/Window.cpp @@ -698,14 +698,21 @@ HWND Window::getHwnd() const int Window::getWidth() const { - // 注意:这里返回 pendingW - // 表示“最近一次收到的尺寸”(可能尚未应用到画布,最终以收口时的 width 为准) - return pendingW; + return width; } int Window::getHeight() const { - // 同上,返回 pendingH(与 getWidth 对应) + return height; +} + +int Window::getPendingWidth() const +{ + return pendingW; +} + +int Window::getPendingHeight() const +{ return pendingH; } diff --git a/Window.h b/Window.h index 5d82755..889a266 100644 --- a/Window.h +++ b/Window.h @@ -84,6 +84,8 @@ public: HWND getHwnd() const; int getWidth() const; int getHeight() const; + int getPendingWidth() const; + int getPendingHeight() const; std::string getHeadline() const; COLORREF getBkcolor() const; IMAGE* getBkImage() const;