15
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-08-04

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

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


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 :A 全角英数                     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」をオフする

15
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?