質問: C/C++とWin32APIでスクリーンキーボードを作っています。 ウインドウに設置されたボタンが押されると、 対応したキーをkebd_eventにて入力する方法で作っているのですが、 そうするとAのキーを押してもIMEの状態によっては「あ」と入力されてしまう 問題にぶつかりました。 そこで、IMEをスクリーンキーボード側で制御しようと考えたのですが、 ImmGetContext()では別アプリのコンテキストハンドルを取得することができないと知り、 悩んでいます。 別アプリのIMEを制御するためにはどうすればいいのでしょうか。
回答: スクリーンキーボードを実装するという観点から次の3案を提示します。ソフトウェアの性質によってどれを採用するかが変わるかと思います。 ### 1.IMEのウィンドウを操作する スクリーンキーボードの操作対象となっているウィンドウのウィンドウハンドルが判明している前提となりますが、ImmGetDefaultIMEWnd で対象ウィンドウに関連付けられた IME ウィンドウを取得し、IMC_SETOPENSTATUS で IME ウィンドウを閉じることにより IME をオフにできます。 参考: ### 2.対象のウィンドウに直接 WM_CHAR または WM_IME_CHAR を直接送信する これも操作対象となっているウィンドウのウィンドウハンドルが判明している前提となりますが、直接 PostMessage で WM_CHAR を送信するとうまいこと反応してくれることが多いと思います。WM_CHAR や WM_IME_CHAR を直接送信すると IME がメッセージを横取りすることはありません。 ただし、WM_CHAR を使用しない特殊なウィンドウには効果がありません。その場合、WM_KEYDOWN と WM_KEYUP を直接送信しても動作する可能性があります。これらのメッセージも IME には横取りされません。 ### 3.グローバルフックで IME を操作する 操作対象のプロセスにグローバルフックで DLL をインジェクションして IME の有効/無効を直接切り替えることでも対応可能です。この手法についてはコーディング量が上2つと比べて多いためあまりお勧めしません。