テキストエディタの一般的な操作で、
変換キーを押して変換ウィンドウを表示する動作についての質問です。
下記と同様のコードで、変換は可能ですが、
変換ウィンドウ表示後、Escキー や Ctrl+z でキャンセルするような操作をしたときに、
IME から WM_IME_COMPOSITION を受け取ってしまい、
結果としてテキスト内容を変更される事は無いですが変換作業を実行してしまいます。
WM_IME_COMPOSITION を受け取るとアンドゥの都合上好ましくないので、
WM_IME_COMPOSITION を送らないように出来るのでしょうか?
出来ないのなら、
こちらの要求と IME の結果を比較して同じならキャンセルという処理を考えています。
// visual c 設定 追加の依存ファイル "Imm32.lib"
#include <Imm.h>
// 変換ターゲットを sample の '4' に指定
#define RECONVERT_BEGIN 4
#define RECONVERT_END 5
LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wp, LPARAM lp )
{
static TCHAR sample[] = TEXT("123 456 789"),
str[256] = TEXT("初期値");
switch( msg ){
case WM_DESTROY:
PostQuitMessage( 0 );
break;
case WM_PAINT:{
PAINTSTRUCT ps;
BeginPaint( hWnd, &ps );
{ TCHAR str[] = TEXT("IME 処理結果"); TextOut( ps.hdc, 10, 30, str, lstrlen(str) ); }
TextOut( ps.hdc, 10, 50, str, lstrlen(str) );
EndPaint( hWnd, &ps );
break;}
case WM_IME_COMPOSITION:{
if( !(lp & GCS_RESULTSTR) ) return DefWindowProc( hWnd, msg, wp, lp );
HIMC hImc = ImmGetContext( hWnd );
int bytesize = ImmGetCompositionString( hImc, GCS_RESULTSTR, str, 0 );
ImmGetCompositionString( hImc, GCS_RESULTSTR, str, sizeof(str) );
str[ bytesize / sizeof(TCHAR) ] = TEXT('\0');
// ImmSetCompositionWindow
ImmReleaseContext( hWnd, hImc );
InvalidateRect( hWnd, NULL, TRUE );
break;}
case WM_IME_REQUEST:
if( wp == IMR_RECONVERTSTRING ){
if( lp ){
MessageBox( hWnd, TEXT("変換位置指定"), TEXT("WM_IME_REQUEST"), MB_OK );
RECONVERTSTRING *rcs = (RECONVERTSTRING *)lp;
rcs->dwStrLen = lstrlen( sample );
rcs->dwStrOffset = sizeof(RECONVERTSTRING);
rcs->dwCompStrLen = rcs->dwTargetStrLen = RECONVERT_END - RECONVERT_BEGIN;
rcs->dwCompStrOffset = rcs->dwTargetStrOffset = sizeof(TCHAR) * RECONVERT_BEGIN;
lstrcpy( (TCHAR *)(rcs + 1), sample );
return rcs->dwSize;
}else{
MessageBox( hWnd, TEXT("サイズ指定"), TEXT("WM_IME_REQUEST"), MB_OK );
return sizeof(RECONVERTSTRING) + sizeof(TCHAR) * (lstrlen(sample) + 1);
}
}else if( wp == IMR_CONFIRMRECONVERTSTRING ){
MessageBox( hWnd, TEXT("IME 変換位置要求"), TEXT("WM_IME_REQUEST"), MB_OK );
return TRUE;
}else{
return DefWindowProc( hWnd, WM_IME_REQUEST, wp, lp );
}
break;
default:
return DefWindowProc( hWnd, msg, wp, lp );
}
return 0;
}