C#でIMEの変換モードを監視・変更する

ときどきＩＭＥが意図せずに全角英数モードになってたりして鬱陶しい（※）ので、
強制的にひらがなモードに変更するコードを書いてみた。
（このコードで問題ないかは自信ない）

// ※：無変換キーは押してないはずなんだけど・・・

```csharp

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace TestIme
{
    public class Form1 : Form
    {
        public Form1()
        {
            Timer timer = new Timer();
            timer.Interval = 1000;
            timer.Tick += timer1_Tick;
            timer.Start();
        }

        [DllImport("User32.dll")]
        static extern int SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
        [DllImport("imm32.dll")]
        static extern IntPtr ImmGetDefaultIMEWnd(IntPtr hWnd);
        [DllImport("user32.dll")]
        static extern bool GetGUIThreadInfo(uint dwthreadid, ref GUITHREADINFO lpguithreadinfo);

        [StructLayout(LayoutKind.Sequential)]
        public struct GUITHREADINFO
        {
            public int cbSize;
            public int flags;
            public IntPtr hwndActive;
            public IntPtr hwndFocus;
            public IntPtr hwndCapture;
            public IntPtr hwndMenuOwner;
            public IntPtr hwndMoveSize;
            public IntPtr hwndCaret;
            public System.Drawing.Rectangle rcCaret;
        }
        
        const int WM_IME_CONTROL = 0x283;
        const int IMC_GETCONVERSIONMODE = 1;
        const int IMC_SETCONVERSIONMODE = 2;
        const int IMC_GETOPENSTATUS = 5;
        const int IMC_SETOPENSTATUS = 6;
        
        const int IME_CMODE_NATIVE    =  1;
        const int IME_CMODE_KATAKANA  =  2;
        const int IME_CMODE_FULLSHAPE =  8;
        const int IME_CMODE_ROMAN     = 16;
        
        const int CMode_HankakuKana = IME_CMODE_ROMAN | IME_CMODE_KATAKANA | IME_CMODE_NATIVE;
        const int CMode_ZenkakuEisu = IME_CMODE_ROMAN | IME_CMODE_FULLSHAPE;
        const int CMode_Hiragana    = IME_CMODE_ROMAN | IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE;
        const int CMode_ZenkakuKana = IME_CMODE_ROMAN | IME_CMODE_FULLSHAPE | IME_CMODE_KATAKANA | IME_CMODE_NATIVE;
        // 実験してみた結果
        // 19 :カ 半角カナ                     0001 0011
        // 24 :Ａ 全角英数                     0001 1000
        // 25 :あ ひらがな（漢字変換モード）   0001 1001
        // 27 :   全角カナ                     0001 1011
        
        // 半角カナ/全角英数/カタカナ モードを強制的に「ひらがな」モードに変更する
        private void timer1_Tick(object sender, EventArgs e)
        {
            //IME状態の取得
            GUITHREADINFO gti = new GUITHREADINFO();
            gti.cbSize = Marshal.SizeOf(gti);
            
            if ( !GetGUIThreadInfo(0, ref gti) ) {
                Console.WriteLine("GetGUIThreadInfo failed");
                throw new System.ComponentModel.Win32Exception(); // 2019.8.21追記:まれにここに来てしまう場合あるようなので throw せずに return; させたほうがよいかも
            }
            IntPtr imwd = ImmGetDefaultIMEWnd(gti.hwndFocus);

            int  imeConvMode = SendMessage(imwd, WM_IME_CONTROL, (IntPtr)IMC_GETCONVERSIONMODE, IntPtr.Zero);
            bool imeEnabled = (SendMessage(imwd, WM_IME_CONTROL, (IntPtr)IMC_GETOPENSTATUS, IntPtr.Zero) != 0);

            Console.WriteLine(imeEnabled.ToString() + " status code:"+imeConvMode.ToString());
            
            if ( imeEnabled ) {
                switch ( imeConvMode ) {
                case CMode_Hiragana:
                    /* Nothing to do */
                    break;
                case CMode_HankakuKana: /* through */
                case CMode_ZenkakuEisu: /* through */
                case CMode_ZenkakuKana:
                    SendMessage(imwd, WM_IME_CONTROL, (IntPtr)IMC_SETCONVERSIONMODE, (IntPtr)CMode_Hiragana); // ひらがなモードに設定
                    break;
                default:
                    /* Nothing to do */
                    /* 環境によっては上のcaseをやめてここに飛ばしたほうがよいかも */
                    break;
                }
            }/* else 無変換(半角英数) */
        }
        
        [STAThread]
        static void Main(){
            Application.Run(new Form1());
        }
    }
}

```

2020.1.1追記：間違っている箇所がある。`SendMessage`の戻り値の型は`int`ではなく`IntPtr`が正。

# おまけ - Windows10で画面中央に表示される「あ」/「A」をオフする

+ [Windows 10でIME切り替え時の「あ」や「A」の表示をオフにする](https://www.atmarkit.co.jp/ait/articles/1902/12/news024.html)
+ [画面中央に A と表示される。 - Qiita](https://qiita.com/mkam/items/c9a655e2dfb323a5eaf2) (PowerShellによるレジストリ設定)