diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/any_map.cpp | 2 | ||||
-rw-r--r-- | src/any_map.hpp (renamed from src/any_map.h) | 0 | ||||
-rw-r--r-- | src/application.cpp | 5 | ||||
-rw-r--r-- | src/application.hpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 43 | ||||
-rw-r--r-- | src/ui/control.hpp | 2 | ||||
-rw-r--r-- | src/ui/window.cpp | 54 | ||||
-rw-r--r-- | src/ui/window.hpp | 28 |
8 files changed, 118 insertions, 18 deletions
diff --git a/src/any_map.cpp b/src/any_map.cpp index 6f9ada66..de13f85e 100644 --- a/src/any_map.cpp +++ b/src/any_map.cpp @@ -1,4 +1,4 @@ -#include "any_map.h" +#include "any_map.hpp" namespace cru { diff --git a/src/any_map.h b/src/any_map.hpp index ea6044b1..ea6044b1 100644 --- a/src/any_map.h +++ b/src/any_map.hpp diff --git a/src/application.cpp b/src/application.cpp index 9a98854c..fa71c37e 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -4,7 +4,6 @@ #include "timer.hpp" #include "ui/window.hpp" #include "ui/cursor.hpp" -#include "ui/ui_manager.hpp" namespace cru { constexpr auto god_window_class_name = L"GodWindowClass"; @@ -27,7 +26,7 @@ namespace cru { return DefWindowProc(hWnd, uMsg, wParam, lParam); } - GodWindow::GodWindow(Application* application) : application_(application) + GodWindow::GodWindow(Application* application) { const auto h_instance = application->GetInstanceHandle(); @@ -37,7 +36,7 @@ namespace cru { god_window_class_name, L"", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - nullptr, nullptr, h_instance, nullptr + HWND_MESSAGE, nullptr, h_instance, nullptr ); if (hwnd_ == nullptr) diff --git a/src/application.hpp b/src/application.hpp index 90a43848..b9427826 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -8,7 +8,6 @@ #include <type_traits> #include "base.hpp" -#include "any_map.h" #ifdef CRU_DEBUG #include <unordered_set> @@ -42,7 +41,6 @@ namespace cru std::optional<LRESULT> HandleGodWindowMessage(HWND hwnd, int msg, WPARAM w_param, LPARAM l_param); private: - Application* application_; std::unique_ptr<ui::WindowClass> god_window_class_; HWND hwnd_; }; diff --git a/src/main.cpp b/src/main.cpp index 264b3c7c..f9bc975c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include "ui/controls/button.hpp" #include "ui/controls/text_box.hpp" +using cru::ui::Rect; using cru::String; using cru::Application; using cru::ui::Window; @@ -28,7 +29,7 @@ int APIENTRY wWinMain( Application application(hInstance); - Window window; + const auto window = Window::CreateOverlapped(); /* window.native_message_event.AddHandler([](cru::ui::events::WindowNativeMessageEventArgs& args) { @@ -86,7 +87,6 @@ int APIENTRY wWinMain( //test 2 - const auto layout = CreateWithLayout<LinearLayout>(LayoutSideParams::Exactly(500), LayoutSideParams::Content()); layout->mouse_click_event.AddHandler([layout](cru::ui::events::MouseButtonEventArgs& args) @@ -104,7 +104,7 @@ int APIENTRY wWinMain( #ifdef CRU_DEBUG_LAYOUT toggle_button->toggle_event.AddHandler([&window](cru::ui::events::ToggleEventArgs& args) { - window.SetDebugLayout(args.GetNewState()); + window->SetDebugLayout(args.GetNewState()); }); #endif inner_layout->AddChild(toggle_button); @@ -114,7 +114,37 @@ int APIENTRY wWinMain( { const auto button = Button::Create(); button->GetLayoutParams()->padding = Thickness(20, 5); - button->AddChild(TextBlock::Create(L"button")); + button->AddChild(TextBlock::Create(L"Show popup window parenting this.")); + button->mouse_click_event.AddHandler([window](auto) + { + Window::CreatePopup(window)->Show(); + }); + layout->AddChild(button); + } + + { + const auto button = Button::Create(); + button->GetLayoutParams()->padding = Thickness(20, 5); + button->AddChild(TextBlock::Create(L"Show popup window parenting null.")); + button->mouse_click_event.AddHandler([](auto) + { + auto popup = Window::CreatePopup(nullptr); + popup->SetWindowRect(Rect(100, 100, 300, 300)); + popup->Show(); + }); + layout->AddChild(button); + } + + { + const auto button = Button::Create(); + button->GetLayoutParams()->padding = Thickness(20, 5); + button->AddChild(TextBlock::Create(L"Show popup window with caption.")); + button->mouse_click_event.AddHandler([](auto) + { + auto popup = Window::CreatePopup(nullptr, true); + popup->SetWindowRect(Rect(100, 100, 300, 300)); + popup->Show(); + }); layout->AddChild(button); } @@ -146,7 +176,7 @@ int APIENTRY wWinMain( layout->AddChild(CreateWithLayout<TextBlock>(LayoutSideParams::Content(Alignment::End), LayoutSideParams::Stretch(), L"By crupest!!!")); - window.AddChild(layout); + window->AddChild(layout); /* window.AddChild( @@ -170,7 +200,8 @@ int APIENTRY wWinMain( window.AddChild(linear_layout); */ - window.Show(); + + window->Show(); return application.Run(); } diff --git a/src/ui/control.hpp b/src/ui/control.hpp index 0e078da2..8ac9ae72 100644 --- a/src/ui/control.hpp +++ b/src/ui/control.hpp @@ -11,7 +11,7 @@ #include "events/ui_event.hpp" #include "border_property.hpp" #include "cursor.hpp" -#include "any_map.h" +#include "any_map.hpp" namespace cru::ui { diff --git a/src/ui/window.cpp b/src/ui/window.cpp index 349b78ff..2737b70b 100644 --- a/src/ui/window.cpp +++ b/src/ui/window.cpp @@ -113,8 +113,19 @@ namespace cru::ui } } - Window::Window() : Control(WindowConstructorTag{}, this), control_list_({ this }) { + 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(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, @@ -125,6 +136,34 @@ namespace cru::ui 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"", 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 + ); + + 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_); @@ -133,7 +172,11 @@ namespace cru::ui } Window::~Window() { - Close(); + if (IsWindowValid()) + { + SetDeleteThisOnDestroy(false); // avoid double delete. + Close(); + } TraverseDescendants([this](Control* control) { control->OnDetachToWindow(this); }); @@ -144,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_); @@ -521,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 2609594d..963bff78 100644 --- a/src/ui/window.hpp +++ b/src/ui/window.hpp @@ -83,13 +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(); + 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; @@ -99,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. @@ -116,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(); @@ -285,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_{}; @@ -302,4 +325,3 @@ namespace cru::ui #endif }; } - |