diff options
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/window.cpp | 48 | ||||
-rw-r--r-- | src/ui/window.hpp | 28 |
2 files changed, 69 insertions, 7 deletions
diff --git a/src/ui/window.cpp b/src/ui/window.cpp index f7506f18..2737b70b 100644 --- a/src/ui/window.cpp +++ b/src/ui/window.cpp @@ -113,20 +113,44 @@ namespace cru::ui } } - Window::Window() : Window(nullptr) + Window* Window::CreateOverlapped() { + return new Window(tag_overlapped_constructor{}); + } + Window* Window::CreatePopup(Window* parent, const bool caption) + { + return new Window(tag_popup_constructor{}, parent, caption); } - Window::Window(Window* parent) : Control(WindowConstructorTag{}, this), control_list_({ this }) { + Window::Window(tag_overlapped_constructor) : Control(WindowConstructorTag{}, this), control_list_({ this }) { + const auto window_manager = WindowManager::GetInstance(); + + hwnd_ = CreateWindowEx(0, + window_manager->GetGeneralWindowClass()->GetName(), + L"", WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + nullptr, nullptr, Application::GetInstance()->GetInstanceHandle(), nullptr + ); + + if (hwnd_ == nullptr) + throw std::runtime_error("Failed to create window."); + + AfterCreateHwnd(window_manager); + } + Window::Window(tag_popup_constructor, Window* parent, const bool caption) : Control(WindowConstructorTag{}, this), control_list_({ this }) + { if (parent != nullptr && !parent->IsWindowValid()) throw std::runtime_error("Parent window is not valid."); + parent_window_ = parent; + const auto window_manager = WindowManager::GetInstance(); + hwnd_ = CreateWindowEx(0, window_manager->GetGeneralWindowClass()->GetName(), - L"", WS_OVERLAPPEDWINDOW, + L"", caption ? (WS_POPUPWINDOW | WS_CAPTION) : WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, parent == nullptr ? nullptr : parent->GetWindowHandle(), nullptr, Application::GetInstance()->GetInstanceHandle(), nullptr @@ -135,6 +159,11 @@ namespace cru::ui if (hwnd_ == nullptr) throw std::runtime_error("Failed to create window."); + AfterCreateHwnd(window_manager); + } + + void Window::AfterCreateHwnd(WindowManager* window_manager) + { window_manager->RegisterWindow(hwnd_, this); render_target_ = graph::GraphManager::GetInstance()->CreateWindowRenderTarget(hwnd_); @@ -143,7 +172,11 @@ namespace cru::ui } Window::~Window() { - Close(); + if (IsWindowValid()) + { + SetDeleteThisOnDestroy(false); // avoid double delete. + Close(); + } TraverseDescendants([this](Control* control) { control->OnDetachToWindow(this); }); @@ -154,6 +187,11 @@ namespace cru::ui return control_type; } + void Window::SetDeleteThisOnDestroy(bool value) + { + delete_this_on_destroy_ = value; + } + void Window::Close() { if (IsWindowValid()) DestroyWindow(hwnd_); @@ -531,6 +569,8 @@ namespace cru::ui void Window::OnDestroyInternal() { WindowManager::GetInstance()->UnregisterWindow(hwnd_); hwnd_ = nullptr; + if (delete_this_on_destroy_) + delete this; } void Window::OnPaintInternal() { diff --git a/src/ui/window.hpp b/src/ui/window.hpp index 82cbfc4f..963bff78 100644 --- a/src/ui/window.hpp +++ b/src/ui/window.hpp @@ -83,14 +83,26 @@ namespace cru::ui - class Window : public Control + class Window final : public Control { friend class WindowManager; public: static constexpr auto control_type = L"Window"; - Window(); - explicit Window(Window* parent); + public: + static Window* CreateOverlapped(); + static Window* CreatePopup(Window* parent, bool caption = false); + + private: + struct tag_overlapped_constructor {}; + struct tag_popup_constructor {}; + + explicit Window(tag_overlapped_constructor); + Window(tag_popup_constructor, Window* parent, bool caption); + + void AfterCreateHwnd(WindowManager* window_manager); + + public: Window(const Window& other) = delete; Window(Window&& other) = delete; Window& operator=(const Window& other) = delete; @@ -100,6 +112,8 @@ namespace cru::ui public: StringView GetControlType() const override final; + void SetDeleteThisOnDestroy(bool value); + //*************** region: handle *************** //Get the handle of the window. Return null if window is invalid. @@ -117,6 +131,11 @@ namespace cru::ui //*************** region: window operations *************** + Window* GetParentWindow() const + { + return parent_window_; + } + //Close and destroy the window if the window is valid. void Close(); @@ -286,7 +305,10 @@ namespace cru::ui void DispatchMouseHoverControlChangeEvent(Control* old_control, Control * new_control, const Point& point); private: + bool delete_this_on_destroy_ = true; + HWND hwnd_ = nullptr; + Window* parent_window_ = nullptr; std::shared_ptr<graph::WindowRenderTarget> render_target_{}; std::list<Control*> control_list_{}; |