aboutsummaryrefslogtreecommitdiff
path: root/include/cru/platform/gui/win
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-05-15 13:56:40 +0800
committercrupest <crupest@outlook.com>2022-05-15 13:56:40 +0800
commit9e0c9d3499bc50c3534b4dc500d8b5d0b5f22752 (patch)
tree7342f6991771fa31b16fd6a5ed892ff6025f3d05 /include/cru/platform/gui/win
parent41de54bad2c0f857821fcc83f41af3334d068b6d (diff)
downloadcru-9e0c9d3499bc50c3534b4dc500d8b5d0b5f22752.tar.gz
cru-9e0c9d3499bc50c3534b4dc500d8b5d0b5f22752.tar.bz2
cru-9e0c9d3499bc50c3534b4dc500d8b5d0b5f22752.zip
...
Diffstat (limited to 'include/cru/platform/gui/win')
-rw-r--r--include/cru/platform/gui/win/Base.h27
-rw-r--r--include/cru/platform/gui/win/Clipboard.h25
-rw-r--r--include/cru/platform/gui/win/Cursor.h51
-rw-r--r--include/cru/platform/gui/win/Exception.h7
-rw-r--r--include/cru/platform/gui/win/GodWindow.h39
-rw-r--r--include/cru/platform/gui/win/InputMethod.h88
-rw-r--r--include/cru/platform/gui/win/Keyboard.h9
-rw-r--r--include/cru/platform/gui/win/Resource.h24
-rw-r--r--include/cru/platform/gui/win/UiApplication.h87
-rw-r--r--include/cru/platform/gui/win/Window.h217
-rw-r--r--include/cru/platform/gui/win/WindowClass.h24
-rw-r--r--include/cru/platform/gui/win/WindowNativeMessageEventArgs.h40
12 files changed, 638 insertions, 0 deletions
diff --git a/include/cru/platform/gui/win/Base.h b/include/cru/platform/gui/win/Base.h
new file mode 100644
index 00000000..78068827
--- /dev/null
+++ b/include/cru/platform/gui/win/Base.h
@@ -0,0 +1,27 @@
+#pragma once
+#include "cru/platform/win/WinPreConfig.h"
+
+#include "cru/common/Base.h"
+
+#ifdef CRU_PLATFORM_WINDOWS
+#ifdef CRU_WIN_GUI_EXPORT_API
+#define CRU_WIN_GUI_API __declspec(dllexport)
+#else
+#define CRU_WIN_GUI_API __declspec(dllimport)
+#endif
+#else
+#define CRU_WIN_GUI_API
+#endif
+
+namespace cru::platform::gui::win {
+class GodWindow;
+class TimerManager;
+class WinCursor;
+class WinCursorManager;
+class WindowClass;
+class WindowManager;
+class WinNativeWindow;
+class WinUiApplication;
+class WinInputMethodContext;
+class WinClipboard;
+} // namespace cru::platform::gui::win
diff --git a/include/cru/platform/gui/win/Clipboard.h b/include/cru/platform/gui/win/Clipboard.h
new file mode 100644
index 00000000..dc4bc9b5
--- /dev/null
+++ b/include/cru/platform/gui/win/Clipboard.h
@@ -0,0 +1,25 @@
+#pragma once
+#include "Resource.h"
+#include "cru/common/Base.h"
+#include "cru/platform/gui/Clipboard.h"
+#include "cru/platform/gui/win/Base.h"
+
+namespace cru::platform::gui::win {
+class WinClipboard : public WinNativeResource, public virtual IClipboard {
+ CRU_DEFINE_CLASS_LOG_TAG(u"WinClipboard")
+ public:
+ explicit WinClipboard(WinUiApplication* application);
+
+ CRU_DELETE_COPY(WinClipboard)
+ CRU_DELETE_MOVE(WinClipboard)
+
+ ~WinClipboard() override;
+
+ public:
+ String GetText() override;
+ void SetText(String text) override;
+
+ private:
+ WinUiApplication* application_;
+};
+} // namespace cru::platform::gui::win
diff --git a/include/cru/platform/gui/win/Cursor.h b/include/cru/platform/gui/win/Cursor.h
new file mode 100644
index 00000000..f9cb0a09
--- /dev/null
+++ b/include/cru/platform/gui/win/Cursor.h
@@ -0,0 +1,51 @@
+#pragma once
+#include "Resource.h"
+
+#include "cru/platform/gui/Cursor.h"
+
+#include <memory>
+
+namespace cru::platform::gui::win {
+class CRU_WIN_GUI_API WinCursor : public WinNativeResource,
+ public virtual ICursor {
+ CRU_DEFINE_CLASS_LOG_TAG(u"WinCursor")
+
+ public:
+ WinCursor(HCURSOR handle, bool auto_destroy);
+
+ CRU_DELETE_COPY(WinCursor)
+ CRU_DELETE_MOVE(WinCursor)
+
+ ~WinCursor() override;
+
+ public:
+ HCURSOR GetHandle() const { return handle_; }
+
+ private:
+ HCURSOR handle_;
+ bool auto_destroy_;
+};
+
+class WinCursorManager : public WinNativeResource,
+ public virtual ICursorManager {
+ public:
+ WinCursorManager();
+
+ CRU_DELETE_COPY(WinCursorManager)
+ CRU_DELETE_MOVE(WinCursorManager)
+
+ ~WinCursorManager() override = default;
+
+ public:
+ std::shared_ptr<WinCursor> GetSystemWinCursor(SystemCursorType type);
+
+ std::shared_ptr<ICursor> GetSystemCursor(SystemCursorType type) override {
+ return std::static_pointer_cast<ICursor>(GetSystemWinCursor(type));
+ }
+
+ private:
+ std::shared_ptr<WinCursor> sys_arrow_;
+ std::shared_ptr<WinCursor> sys_hand_;
+ std::shared_ptr<WinCursor> sys_ibeam_;
+};
+} // namespace cru::platform::gui::win
diff --git a/include/cru/platform/gui/win/Exception.h b/include/cru/platform/gui/win/Exception.h
new file mode 100644
index 00000000..a0689075
--- /dev/null
+++ b/include/cru/platform/gui/win/Exception.h
@@ -0,0 +1,7 @@
+#pragma once
+#include "cru/platform/win/Exception.h"
+
+namespace cru::platform::gui::win {
+using platform::win::HResultError;
+using platform::win::Win32Error;
+} // namespace cru::platform::gui::win
diff --git a/include/cru/platform/gui/win/GodWindow.h b/include/cru/platform/gui/win/GodWindow.h
new file mode 100644
index 00000000..fe61c80d
--- /dev/null
+++ b/include/cru/platform/gui/win/GodWindow.h
@@ -0,0 +1,39 @@
+#pragma once
+#include "Base.h"
+
+#include "WindowNativeMessageEventArgs.h"
+#include "cru/common/Event.h"
+#include "cru/common/String.h"
+
+#include <memory>
+
+namespace cru::platform::gui::win {
+class CRU_WIN_GUI_API GodWindow : public Object {
+ CRU_DEFINE_CLASS_LOG_TAG(u"GodWindow")
+
+ public:
+ explicit GodWindow(WinUiApplication* application);
+
+ CRU_DELETE_COPY(GodWindow)
+ CRU_DELETE_MOVE(GodWindow)
+
+ ~GodWindow() override;
+
+ HWND GetHandle() const { return hwnd_; }
+
+ bool HandleGodWindowMessage(HWND hwnd, UINT msg, WPARAM w_param,
+ LPARAM l_param, LRESULT* result);
+
+ IEvent<WindowNativeMessageEventArgs&>* MessageEvent() {
+ return &message_event_;
+ }
+
+ private:
+ WinUiApplication* application_;
+
+ std::unique_ptr<WindowClass> god_window_class_;
+ HWND hwnd_;
+
+ Event<WindowNativeMessageEventArgs&> message_event_;
+};
+} // namespace cru::platform::gui::win
diff --git a/include/cru/platform/gui/win/InputMethod.h b/include/cru/platform/gui/win/InputMethod.h
new file mode 100644
index 00000000..8e28f857
--- /dev/null
+++ b/include/cru/platform/gui/win/InputMethod.h
@@ -0,0 +1,88 @@
+// Some useful information can be found from chromium code:
+// https://chromium.googlesource.com/chromium/chromium/+/refs/heads/master/ui/base/win/ime_input.h
+// https://chromium.googlesource.com/chromium/chromium/+/refs/heads/master/ui/base/win/ime_input.cc
+
+#pragma once
+#include "Resource.h"
+
+#include "WindowNativeMessageEventArgs.h"
+#include "cru/platform/gui/InputMethod.h"
+
+#include <imm.h>
+
+namespace cru::platform::gui::win {
+class CRU_WIN_GUI_API AutoHIMC : public Object {
+ CRU_DEFINE_CLASS_LOG_TAG(u"AutoHIMC")
+
+ public:
+ explicit AutoHIMC(HWND hwnd);
+
+ CRU_DELETE_COPY(AutoHIMC)
+
+ AutoHIMC(AutoHIMC&& other);
+ AutoHIMC& operator=(AutoHIMC&& other);
+
+ ~AutoHIMC() override;
+
+ HWND GetHwnd() const { return hwnd_; }
+
+ HIMC Get() const { return handle_; }
+
+ private:
+ HWND hwnd_;
+ HIMC handle_;
+};
+
+class CRU_WIN_GUI_API WinInputMethodContext
+ : public WinNativeResource,
+ public virtual IInputMethodContext {
+ CRU_DEFINE_CLASS_LOG_TAG(u"WinInputMethodContext")
+
+ public:
+ WinInputMethodContext(gsl::not_null<WinNativeWindow*> window);
+
+ CRU_DELETE_COPY(WinInputMethodContext)
+ CRU_DELETE_MOVE(WinInputMethodContext)
+
+ ~WinInputMethodContext() override;
+
+ bool ShouldManuallyDrawCompositionText() override { return true; }
+
+ void EnableIME() override;
+
+ void DisableIME() override;
+
+ void CompleteComposition() override;
+
+ void CancelComposition() override;
+
+ CompositionText GetCompositionText() override;
+
+ void SetCandidateWindowPosition(const Point& point) override;
+
+ IEvent<std::nullptr_t>* CompositionStartEvent() override;
+
+ IEvent<std::nullptr_t>* CompositionEndEvent() override;
+
+ IEvent<std::nullptr_t>* CompositionEvent() override;
+
+ IEvent<StringView>* TextEvent() override;
+
+ private:
+ void OnWindowNativeMessage(WindowNativeMessageEventArgs& args);
+
+ String GetResultString();
+
+ AutoHIMC GetHIMC();
+
+ private:
+ WinNativeWindow* native_window_;
+
+ EventRevokerListGuard event_guard_;
+
+ Event<std::nullptr_t> composition_start_event_;
+ Event<std::nullptr_t> composition_end_event_;
+ Event<std::nullptr_t> composition_event_;
+ Event<StringView> text_event_;
+};
+} // namespace cru::platform::gui::win
diff --git a/include/cru/platform/gui/win/Keyboard.h b/include/cru/platform/gui/win/Keyboard.h
new file mode 100644
index 00000000..18b37b60
--- /dev/null
+++ b/include/cru/platform/gui/win/Keyboard.h
@@ -0,0 +1,9 @@
+#pragma once
+#include "Base.h"
+
+#include "cru/platform/gui/Keyboard.h"
+
+namespace cru::platform::gui::win {
+KeyCode CRU_WIN_GUI_API VirtualKeyToKeyCode(int virtual_key);
+KeyModifier CRU_WIN_GUI_API RetrieveKeyMofifier();
+} // namespace cru::platform::gui::win
diff --git a/include/cru/platform/gui/win/Resource.h b/include/cru/platform/gui/win/Resource.h
new file mode 100644
index 00000000..ed43bec3
--- /dev/null
+++ b/include/cru/platform/gui/win/Resource.h
@@ -0,0 +1,24 @@
+#pragma once
+#include "Base.h"
+
+#include "cru/platform/Resource.h"
+
+namespace cru::platform::gui::win {
+class CRU_WIN_GUI_API WinNativeResource : public Object,
+ public virtual IPlatformResource {
+ public:
+ static String kPlatformId;
+
+ protected:
+ WinNativeResource() = default;
+
+ public:
+ CRU_DELETE_COPY(WinNativeResource)
+ CRU_DELETE_MOVE(WinNativeResource)
+
+ ~WinNativeResource() override = default;
+
+ public:
+ String GetPlatformId() const final { return kPlatformId; }
+};
+} // namespace cru::platform::gui::win
diff --git a/include/cru/platform/gui/win/UiApplication.h b/include/cru/platform/gui/win/UiApplication.h
new file mode 100644
index 00000000..5abe7356
--- /dev/null
+++ b/include/cru/platform/gui/win/UiApplication.h
@@ -0,0 +1,87 @@
+#pragma once
+#include "Resource.h"
+
+#include "cru/platform/gui/Base.h"
+#include "cru/platform/gui/UiApplication.h"
+
+#include <memory>
+
+namespace cru::platform::graphics::direct2d {
+class DirectGraphicsFactory;
+}
+
+namespace cru::platform::gui::win {
+class CRU_WIN_GUI_API WinUiApplication : public WinNativeResource,
+ public virtual IUiApplication {
+ public:
+ static WinUiApplication* GetInstance() { return instance; }
+
+ private:
+ static WinUiApplication* instance;
+
+ public:
+ WinUiApplication();
+
+ CRU_DELETE_COPY(WinUiApplication)
+ CRU_DELETE_MOVE(WinUiApplication)
+
+ ~WinUiApplication() override;
+
+ public:
+ int Run() override;
+ void RequestQuit(int quit_code) override;
+
+ void AddOnQuitHandler(std::function<void()> handler) override;
+
+ bool IsQuitOnAllWindowClosed() override {
+ return is_quit_on_all_window_closed_;
+ }
+ void SetQuitOnAllWindowClosed(bool quit_on_all_window_closed) override {
+ is_quit_on_all_window_closed_ = quit_on_all_window_closed;
+ }
+
+ long long SetImmediate(std::function<void()> action) override;
+ long long SetTimeout(std::chrono::milliseconds milliseconds,
+ std::function<void()> action) override;
+ long long SetInterval(std::chrono::milliseconds milliseconds,
+ std::function<void()> action) override;
+ void CancelTimer(long long id) override;
+
+ std::vector<INativeWindow*> GetAllWindow() override;
+ INativeWindow* CreateWindow() override;
+
+ cru::platform::graphics::IGraphicsFactory* GetGraphicsFactory() override;
+
+ cru::platform::graphics::direct2d::DirectGraphicsFactory*
+ GetDirectFactory() {
+ return graph_factory_.get();
+ }
+
+ ICursorManager* GetCursorManager() override;
+
+ IClipboard* GetClipboard() override;
+
+ HINSTANCE GetInstanceHandle() const { return instance_handle_; }
+
+ GodWindow* GetGodWindow() const { return god_window_.get(); }
+ TimerManager* GetTimerManager() const { return timer_manager_.get(); }
+ WindowManager* GetWindowManager() const { return window_manager_.get(); }
+
+ private:
+ HINSTANCE instance_handle_;
+
+ bool is_quit_on_all_window_closed_ = true;
+
+ std::unique_ptr<cru::platform::graphics::direct2d::DirectGraphicsFactory>
+ graph_factory_;
+
+ std::unique_ptr<GodWindow> god_window_;
+ std::unique_ptr<TimerManager> timer_manager_;
+ std::unique_ptr<WindowManager> window_manager_;
+
+ std::unique_ptr<WinCursorManager> cursor_manager_;
+ std::unique_ptr<WinClipboard> clipboard_;
+
+ std::vector<std::function<void()>> quit_handlers_;
+};
+} // namespace cru::platform::gui::win
diff --git a/include/cru/platform/gui/win/Window.h b/include/cru/platform/gui/win/Window.h
new file mode 100644
index 00000000..292bdee2
--- /dev/null
+++ b/include/cru/platform/gui/win/Window.h
@@ -0,0 +1,217 @@
+#pragma once
+#include "Resource.h"
+
+#include "WindowNativeMessageEventArgs.h"
+#include "cru/platform/gui/Base.h"
+#include "cru/platform/gui/Window.h"
+#include "cru/platform/graphics/direct2d/WindowRenderTarget.h"
+
+#include <memory>
+
+namespace cru::platform::gui::win {
+class CRU_WIN_GUI_API WinNativeWindow : public WinNativeResource,
+ public virtual INativeWindow {
+ CRU_DEFINE_CLASS_LOG_TAG(u"WinNativeWindow")
+
+ public:
+ explicit WinNativeWindow(WinUiApplication* application);
+
+ CRU_DELETE_COPY(WinNativeWindow)
+ CRU_DELETE_MOVE(WinNativeWindow)
+
+ ~WinNativeWindow() override;
+
+ public:
+ void Close() override;
+
+ WinNativeWindow* GetParent() override { return parent_window_; }
+ void SetParent(INativeWindow* parent) override;
+
+ WindowStyleFlag GetStyleFlag() override { return style_flag_; }
+ void SetStyleFlag(WindowStyleFlag flag) override;
+
+ String GetTitle() override;
+ void SetTitle(String title) override;
+
+ WindowVisibilityType GetVisibility() override { return visibility_; }
+ void SetVisibility(WindowVisibilityType visibility) override;
+
+ Size GetClientSize() override;
+ void SetClientSize(const Size& size) override;
+
+ Rect GetClientRect() override;
+ void SetClientRect(const Rect& rect) override;
+
+ // Get the rect of the window containing frame.
+ // The lefttop of the rect is relative to screen lefttop.
+ Rect GetWindowRect() override;
+
+ // Set the rect of the window containing frame.
+ // The lefttop of the rect is relative to screen lefttop.
+ void SetWindowRect(const Rect& rect) override;
+
+ bool RequestFocus() override;
+
+ Point GetMousePosition() override;
+
+ bool CaptureMouse() override;
+ bool ReleaseMouse() override;
+
+ void RequestRepaint() override;
+ std::unique_ptr<graphics::IPainter> BeginPaint() override;
+
+ void SetCursor(std::shared_ptr<ICursor> cursor) override;
+
+ void SetToForeground() override;
+
+ IEvent<std::nullptr_t>* CreateEvent() override { return &create_event_; }
+ IEvent<std::nullptr_t>* DestroyEvent() override { return &destroy_event_; }
+ IEvent<std::nullptr_t>* PaintEvent() override { return &paint_event_; }
+ IEvent<WindowVisibilityType>* VisibilityChangeEvent() override {
+ return &visibility_change_event_;
+ }
+ IEvent<Size>* ResizeEvent() override { return &resize_event_; }
+ IEvent<FocusChangeType>* FocusEvent() override { return &focus_event_; }
+ IEvent<MouseEnterLeaveType>* MouseEnterLeaveEvent() override {
+ return &mouse_enter_leave_event_;
+ }
+ IEvent<Point>* MouseMoveEvent() override { return &mouse_move_event_; }
+ IEvent<platform::gui::NativeMouseButtonEventArgs>* MouseDownEvent() override {
+ return &mouse_down_event_;
+ }
+ IEvent<platform::gui::NativeMouseButtonEventArgs>* MouseUpEvent() override {
+ return &mouse_up_event_;
+ }
+ IEvent<NativeMouseWheelEventArgs>* MouseWheelEvent() override {
+ return &mouse_wheel_event_;
+ }
+
+ IEvent<platform::gui::NativeKeyEventArgs>* KeyDownEvent() override {
+ return &key_down_event_;
+ }
+ IEvent<platform::gui::NativeKeyEventArgs>* KeyUpEvent() override {
+ return &key_up_event_;
+ }
+
+ IEvent<WindowNativeMessageEventArgs&>* NativeMessageEvent() {
+ return &native_message_event_;
+ }
+
+ IInputMethodContext* GetInputMethodContext() override;
+
+ // Get the handle of the window. Return null if window is invalid.
+ HWND GetWindowHandle() const { return hwnd_; }
+
+ bool HandleNativeWindowMessage(HWND hwnd, UINT msg, WPARAM w_param,
+ LPARAM l_param, LRESULT* result);
+
+ graphics::direct2d::D2DWindowRenderTarget* GetWindowRenderTarget() const {
+ return window_render_target_.get();
+ }
+
+ //*************** region: dpi ***************
+ float GetDpi() const { return dpi_; }
+
+ inline int DipToPixel(const float dip) {
+ return static_cast<int>(dip * GetDpi() / 96.0f);
+ }
+
+ inline POINT DipToPixel(const Point& dip_point) {
+ POINT result;
+ result.x = DipToPixel(dip_point.x);
+ result.y = DipToPixel(dip_point.y);
+ return result;
+ }
+
+ inline RECT DipToPixel(const Rect& dip_rect) {
+ RECT result;
+ result.left = DipToPixel(dip_rect.left);
+ result.top = DipToPixel(dip_rect.top);
+ result.right = DipToPixel(dip_rect.GetRight());
+ result.bottom = DipToPixel(dip_rect.GetBottom());
+ return result;
+ }
+
+ inline float PixelToDip(const int pixel) {
+ return static_cast<float>(pixel) * 96.0f / GetDpi();
+ }
+
+ inline Point PixelToDip(const POINT& pi_point) {
+ return Point(PixelToDip(pi_point.x), PixelToDip(pi_point.y));
+ }
+
+ inline Rect PixelToDip(const RECT& pi_rect) {
+ return Rect::FromVertices(PixelToDip(pi_rect.left), PixelToDip(pi_rect.top),
+ PixelToDip(pi_rect.right),
+ PixelToDip(pi_rect.bottom));
+ }
+
+ private:
+ // Get the client rect in pixel.
+ RECT GetClientRectPixel();
+
+ void RecreateWindow();
+
+ //*************** region: native messages ***************
+
+ void OnCreateInternal();
+ void OnDestroyInternal();
+ void OnPaintInternal();
+ void OnMoveInternal(int new_left, int new_top);
+ void OnResizeInternal(int new_width, int new_height);
+
+ void OnSetFocusInternal();
+ void OnKillFocusInternal();
+
+ void OnMouseMoveInternal(POINT point);
+ void OnMouseLeaveInternal();
+ void OnMouseDownInternal(platform::gui::MouseButton button, POINT point);
+ void OnMouseUpInternal(platform::gui::MouseButton button, POINT point);
+
+ void OnMouseWheelInternal(short delta, POINT point);
+ void OnKeyDownInternal(int virtual_code);
+ void OnKeyUpInternal(int virtual_code);
+
+ void OnActivatedInternal();
+ void OnDeactivatedInternal();
+
+ private:
+ WinUiApplication* application_;
+
+ WindowStyleFlag style_flag_{};
+ WindowVisibilityType visibility_ = WindowVisibilityType::Hide;
+ Rect client_rect_{100, 100, 400, 300};
+ String title_;
+
+ HWND hwnd_ = nullptr;
+ WinNativeWindow* parent_window_ = nullptr;
+
+ float dpi_;
+
+ bool has_focus_ = false;
+ bool is_mouse_in_ = false;
+
+ std::unique_ptr<graphics::direct2d::D2DWindowRenderTarget>
+ window_render_target_;
+
+ std::shared_ptr<WinCursor> cursor_;
+
+ std::unique_ptr<WinInputMethodContext> input_method_context_;
+
+ Event<std::nullptr_t> create_event_;
+ Event<std::nullptr_t> destroy_event_;
+ Event<std::nullptr_t> paint_event_;
+ Event<Size> resize_event_;
+ Event<WindowVisibilityType> visibility_change_event_;
+ Event<FocusChangeType> focus_event_;
+ Event<MouseEnterLeaveType> mouse_enter_leave_event_;
+ Event<Point> mouse_move_event_;
+ Event<platform::gui::NativeMouseButtonEventArgs> mouse_down_event_;
+ Event<platform::gui::NativeMouseButtonEventArgs> mouse_up_event_;
+ Event<platform::gui::NativeMouseWheelEventArgs> mouse_wheel_event_;
+ Event<platform::gui::NativeKeyEventArgs> key_down_event_;
+ Event<platform::gui::NativeKeyEventArgs> key_up_event_;
+
+ Event<WindowNativeMessageEventArgs&> native_message_event_;
+};
+} // namespace cru::platform::gui::win
diff --git a/include/cru/platform/gui/win/WindowClass.h b/include/cru/platform/gui/win/WindowClass.h
new file mode 100644
index 00000000..50729887
--- /dev/null
+++ b/include/cru/platform/gui/win/WindowClass.h
@@ -0,0 +1,24 @@
+#pragma once
+#include "Base.h"
+
+#include <string>
+
+namespace cru::platform::gui::win {
+class CRU_WIN_GUI_API WindowClass : public Object {
+ public:
+ WindowClass(std::wstring name, WNDPROC window_proc, HINSTANCE h_instance);
+
+ CRU_DELETE_COPY(WindowClass)
+ CRU_DELETE_MOVE(WindowClass)
+
+ ~WindowClass() override = default;
+
+ const wchar_t* GetName() const { return name_.c_str(); }
+
+ ATOM GetAtom() const { return atom_; }
+
+ private:
+ std::wstring name_;
+ ATOM atom_;
+};
+} // namespace cru::platform::gui::win
diff --git a/include/cru/platform/gui/win/WindowNativeMessageEventArgs.h b/include/cru/platform/gui/win/WindowNativeMessageEventArgs.h
new file mode 100644
index 00000000..bc85a597
--- /dev/null
+++ b/include/cru/platform/gui/win/WindowNativeMessageEventArgs.h
@@ -0,0 +1,40 @@
+#pragma once
+#include "Base.h"
+
+#include "cru/common/Base.h"
+
+namespace cru::platform::gui::win {
+struct CRU_WIN_GUI_API WindowNativeMessage {
+ HWND hwnd;
+ UINT msg;
+ WPARAM w_param;
+ LPARAM l_param;
+};
+
+class CRU_WIN_GUI_API WindowNativeMessageEventArgs : public Object {
+ public:
+ WindowNativeMessageEventArgs(const WindowNativeMessage& message)
+ : message_(message) {}
+ CRU_DEFAULT_COPY(WindowNativeMessageEventArgs)
+ CRU_DEFAULT_MOVE(WindowNativeMessageEventArgs)
+ ~WindowNativeMessageEventArgs() override = default;
+
+ const WindowNativeMessage& GetWindowMessage() const { return message_; }
+
+ LRESULT GetResult() const { return result_; }
+ void SetResult(LRESULT result) { result_ = result; }
+
+ bool IsHandled() const { return handled_; }
+ void SetHandled(bool handled) { handled_ = handled; }
+
+ void HandleWithResult(LRESULT result) {
+ handled_ = true;
+ result_ = result;
+ }
+
+ private:
+ WindowNativeMessage message_;
+ LRESULT result_;
+ bool handled_ = false;
+};
+} // namespace cru::platform::gui::win