fix the strange behavior of Korean ime composition window.

Because Hangul is a combination character, WM_IME_STARTCOMPOSITION is only called once when the IME input is started, so the position of the composition window is strange.

Therefore, I solved the problem by controlling the state of characters combined using WM_IME_COMPOSITION and WM_IME_CHAR.

We have also improved to support other IME languages such as Chinese and Japanese.
This commit is contained in:
이지한
2019-08-01 15:24:46 +09:00
parent de9043e223
commit 129b83e68f
13 changed files with 152 additions and 12 deletions

View File

@@ -77,6 +77,9 @@ namespace detail
typedef BOOL (__stdcall* imm_set_composition_window_type)(HIMC, LPCOMPOSITIONFORM);
imm_set_composition_window_type imm_set_composition_window;
typedef LONG(__stdcall* imm_get_composition_string_type)(HIMC, DWORD, LPVOID, DWORD);
imm_get_composition_string_type imm_get_composition_string;
}
#pragma pack(1)
//Decoder of WPARAM and LPARAM
@@ -210,6 +213,9 @@ namespace detail
restrict::imm_set_composition_window = reinterpret_cast<restrict::imm_set_composition_window_type>(
::GetProcAddress(imm32, "ImmSetCompositionWindow"));
restrict::imm_get_composition_string = reinterpret_cast<restrict::imm_get_composition_string_type>(
::GetProcAddress(imm32, "ImmGetCompositionStringW"));
}
bedrock::~bedrock()
@@ -639,6 +645,8 @@ namespace detail
case WM_NCRBUTTONDOWN:
case WM_NCMBUTTONDOWN:
case WM_IME_STARTCOMPOSITION:
case WM_IME_COMPOSITION:
case WM_IME_CHAR:
case WM_DROPFILES:
case WM_MOUSELEAVE:
case WM_MOUSEWHEEL: //The WM_MOUSELAST may not include the WM_MOUSEWHEEL/WM_MOUSEHWHEEL when the version of SDK is low.
@@ -786,25 +794,67 @@ namespace detail
}
break;
case WM_IME_STARTCOMPOSITION:
if (msgwnd->other.attribute.root->ime_enabled)
break;
case WM_IME_COMPOSITION:
if (lParam & (GCS_COMPSTR | GCS_RESULTSTR))
{
auto native_font = msgwnd->drawer.graphics.typeface().handle();
LOGFONTW logfont;
::GetObjectW(reinterpret_cast<HFONT>(native_font), sizeof logfont, &logfont);
msgwnd = brock.focus();
if (msgwnd && msgwnd->flags.enabled)
{
auto & wd_manager = brock.wd_manager();
auto composition_index = static_cast<DWORD>(lParam & (GCS_COMPSTR | GCS_RESULTSTR));
HIMC imc = restrict::imm_get_context(root_window);
restrict::imm_set_composition_font(imc, &logfont);
arg_ime arg;
arg.window_handle = msgwnd;
if (lParam & GCS_COMPSTR)
{
arg.ime_reason = arg_ime::reason::composition;
}
if (lParam & GCS_RESULTSTR)
{
arg.ime_reason = arg_ime::reason::result;
}
POINT pos;
::GetCaretPos(&pos);
HIMC imc = restrict::imm_get_context(root_window);
auto size = restrict::imm_get_composition_string(imc, composition_index, nullptr, 0);
if (size > 0)
{
wchar_t * buffer = new wchar_t[100 / sizeof(wchar_t) + 1];
size = restrict::imm_get_composition_string(imc, composition_index, buffer, size + sizeof(wchar_t));
buffer[size / sizeof(wchar_t)] = '\0';
arg.composition_string = std::move(buffer);
delete[] buffer;
}
restrict::imm_release_context(root_window, imc);
COMPOSITIONFORM cf = { CFS_POINT };
cf.ptCurrentPos = pos;
restrict::imm_set_composition_window(imc, &cf);
restrict::imm_release_context(root_window, imc);
if (wd_manager.available(msgwnd))
draw_invoker(&drawer::key_ime, msgwnd, arg, &context);
wd_manager.do_lazy_refresh(msgwnd, false);
}
}
def_window_proc = true;
break;
case WM_IME_CHAR:
msgwnd = brock.focus();
if (msgwnd && msgwnd->flags.enabled)
{
auto & wd_manager = brock.wd_manager();
arg_keyboard arg;
arg.evt_code = event_code::key_char;
arg.window_handle = msgwnd;
arg.key = static_cast<wchar_t>(wParam);
brock.get_key_state(arg);
arg.ignore = false;
msgwnd->annex.events_ptr->key_char.emit(arg, msgwnd);
if ((false == arg.ignore) && wd_manager.available(msgwnd))
draw_invoker(&drawer::key_char, msgwnd, arg, &context);
wd_manager.do_lazy_refresh(msgwnd, false);
}
break;
case WM_GETMINMAXINFO:
{
bool take_over = false;

View File

@@ -96,6 +96,11 @@ namespace nana
overridden_ &= ~(1 << static_cast<int>(event_code::focus));
}
void drawer_trigger::key_ime(graph_reference, const arg_ime&)
{
overridden_ &= ~(1 << static_cast<int>(event_code::key_ime));
}
void drawer_trigger::key_press(graph_reference, const arg_keyboard&)
{
overridden_ &= ~(1 << static_cast<int>(event_code::key_press));
@@ -318,6 +323,11 @@ namespace nana
_m_emit(event_code::focus, arg, &drawer_trigger::focus, bForce__EmitInternal);
}
void drawer::key_ime(const arg_ime& arg, const bool bForce__EmitInternal)
{
_m_emit(event_code::key_ime, arg, &drawer_trigger::key_ime, bForce__EmitInternal);
}
void drawer::key_press(const arg_keyboard& arg, const bool bForce__EmitInternal)
{
_m_emit(event_code::key_press, arg, &drawer_trigger::key_press, bForce__EmitInternal);