none
IMEの状態取得方法について RRS feed

  • 質問

  • ■質問内容

    IMEはALT+半角/全角キーや半角/全角キーで「あ」と「A」に表示が切り替わります。

    IME上でマウスを右クリックすると、ひらがな~直接入力まで変更が可能です。

    さらにIMEを利用するソフトウェア毎に設定を保持しておりますが、この状態「あ」・「A」などをAPIで知る方法、また変更する方法はございますか?

    過去ログを読んでプログラムを組んだのですが、行き詰まっておりますので教えて頂けると幸いです。


    ■組んでみたプログラム

            [DllImport("Imm32.dll")]
            public static extern IntPtr ImmGetContext(IntPtr hWnd);

            [DllImport("user32.dll")]
            public static extern IntPtr GetForegroundWindow();

            [DllImport("user32.dll")]
            public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

            private void timer1_Tick(object sender, EventArgs e)
            {
                int iActiveThreadID = 0;
                int iProcessID = 0;
                IntPtr hWnd;
                IntPtr lngInputContextHandle;

                //アクティブウィンドウのハンドルを取得
                hWnd = GetForegroundWindow();

                //アクティブウィンドウのプロセスIDを取得
                iActiveThreadID = GetWindowThreadProcessId(hWnd, out iProcessID);

                //アクティブウィンドウのコンテキストを取得
                lngInputContextHandle = ImmGetContext(hWnd);

                //ここから先が行き詰まっています。
                //lngInputContextHandleも値を表示すると0になってしまいます。

                //デバッグ表示
                Console.WriteLine(hWnd.ToString() + "," +  iActiveThreadID.ToString() + "," + lngInputContextHandle.ToString());

            }


    2016年6月26日 8:32

回答

  • // 私も自分で実装したことは無いので聞きかじりですが。

    まず、おそらく別プロセスのウィンドウに対するImmGetContextは必ず失敗します。対象プロセス内でImmGetContextする必要があります。

    対象プロセスにコードを注入する一般的な方法としてSetWindowsHookEx関数を使ったグローバルフックがあります。WH_KEYBOARDやWH_CALLWNDPROCでフックすれば、適切なメッセージ受信時にImmGetContextから色々操作できるようです。

    ただ、グローバルフックにはネイティブDLLが必要であり、.NETの諸言語では作成することができません。DLL部分だけでもC++などで作成する必要があります。

    一応、ImmGetContextのためのフックに関するリンクは貼っておきます。

    http://blog.mikage.to/mika/2005/07/windows_3805.html

    • 回答の候補に設定 星 睦美 2016年7月4日 2:35
    • 回答としてマーク akasatana3535 2016年7月17日 8:29
    • 回答としてマークされていない akasatana3535 2016年7月17日 8:29
    • 回答としてマーク akasatana3535 2016年7月17日 8:30
    2016年6月26日 8:50

すべての返信

  • // 私も自分で実装したことは無いので聞きかじりですが。

    まず、おそらく別プロセスのウィンドウに対するImmGetContextは必ず失敗します。対象プロセス内でImmGetContextする必要があります。

    対象プロセスにコードを注入する一般的な方法としてSetWindowsHookEx関数を使ったグローバルフックがあります。WH_KEYBOARDやWH_CALLWNDPROCでフックすれば、適切なメッセージ受信時にImmGetContextから色々操作できるようです。

    ただ、グローバルフックにはネイティブDLLが必要であり、.NETの諸言語では作成することができません。DLL部分だけでもC++などで作成する必要があります。

    一応、ImmGetContextのためのフックに関するリンクは貼っておきます。

    http://blog.mikage.to/mika/2005/07/windows_3805.html

    • 回答の候補に設定 星 睦美 2016年7月4日 2:35
    • 回答としてマーク akasatana3535 2016年7月17日 8:29
    • 回答としてマークされていない akasatana3535 2016年7月17日 8:29
    • 回答としてマーク akasatana3535 2016年7月17日 8:30
    2016年6月26日 8:50
  • 返信が遅くなり申し訳ありません。

    外部DLLのフックを試してみます。

    ありがとうございました!

    2016年7月17日 8:30