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:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user