aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2018-09-23 23:08:54 +0800
committercrupest <crupest@outlook.com>2018-09-23 23:08:54 +0800
commitbe84ddd03d3b59c0c27aa538d5ef5129f94d511c (patch)
tree66448a2559b216352cca5ee28a470cbc8fb9c08a
parent800c98a732f82df09a98fddba91eddb5d675318d (diff)
downloadcru-be84ddd03d3b59c0c27aa538d5ef5129f94d511c.tar.gz
cru-be84ddd03d3b59c0c27aa538d5ef5129f94d511c.tar.bz2
cru-be84ddd03d3b59c0c27aa538d5ef5129f94d511c.zip
Add keyboard events to control.
-rw-r--r--CruUI/ui/control.cpp45
-rw-r--r--CruUI/ui/control.h17
-rw-r--r--CruUI/ui/controls/text_block.cpp37
-rw-r--r--CruUI/ui/controls/text_box.cpp42
-rw-r--r--CruUI/ui/events/ui_event.h46
-rw-r--r--CruUI/ui/window.cpp30
-rw-r--r--CruUI/ui/window.h5
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();