feat(window): add ime input event

This commit is contained in:
Nomango 2023-09-09 00:16:10 +08:00
parent 612a4cd21d
commit 6731b7dd3d
6 changed files with 92 additions and 10 deletions

View File

@ -162,10 +162,15 @@ void ImGuiModule::HandleEvent(EventModuleContext& ctx)
} }
else if (evt->IsType<KeyCharEvent>()) else if (evt->IsType<KeyCharEvent>())
{ {
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
char ch = dynamic_cast<KeyCharEvent*>(evt)->value; char ch = dynamic_cast<KeyCharEvent*>(evt)->value;
io.AddInputCharacter(static_cast<ImWchar>(ch)); io.AddInputCharacter(static_cast<ImWchar>(ch));
} }
else if (evt->IsType<IMEInputEvent>())
{
const auto& str = dynamic_cast<IMEInputEvent*>(evt)->value;
const auto utf8_str = strings::WideToUTF8(strings::NarrowToWide(str));
io.AddInputCharactersUTF8(utf8_str.c_str());
}
} }
} }

View File

@ -81,40 +81,60 @@ WideString FormatArgs(const wchar_t* format, va_list args)
return result; return result;
} }
String WideToNarrow(const WideString& str) String WideToNarrowWithCodePage(const WideString& str, UINT code_page)
{ {
if (str.empty()) if (str.empty())
return String(); 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) if (len > 0)
{ {
String result; String result;
result.resize(len - 1); 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 result;
} }
return String(); return String();
} }
WideString NarrowToWide(const String& str) WideString NarrowToWideWithCodePage(const String& str, UINT code_page)
{ {
if (str.empty()) if (str.empty())
return WideString(); 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) if (len > 0)
{ {
WideString result; WideString result;
result.resize(len - 1); 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 result;
} }
return WideString(); 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 #endif // KGE_PLATFORM_WINDOWS
} // namespace string } // namespace string

View File

@ -66,6 +66,14 @@ String WideToNarrow(const WideString& str);
/// @brief Õ­×Ö·û´®×ª¿í×Ö·û´® /// @brief Õ­×Ö·û´®×ª¿í×Ö·û´®
WideString NarrowToWide(const String& str); WideString NarrowToWide(const String& str);
/// \~chinese
/// @brief ¿í×Ö·û´®×ª utf8 ×Ö·û´®
String WideToUTF8(const WideString& str);
/// \~chinese
/// @brief utf8 ×Ö·û´®×ª¿í×Ö·û´®
WideString UTF8ToWide(const String& str);
} }

View File

@ -26,4 +26,10 @@ KeyCharEvent::KeyCharEvent()
{ {
} }
IMEInputEvent::IMEInputEvent()
: KeyEvent(KGE_EVENT(IMEInputEvent))
, value()
{
}
} // namespace kiwano } // namespace kiwano

View File

@ -28,6 +28,7 @@ KGE_DECLARE_SMART_PTR(KeyEvent);
KGE_DECLARE_SMART_PTR(KeyDownEvent); KGE_DECLARE_SMART_PTR(KeyDownEvent);
KGE_DECLARE_SMART_PTR(KeyUpEvent); KGE_DECLARE_SMART_PTR(KeyUpEvent);
KGE_DECLARE_SMART_PTR(KeyCharEvent); KGE_DECLARE_SMART_PTR(KeyCharEvent);
KGE_DECLARE_SMART_PTR(IMEInputEvent);
/** /**
* \addtogroup Event * \addtogroup Event
@ -72,13 +73,23 @@ public:
KeyCharEvent(); KeyCharEvent();
}; };
/// \~chinese
/// @brief 输入法输入事件
class KGE_API IMEInputEvent : public KeyEvent
{
public:
String value; ///< 输入内容
IMEInputEvent();
};
template <> template <>
struct IsSameEventType<KeyEvent> struct IsSameEventType<KeyEvent>
{ {
inline bool operator()(const Event* evt) const inline bool operator()(const Event* evt) const
{ {
return evt->GetType() == KGE_EVENT(KeyDownEvent) || evt->GetType() == KGE_EVENT(KeyUpEvent) 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);
} }
}; };

View File

@ -305,7 +305,7 @@ void WindowWin32Impl::Init(const WindowConfig& config)
::SetWindowPos(handle_, HWND_TOPMOST, x, y, cx, cy, SWP_NOACTIVATE); ::SetWindowPos(handle_, HWND_TOPMOST, x, y, cx, cy, SWP_NOACTIVATE);
::ShowWindow(handle_, SW_SHOWNORMAL); ::ShowWindow(handle_, SW_SHOWNORMAL);
resolution_.width = config.width; resolution_.width = config.width;
resolution_.height = config.height; resolution_.height = config.height;
} }
else else
@ -552,6 +552,38 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
} }
break; 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<char*>(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_LBUTTONDOWN:
case WM_LBUTTONDBLCLK: case WM_LBUTTONDBLCLK:
case WM_RBUTTONDOWN: case WM_RBUTTONDOWN:
@ -742,7 +774,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
if (max_width_ && max_height_) if (max_width_ && max_height_)
{ {
((MINMAXINFO*)lparam)->ptMaxTrackSize = POINT{ LONG(max_width_), LONG(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; return 0;
} }