- ベストアンサー
変換中の文字を表示させず、IMEを利用するには。
現在 VC9にて、IME入力を取得するプログラムを書いています。 そのプログラムには、エディットボックスなどが なく、普通のウィンドウに対してImmGetContext()を行い、 現在の入力状況を取得しています。 ここで問題なのですが、この状態で実行すると、ウィンドウの左上に 変換中の文字が見えてしまいます。これを見えなくさせようと思い、 ImmDisableIMEを呼ぶと当然ながら、IMEからのメッセージは なくなってしまいます。 要点は ・変換中の文字を見せることなく ・IMEの編集状況を取得するにはどうしたらよいか? です。 環境はVC9、XP sp3になります。 よろしくお願いします。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
IMEの入力位置を移動するサンプル作ってみました。 imm.h使うの結構久しぶりなので、てこずりました。 テストとかしてませんので、バグあると思います。 参考にどうぞ。 ---------------------------------------------------------------------- /* * test_SetCaret.cxx * * Created on: 2009/02/11 * Author: yanch */ #define STRICT #include <cstdio> #include <windows.h> #include <imm.h> #define MEM_CLEAR(x) ::ZeroMemory(&x,sizeof(x)) #define CLASS_NAME TEXT("SAMPLE") #define WINDOW_NAME TEXT("test_SetCaret") HWND hMainWnd; LRESULT CALLBACK MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); LRESULT onKillFocus( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); LRESULT onSetFocus( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); /*============================================================================= =============================================================================*/ int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd ) { MSG msg; HRESULT hRet; WNDCLASSEX wcex; MEM_CLEAR( wcex ); wcex.cbSize = sizeof( WNDCLASSEX ); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)::MainWndProc; wcex.hInstance = hInst; wcex.hIcon = ::LoadIcon( 0, IDI_APPLICATION ); wcex.hCursor = ::LoadCursor( 0, IDC_ARROW ); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW); wcex.lpszClassName = CLASS_NAME; hRet = ::RegisterClassEx( &wcex ); if ( !hRet ) return 0; hMainWnd = ::CreateWindowEx( 0, CLASS_NAME, WINDOW_NAME, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInst, 0 ); if ( !hMainWnd ) return 0; ::ShowWindow( hMainWnd, nShowCmd ); ::UpdateWindow( hMainWnd ); while ( ::GetMessage( &msg, 0, 0, 0 ) ) { ::TranslateMessage( &msg ); ::DispatchMessage( &msg ); } return msg.wParam; } /*============================================================================= =============================================================================*/ LRESULT CALLBACK MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch ( uMsg ) { case WM_KILLFOCUS: return onKillFocus( hWnd, uMsg, wParam, lParam ); case WM_SETFOCUS: return onSetFocus( hWnd, uMsg, wParam, lParam ); case WM_DESTROY: ::PostQuitMessage( 0 ); return 0; } return ::DefWindowProc( hWnd, uMsg, wParam, lParam ); } LRESULT onKillFocus( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { ::HideCaret(hWnd); ::DestroyCaret(); return 0; } LRESULT onSetFocus( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { int nNewPosX = 100; int nNewPosY = 100; ::CreateCaret(hWnd, NULL, 10, 10); ::SetCaretPos(nNewPosX, nNewPosY); HIMC hImc = ::ImmGetContext(hWnd); if (hImc) { COMPOSITIONFORM cpf; cpf.dwStyle = CFS_POINT; cpf.ptCurrentPos.x = nNewPosX; cpf.ptCurrentPos.y = nNewPosY; ImmSetCompositionWindow(hImc, &cpf); ImmReleaseContext(hWnd, hImc); } return 0; } // [EOF:test_SetCaret.cxx] ----------------------------------------------------------------------
その他の回答 (3)
- sha-girl
- ベストアンサー率52% (430/816)
よくゲームでは IMEの候補リストウインドウを含めて自前で描画しますが 質問者さんが行おうとしている処理と関係があると思います。 DirectX SDKについてくるサンプルソースで CustomUIというものがありますが、 これは日本語入力部分の表示をDirectXを使って独自に描画しているので参考になると思います。 http://msdn.microsoft.com/ja-jp/directx/default.aspx (DirectXに関係なく自前で描画出来ます。) 具体的にどうしてるかというと WM_IME_SETCONTEXTを受け取ったときに lParam = 0;とするとIME関連の表示が行われなくなります。 後はWM_IME~のメッセージ(WM_IME_STARTCOMPOSITION 、WM_IME_COMPOSITION、WM_IME_ENDCOMPOSITION、WM_IME_NOTIFY) に必要な処理をしてやれば お望みの動作が可能かと思います。
- Yanch
- ベストアンサー率50% (114/225)
ちと、記憶を頼りに調べてみました。 動作確認していないので、うまく行くかわかりませんが、 SetCaretPos()とか使えませんか? 後、「キャレット」などで、ウェブ検索すると、何か参考になるページが見つかるかもしれません。
補足
ありがとうございます。 しかし、やはり上手くいきませんね。 画像つきのほうが解りやすいと思ったので、上げました。 http://www.dotup.org/uploda/www.dotup.org3267.jpg このように、エディットボックスなどがないまっさらなウィンドウ 上で入力すると出るタイプのものです。 教えて頂いたSetCaretPosを利用しても、位置は変わらず、 HideCaretを利用しても表示は消えませんでした。 う~ん。
- Yanch
- ベストアンサー率50% (114/225)
変換中の文字が見えないと、文字入力しているユーザが困るんじゃ? と言う気がしますが、 確か、拙者の記憶だと、IMEの変換入力中の文字列を表示する位置を 変更するAPIがあったと思います。 デスクトップの外などに変換入力位置を飛ばしてしまうどうでしょう。
補足
返答ありがとうございます。 説明不足でしたね。 これはフルスクリーンゲーム中でのキーボード入力を 取得する部分になります。 >IMEの変換入力中の文字列を表示する位置を変更するAPI 調べてみました。ImmSetCompositionWindowですかね? やり方が不味いのか、これでは上手くいきませんでした。 同様にImmSetCompositionWindowも試してみましたが、 上手くいきません。
補足
おお、ありがとうございます!!! まさしく自分がやりたかったことです。 ちょっとESPを要求するような書き方でしたね。すいません。 #CustomUIのサンプルは、新旧のSDKの設定がこんがらがって #しまっていて、ビルドできずに、「ひとまず自力でやってみる」 #という方針でやっていました。