aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/any_map.cpp2
-rw-r--r--src/any_map.hpp (renamed from src/any_map.h)0
-rw-r--r--src/application.cpp5
-rw-r--r--src/application.hpp2
-rw-r--r--src/main.cpp43
-rw-r--r--src/ui/control.hpp2
-rw-r--r--src/ui/window.cpp54
-rw-r--r--src/ui/window.hpp28
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
};
}
-