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>())
{
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
char ch = dynamic_cast<KeyCharEvent*>(evt)->value;
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;
}
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

View File

@ -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);
}

View File

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

View File

@ -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<KeyEvent>
{
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);
}
};

View File

@ -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<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_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;
}