From 6731b7dd3d0b8361f25426c69cdc0727f8d0f645 Mon Sep 17 00:00:00 2001 From: Nomango Date: Sat, 9 Sep 2023 00:16:10 +0800 Subject: [PATCH] feat(window): add ime input event --- src/kiwano-imgui/ImGuiModule.cpp | 7 ++++- src/kiwano/core/String.cpp | 32 +++++++++++++++++---- src/kiwano/core/String.h | 8 ++++++ src/kiwano/event/KeyEvent.cpp | 6 ++++ src/kiwano/event/KeyEvent.h | 13 ++++++++- src/kiwano/platform/win32/WindowImpl.cpp | 36 ++++++++++++++++++++++-- 6 files changed, 92 insertions(+), 10 deletions(-) diff --git a/src/kiwano-imgui/ImGuiModule.cpp b/src/kiwano-imgui/ImGuiModule.cpp index 9cfd243a..2c03c508 100644 --- a/src/kiwano-imgui/ImGuiModule.cpp +++ b/src/kiwano-imgui/ImGuiModule.cpp @@ -162,10 +162,15 @@ void ImGuiModule::HandleEvent(EventModuleContext& ctx) } else if (evt->IsType()) { - // You can also use ToAscii()+GetKeyboardState() to retrieve characters. char ch = dynamic_cast(evt)->value; io.AddInputCharacter(static_cast(ch)); } + else if (evt->IsType()) + { + const auto& str = dynamic_cast(evt)->value; + const auto utf8_str = strings::WideToUTF8(strings::NarrowToWide(str)); + io.AddInputCharactersUTF8(utf8_str.c_str()); + } } } diff --git a/src/kiwano/core/String.cpp b/src/kiwano/core/String.cpp index f416bdc0..33a9ea53 100644 --- a/src/kiwano/core/String.cpp +++ b/src/kiwano/core/String.cpp @@ -81,40 +81,60 @@ WideString FormatArgs(const wchar_t* format, va_list args) return result; } -String WideToNarrow(const WideString& str) +String WideToNarrowWithCodePage(const WideString& str, UINT code_page) { if (str.empty()) return String(); - int len = ::WideCharToMultiByte(CP_ACP, 0, str.c_str(), -1, NULL, 0, NULL, NULL); + int len = ::WideCharToMultiByte(code_page, 0, str.c_str(), -1, NULL, 0, NULL, NULL); if (len > 0) { String result; result.resize(len - 1); - ::WideCharToMultiByte(CP_ACP, 0, str.c_str(), -1, &result[0], len, NULL, NULL); + ::WideCharToMultiByte(code_page, 0, str.c_str(), -1, &result[0], len, NULL, NULL); return result; } return String(); } -WideString NarrowToWide(const String& str) +WideString NarrowToWideWithCodePage(const String& str, UINT code_page) { if (str.empty()) return WideString(); - int len = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0); + int len = ::MultiByteToWideChar(code_page, 0, str.c_str(), -1, NULL, 0); if (len > 0) { WideString result; result.resize(len - 1); - ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, &result[0], len); + ::MultiByteToWideChar(code_page, 0, str.c_str(), -1, &result[0], len); return result; } return WideString(); } +String WideToNarrow(const WideString& str) +{ + return WideToNarrowWithCodePage(str, CP_ACP); +} + +WideString NarrowToWide(const String& str) +{ + return NarrowToWideWithCodePage(str, CP_ACP); +} + +String WideToUTF8(const WideString& str) +{ + return WideToNarrowWithCodePage(str, CP_UTF8); +} + +WideString UTF8ToWide(const String& str) +{ + return NarrowToWideWithCodePage(str, CP_UTF8); +} + #endif // KGE_PLATFORM_WINDOWS } // namespace string diff --git a/src/kiwano/core/String.h b/src/kiwano/core/String.h index a1ab168c..a007822c 100644 --- a/src/kiwano/core/String.h +++ b/src/kiwano/core/String.h @@ -66,6 +66,14 @@ String WideToNarrow(const WideString& str); /// @brief Õ­×Ö·û´®×ª¿í×Ö·û´® WideString NarrowToWide(const String& str); +/// \~chinese +/// @brief ¿í×Ö·û´®×ª utf8 ×Ö·û´® +String WideToUTF8(const WideString& str); + +/// \~chinese +/// @brief utf8 ×Ö·û´®×ª¿í×Ö·û´® +WideString UTF8ToWide(const String& str); + } diff --git a/src/kiwano/event/KeyEvent.cpp b/src/kiwano/event/KeyEvent.cpp index f654ffd1..df5b8e39 100644 --- a/src/kiwano/event/KeyEvent.cpp +++ b/src/kiwano/event/KeyEvent.cpp @@ -26,4 +26,10 @@ KeyCharEvent::KeyCharEvent() { } +IMEInputEvent::IMEInputEvent() + : KeyEvent(KGE_EVENT(IMEInputEvent)) + , value() +{ +} + } // namespace kiwano diff --git a/src/kiwano/event/KeyEvent.h b/src/kiwano/event/KeyEvent.h index 2925ccbb..0beccf0a 100644 --- a/src/kiwano/event/KeyEvent.h +++ b/src/kiwano/event/KeyEvent.h @@ -28,6 +28,7 @@ KGE_DECLARE_SMART_PTR(KeyEvent); KGE_DECLARE_SMART_PTR(KeyDownEvent); KGE_DECLARE_SMART_PTR(KeyUpEvent); KGE_DECLARE_SMART_PTR(KeyCharEvent); +KGE_DECLARE_SMART_PTR(IMEInputEvent); /** * \addtogroup Event @@ -72,13 +73,23 @@ public: KeyCharEvent(); }; +/// \~chinese +/// @brief ÊäÈë·¨ÊäÈëʼþ +class KGE_API IMEInputEvent : public KeyEvent +{ +public: + String value; ///< ÊäÈëÄÚÈÝ + + IMEInputEvent(); +}; + template <> struct IsSameEventType { inline bool operator()(const Event* evt) const { return evt->GetType() == KGE_EVENT(KeyDownEvent) || evt->GetType() == KGE_EVENT(KeyUpEvent) - || evt->GetType() == KGE_EVENT(KeyCharEvent); + || evt->GetType() == KGE_EVENT(KeyCharEvent) || evt->GetType() == KGE_EVENT(IMEInputEvent); } }; diff --git a/src/kiwano/platform/win32/WindowImpl.cpp b/src/kiwano/platform/win32/WindowImpl.cpp index b4ffe93c..b968ee0f 100644 --- a/src/kiwano/platform/win32/WindowImpl.cpp +++ b/src/kiwano/platform/win32/WindowImpl.cpp @@ -305,7 +305,7 @@ void WindowWin32Impl::Init(const WindowConfig& config) ::SetWindowPos(handle_, HWND_TOPMOST, x, y, cx, cy, SWP_NOACTIVATE); ::ShowWindow(handle_, SW_SHOWNORMAL); - resolution_.width = config.width; + resolution_.width = config.width; resolution_.height = config.height; } else @@ -552,6 +552,38 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA } break; + case WM_IME_CHAR: + { + // no need to handle + return TRUE; + } + + case WM_IME_COMPOSITION: + { + if (lparam & GCS_RESULTSTR) + { + const auto hIMC = ::ImmGetContext(hwnd); + if (hIMC) + { + // Get the size of the result string. + auto dwSize = ::ImmGetCompositionStringA(hIMC, GCS_RESULTSTR, NULL, 0); + + // increase buffer size for terminating null character + dwSize += sizeof(char); + + // Get the result strings that is generated by IME. + String buf(size_t(dwSize), 0); + ::ImmGetCompositionStringA(hIMC, GCS_RESULTSTR, const_cast(buf.data()), dwSize); + ::ImmReleaseContext(hwnd, hIMC); + + IMEInputEventPtr evt = new IMEInputEvent; + evt->value = std::move(buf); + this->PushEvent(evt); + return TRUE; + } + } + } + case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: @@ -742,7 +774,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA if (max_width_ && max_height_) { ((MINMAXINFO*)lparam)->ptMaxTrackSize = POINT{ LONG(max_width_), LONG(max_height_) }; - ((MINMAXINFO*)lparam)->ptMaxSize = POINT{ LONG(max_width_), LONG(max_height_) }; + ((MINMAXINFO*)lparam)->ptMaxSize = POINT{ LONG(max_width_), LONG(max_height_) }; } return 0; }