diff options
author | crupest <crupest@outlook.com> | 2018-09-23 23:08:54 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2018-09-23 23:08:54 +0800 |
commit | be84ddd03d3b59c0c27aa538d5ef5129f94d511c (patch) | |
tree | 66448a2559b216352cca5ee28a470cbc8fb9c08a | |
parent | 800c98a732f82df09a98fddba91eddb5d675318d (diff) | |
download | cru-be84ddd03d3b59c0c27aa538d5ef5129f94d511c.tar.gz cru-be84ddd03d3b59c0c27aa538d5ef5129f94d511c.tar.bz2 cru-be84ddd03d3b59c0c27aa538d5ef5129f94d511c.zip |
Add keyboard events to control.
-rw-r--r-- | CruUI/ui/control.cpp | 45 | ||||
-rw-r--r-- | CruUI/ui/control.h | 17 | ||||
-rw-r--r-- | CruUI/ui/controls/text_block.cpp | 37 | ||||
-rw-r--r-- | CruUI/ui/controls/text_box.cpp | 42 | ||||
-rw-r--r-- | CruUI/ui/events/ui_event.h | 46 | ||||
-rw-r--r-- | CruUI/ui/window.cpp | 30 | ||||
-rw-r--r-- | CruUI/ui/window.h | 5 |
7 files changed, 169 insertions, 53 deletions
diff --git a/CruUI/ui/control.cpp b/CruUI/ui/control.cpp index 25f7c028..eaf206ac 100644 --- a/CruUI/ui/control.cpp +++ b/CruUI/ui/control.cpp @@ -472,6 +472,51 @@ namespace cru { } + void Control::OnKeyDown(KeyEventArgs& args) + { + } + + void Control::OnKeyUp(KeyEventArgs& args) + { + } + + void Control::OnChar(events::CharEvent& args) + { + } + + void Control::OnKeyDownCore(KeyEventArgs& args) + { + } + + void Control::OnKeyUpCore(KeyEventArgs& args) + { + } + + void Control::OnCharCore(events::CharEvent& args) + { + } + + void Control::RaiseKeyDownEvent(KeyEventArgs& args) + { + OnKeyDownCore(args); + OnKeyDown(args); + key_down_event.Raise(args); + } + + void Control::RaiseKeyUpEvent(KeyEventArgs& args) + { + OnKeyUpCore(args); + OnKeyUp(args); + key_up_event.Raise(args); + } + + void Control::RaiseCharEvent(CharEvent& args) + { + OnCharCore(args); + OnChar(args); + char_event.Raise(args); + } + void Control::OnGetFocus(FocusChangeEventArgs& args) { diff --git a/CruUI/ui/control.h b/CruUI/ui/control.h index 78261a80..fa1158a4 100644 --- a/CruUI/ui/control.h +++ b/CruUI/ui/control.h @@ -214,6 +214,10 @@ namespace cru //Raised when a mouse button is pressed in the control and released in the control with mouse not leaving it between two operations. events::MouseButtonEvent mouse_click_event; + events::KeyEvent key_down_event; + events::KeyEvent key_up_event; + events::CharEvent char_event; + events::FocusChangeEvent get_focus_event; events::FocusChangeEvent lose_focus_event; @@ -278,6 +282,19 @@ namespace cru virtual void OnMouseClickBegin(MouseButton button); virtual void OnMouseClickEnd(MouseButton button); + //*************** region: keyboard event *************** + virtual void OnKeyDown(events::KeyEventArgs& args); + virtual void OnKeyUp(events::KeyEventArgs& args); + virtual void OnChar(events::CharEvent& args); + + virtual void OnKeyDownCore(events::KeyEventArgs& args); + virtual void OnKeyUpCore(events::KeyEventArgs& args); + virtual void OnCharCore(events::CharEvent& args); + + void RaiseKeyDownEvent(events::KeyEventArgs& args); + void RaiseKeyUpEvent(events::KeyEventArgs& args); + void RaiseCharEvent(events::CharEvent& args); + //*************** region: focus event *************** virtual void OnGetFocus(events::FocusChangeEventArgs& args); virtual void OnLoseFocus(events::FocusChangeEventArgs& args); diff --git a/CruUI/ui/controls/text_block.cpp b/CruUI/ui/controls/text_block.cpp index f0ef41d9..4ecbb672 100644 --- a/CruUI/ui/controls/text_block.cpp +++ b/CruUI/ui/controls/text_block.cpp @@ -20,12 +20,11 @@ namespace cru TextBlock::TextBlock(const Microsoft::WRL::ComPtr<IDWriteTextFormat>& init_text_format, const Microsoft::WRL::ComPtr<ID2D1Brush>& init_brush) : Control(false) { - text_format_ = init_text_format; + text_format_ = init_text_format == nullptr ? graph::CreateDefaultTextFormat() : init_text_format; - if (init_brush == nullptr) - brush_ = CreateSolidBrush(D2D1::ColorF(D2D1::ColorF::Black)); - else - brush_ = init_brush; + RecreateTextLayout(); + + brush_ = init_brush == nullptr ? CreateSolidBrush(D2D1::ColorF(D2D1::ColorF::Black)) : init_brush; selection_brush_ = CreateSolidBrush(D2D1::ColorF(D2D1::ColorF::LightSkyBlue)); } @@ -126,15 +125,18 @@ namespace cru } } - std::optional<unsigned> TextLayoutHitTest(IDWriteTextLayout* text_layout, const Point& point, bool test_inside = true) + namespace { - BOOL is_trailing, is_inside; - DWRITE_HIT_TEST_METRICS metrics{}; - text_layout->HitTestPoint(point.x, point.y, &is_trailing, &is_inside, &metrics); - if (!test_inside || is_inside) - return is_trailing == 0 ? metrics.textPosition : metrics.textPosition + 1; - else - return std::nullopt; + std::optional<unsigned> TextLayoutHitTest(IDWriteTextLayout* text_layout, const Point& point, const bool test_inside = true) + { + BOOL is_trailing, is_inside; + DWRITE_HIT_TEST_METRICS metrics{}; + text_layout->HitTestPoint(point.x, point.y, &is_trailing, &is_inside, &metrics); + if (!test_inside || is_inside) + return is_trailing == 0 ? metrics.textPosition : metrics.textPosition + 1; + else + return std::nullopt; + } } void TextBlock::OnMouseDownCore(events::MouseButtonEventArgs& args) @@ -264,17 +266,10 @@ namespace cru void TextBlock::RecreateTextLayout() { - if (text_.empty()) - { - text_layout_ = nullptr; - return; - } + assert(text_format_ != nullptr); const auto dwrite_factory = GetDWriteFactory(); - if (text_format_ == nullptr) - text_format_ = graph::CreateDefaultTextFormat(); - const auto&& size = GetSize(); ThrowIfFailed(dwrite_factory->CreateTextLayout( diff --git a/CruUI/ui/controls/text_box.cpp b/CruUI/ui/controls/text_box.cpp index ce834ef6..586bc017 100644 --- a/CruUI/ui/controls/text_box.cpp +++ b/CruUI/ui/controls/text_box.cpp @@ -65,40 +65,22 @@ namespace cru::ui::controls Control::OnDraw(device_context); if (text_layout_ != nullptr) { - //if (selected_range_.has_value()) - //{ - // DWRITE_TEXT_METRICS text_metrics{}; - // ThrowIfFailed(text_layout_->GetMetrics(&text_metrics)); - // const auto metrics_count = text_metrics.lineCount * text_metrics.maxBidiReorderingDepth; - - // Vector<DWRITE_HIT_TEST_METRICS> hit_test_metrics(metrics_count); - // UINT32 actual_count; - // text_layout_->HitTestTextRange( - // selected_range_.value().position, selected_range_.value().count, - // 0, 0, - // hit_test_metrics.data(), metrics_count, &actual_count - // ); - - // hit_test_metrics.erase(hit_test_metrics.cbegin() + actual_count, hit_test_metrics.cend()); - - // for (const auto& metrics : hit_test_metrics) - // { - // device_context->FillRoundedRectangle(D2D1::RoundedRect(D2D1::RectF(metrics.left, metrics.top, metrics.left + metrics.width, metrics.top + metrics.height), 3, 3), selection_brush_.Get()); - // } - //} device_context->DrawTextLayout(D2D1::Point2F(), text_layout_.Get(), brush_.Get()); } } - std::optional<unsigned> TextLayoutHitTest(IDWriteTextLayout* text_layout, const Point& point, bool test_inside = true) + namespace { - BOOL is_trailing, is_inside; - DWRITE_HIT_TEST_METRICS metrics{}; - text_layout->HitTestPoint(point.x, point.y, &is_trailing, &is_inside, &metrics); - if (!test_inside || is_inside) - return is_trailing == 0 ? metrics.textPosition : metrics.textPosition + 1; - else - return std::nullopt; + std::optional<unsigned> TextLayoutHitTest(IDWriteTextLayout* text_layout, const Point& point, bool test_inside = true) + { + BOOL is_trailing, is_inside; + DWRITE_HIT_TEST_METRICS metrics{}; + text_layout->HitTestPoint(point.x, point.y, &is_trailing, &is_inside, &metrics); + if (!test_inside || is_inside) + return is_trailing == 0 ? metrics.textPosition : metrics.textPosition + 1; + else + return std::nullopt; + } } void TextBox::OnMouseDownCore(events::MouseButtonEventArgs& args) @@ -107,7 +89,7 @@ namespace cru::ui::controls if (args.GetMouseButton() == MouseButton::Left) { position_ = TextLayoutHitTest(text_layout_.Get(), args.GetPoint(this), false).value(); - + Repaint(); } } diff --git a/CruUI/ui/events/ui_event.h b/CruUI/ui/events/ui_event.h index a17067c7..b042b706 100644 --- a/CruUI/ui/events/ui_event.h +++ b/CruUI/ui/events/ui_event.h @@ -257,6 +257,50 @@ namespace cru std::optional<LRESULT> result_; }; + class KeyEventArgs : public UiEventArgs + { + public: + KeyEventArgs(Object* sender, Object* original_sender, int virtual_code) + : UiEventArgs(sender, original_sender), virtual_code_(virtual_code) + { + } + KeyEventArgs(const KeyEventArgs& other) = default; + KeyEventArgs(KeyEventArgs&& other) = default; + KeyEventArgs& operator=(const KeyEventArgs& other) = default; + KeyEventArgs& operator=(KeyEventArgs&& other) = default; + ~KeyEventArgs() override = default; + + int GetVirtualCode() const + { + return virtual_code_; + } + + private: + int virtual_code_; + }; + + class CharEventArgs : public UiEventArgs + { + public: + CharEventArgs(Object* sender, Object* original_sender, wchar_t c) + : UiEventArgs(sender, original_sender), c_(c) + { + } + CharEventArgs(const CharEventArgs& other) = default; + CharEventArgs(CharEventArgs&& other) = default; + CharEventArgs& operator=(const CharEventArgs& other) = default; + CharEventArgs& operator=(CharEventArgs&& other) = default; + ~CharEventArgs() override = default; + + wchar_t GetChar() const + { + return c_; + } + + private: + wchar_t c_; + }; + using UiEvent = Event<UiEventArgs>; using MouseEvent = Event<MouseEventArgs>; using MouseButtonEvent = Event<MouseButtonEventArgs>; @@ -266,6 +310,8 @@ namespace cru using FocusChangeEvent = Event<FocusChangeEventArgs>; using ToggleEvent = Event<ToggleEventArgs>; using WindowNativeMessageEvent = Event<WindowNativeMessageEventArgs>; + using KeyEvent = Event<KeyEventArgs>; + using CharEvent = Event<CharEventArgs>; } } }
\ No newline at end of file diff --git a/CruUI/ui/window.cpp b/CruUI/ui/window.cpp index 6ff962b6..34a54512 100644 --- a/CruUI/ui/window.cpp +++ b/CruUI/ui/window.cpp @@ -204,8 +204,7 @@ namespace cru if (!native_message_event.IsNoHandler()) { - const events::WindowNativeMessage message{hwnd, msg, w_param, l_param}; - events::WindowNativeMessageEventArgs args(this, this, message); + events::WindowNativeMessageEventArgs args(this, this, {hwnd, msg, w_param, l_param}); native_message_event.Raise(args); if (args.GetResult().has_value()) { @@ -293,6 +292,18 @@ namespace cru result = 0; return true; } + case WM_KEYDOWN: + OnKeyDownInternal(static_cast<int>(w_param)); + result = 0; + return true; + case WM_KEYUP: + OnKeyUpInternal(static_cast<int>(w_param)); + result = 0; + return true; + case WM_CHAR: + OnCharInternal(static_cast<wchar_t>(w_param)); + result = 0; + return true; case WM_SIZE: OnResizeInternal(LOWORD(l_param), HIWORD(l_param)); result = 0; @@ -553,6 +564,21 @@ namespace cru DispatchEvent(control, &Control::RaiseMouseUpEvent, nullptr, dip_point, button); } + void Window::OnKeyDownInternal(int virtual_code) + { + DispatchEvent(focus_control_, &Control::RaiseKeyDownEvent, nullptr, virtual_code); + } + + void Window::OnKeyUpInternal(int virtual_code) + { + DispatchEvent(focus_control_, &Control::RaiseKeyUpEvent, nullptr, virtual_code); + } + + void Window::OnCharInternal(wchar_t c) + { + DispatchEvent(focus_control_, &Control::RaiseCharEvent, nullptr, c); + } + void Window::OnActivatedInternal() { events::UiEventArgs args(this, this); diff --git a/CruUI/ui/window.h b/CruUI/ui/window.h index 42ebf477..40d81a06 100644 --- a/CruUI/ui/window.h +++ b/CruUI/ui/window.h @@ -6,6 +6,7 @@ #include <memory> #include "control.h" +#include "events/ui_event.h" namespace cru { namespace graph { @@ -219,6 +220,10 @@ namespace cru { void OnMouseDownInternal(MouseButton button, POINT point); void OnMouseUpInternal(MouseButton button, POINT point); + void OnKeyDownInternal(int virtual_code); + void OnKeyUpInternal(int virtual_code); + void OnCharInternal(wchar_t c); + void OnActivatedInternal(); void OnDeactivatedInternal(); |