feat: add a new awesome feature

This commit is contained in:
Ysm-04
2025-09-22 15:08:49 +08:00
parent bd4588731b
commit 9f2b175b17
25 changed files with 1962 additions and 616 deletions
+132 -9
View File
@@ -1,4 +1,5 @@
#include "StellarX/Window.h"
#include "Window.h"
#include"Dialog.h"
Window::Window(int width, int height, int mode)
{
@@ -59,24 +60,93 @@ void Window::draw(std::string pImgFile)
BeginBatchDraw(); // 开始批量绘制
for (auto& control : controls)
control->draw();
for(auto& d: dialogs)
d->draw();
EndBatchDraw(); // 结束批量绘制
}
// 运行主事件循环,处理用户输入和窗口消息
// 此方法会阻塞直到窗口关闭
// 主消息循环优先级:对话框 > 普通控件。
// 重绘策略:为保证视觉一致性,每次有对话框状态变化(打开/关闭)时,
// 会强制重绘所有控件。先绘制普通控件,再绘制对话框(确保对话框在最上层)。
void Window::runEventLoop()
{
ExMessage msg;
bool running = true;
while (running) {
msg = getmessage(EX_MOUSE | EX_KEY);
if (msg.message == WM_CLOSE) {
running = false;
continue;
while (running)
{
bool consume = false;// 是否处理了消息
// 处理所有消息
if (peekmessage(&msg, EX_MOUSE | EX_KEY | EX_WINDOW, true))
{
if (msg.message == WM_CLOSE)
{
running = false;
break;
}
// 优先处理对话框事件
for (auto& d : dialogs)
{
if (d->IsVisible() && !d->model())
consume = d->handleEvent(msg);
if (consume)
break;
}
if(!consume)
for (auto& c : controls)
{
consume = c->handleEvent(msg);
if (consume)
break;
}
}
for (auto& c : controls)
c->handleEvent(msg);
flushmessage(EX_MOUSE |EX_KEY |EX_CHAR|EX_WINDOW);
//如果有对话框打开或者关闭强制重绘
bool needredraw = false;
for (auto& d : dialogs)
{
needredraw = d->IsVisible();
if (needredraw)break;
}
if (needredraw || dialogClose)
{
// 对话框关闭后,需要手动合成一个鼠标移动消息并分发给所有普通控件,
// 以便它们能及时更新悬停状态(hover),否则悬停状态可能保持错误状态。
// 先把当前鼠标位置转换为客户区坐标,并合成一次 WM_MOUSEMOVE,先分发给控件更新 hover 状态
POINT pt;
if (GetCursorPos(&pt))
{
ScreenToClient(this->hWnd, &pt);
ExMessage mm;
mm.message = WM_MOUSEMOVE;
mm.x =(short) pt.x;
mm.y =(short) pt.y;
// 只分发给 window 层控件(因为 dialog 已经关闭或即将关闭)
for (auto& c : controls)
c->handleEvent(mm);
}
BeginBatchDraw();
// 先绘制普通控件
for (auto& c : controls)
c->draw();
// 然后绘制对话框(确保对话框在最上层)
for (auto& d : dialogs)
{
if (!d->model() && d->IsVisible())
d->setDirty(true);
d->draw();
}
EndBatchDraw();
needredraw = false;
}
// 避免CPU占用过高
Sleep(10);
}
}
@@ -108,6 +178,59 @@ void Window::addControl(std::unique_ptr<Control> control)
this->controls.push_back(std::move(control));
}
void Window::addDialog(std::unique_ptr<Control> dialogs)
{
this->dialogs.push_back(std::move(dialogs));
}
bool Window::hasNonModalDialogWithCaption(const std::string& caption) const {
for (const auto& dptr : dialogs) {
if (!dptr) continue;
// 只检查 Dialog 类型的控件
Dialog* d = dynamic_cast<Dialog*>(dptr.get());
//检查是否有非模态对话框可见,并且消息内容一致
if (d && d->IsVisible() && !d->model() && d->GetCaption() == caption)
return true;
}
return false;
}
HWND Window::getHwnd() const
{
return hWnd;
}
int Window::getWidth() const
{
return this->width;
}
int Window::getHeight() const
{
return this->height;
}
std::string Window::getHeadline() const
{
return this->headline;
}
COLORREF Window::getBkcolor() const
{
return this->wBkcolor;
}
IMAGE* Window::getBkImage() const
{
return this->background;
}
std::vector<std::unique_ptr<Control>>& Window::getControls()
{
return this->controls;
}