Windows TerminalでのIMEエラー
Windows Terminalを立ち上げた直後にIMEが半角英数になる.

同様の現象は他の環境でもあるらしい.
環境
- Windows 11 22H2
- Windows Terminal 1.16.10262.0
- PowerShell 7.3.2
現状の対応策
- Microsoft IMEを使用する
でもGoogle IME使いたい...
pwsh起動時の構成でIMEを変更する
基本的にpwshしか使用しないため ,pwshのスクリプトでIMEを変更できれば対処はできそう.
IMEの状態を取得し,OFFならばONに変更するpwshスクリプトを以下に示す.
set-variable -name WM_IME_CONTROL -value 0x0283 -option constant
set-variable -name IMC_GETOPENSTATUS -value 0x05 -option constant
set-variable -name IMC_SETOPENSTATUS -value 0x06 -option constant
$ime_code = @"
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
[DllImport("imm32.dll")]
public static extern IntPtr ImmGetDefaultIMEWnd(IntPtr hWnd);
"@
if(!('Win32.Ime' -as [type])) {
Add-Type $ime_code -Name Ime -Namespace Win32
}
$window_handle = [Win32.Ime]::GetForegroundWindow()
echo $window_handle
$ime_handle = [Win32.Ime]::ImmGetDefaultIMEWnd($window_handle)
echo $ime_handle
$enableIME = ([Win32.Ime]::SendMessage($ime_handle, $WM_IME_CONTROL, $IMC_GETOPENSTATUS, 0) -ne 0)
if (!$enableIME) {
echo "IME turn to ON"
$null = [Win32.Ime]::SendMessage($ime_handle, $WM_IME_CONTROL, $IMC_SETOPENSTATUS, 1)
}
Win32APIをPowershellから呼び出せるようにし,GetForegroundWindow()でアクティブウィンドウのウィンドウハンドルを取得し,ImmGetDefaultIMEWnd()でIMEのウィンドウハンドルを取得する.
そのウィンドウハンドルに対して,IMEの状態を取得・変更する命令を送っている.
参考文献
PowerShellでコマンド実行したらIMEをオフにする
C#でIMEの変換モードを監視・変更する
WM_IME_CONTROL メッセージ
同様に以下のようにIMEの変換モードの情報を取得できる.
set-variable -name IMC_GETCONVERSIONMODE -value 0x01 -option constant
[Win32.Ime]::SendMessage($ime_handle, $WM_IME_CONTROL, $IMC_GETCONVERSIONMODE, 0);
Google IMEとMicrosoft IMEでget_conversion_mode.ps1を動かしたときの各変換モードとの対応表
| 変換モード | Google IME | Microsoft IME |
|---|---|---|
| ひらがな | 25(0x19) | 9(0x09) |
| 全角カタカナ | 27(0x1B) | 11(0x0B) |
| 全角英数 | 24(0x18) | 8(0x08) |
| 半角カタカナ | 19(0x13) | 3(0x03) |
| 半角英数 | 16(0x10) | 0(0x00) |
うーん...Google IMEとMicrosoft IMEで値が変わってもいいのか?共通じゃないと色々不具合が出てきそうではあるが...
16進表記にすると上位4bitが0b0001なのがGoogle IMEだな...
imm.hを覗いてみるとと以下のように定義されていた.
#define IME_CMODE_ALPHANUMERIC 0x0000
#define IME_CMODE_NATIVE 0x0001
#define IME_CMODE_CHINESE IME_CMODE_NATIVE
#define IME_CMODE_HANGEUL IME_CMODE_NATIVE
#define IME_CMODE_JAPANESE IME_CMODE_NATIVE
#define IME_CMODE_KATAKANA 0x0002 // only effect under IME_CMODE_NATIVE
#define IME_CMODE_LANGUAGE 0x0003
#define IME_CMODE_FULLSHAPE 0x0008
#define IME_CMODE_ROMAN 0x0010
Google IMEなら以下のような対応になりそう.
| 変換モード | 2進表記 | 対応 |
|---|---|---|
| ひらがな | 0b0001_1001 | IME_CMODE_ROMAN or IME_CMODE_FULLSHAPE or IME_CMODE_JAPANESE |
| 全角カタカナ | 0b0001_1011 | IME_CMODE_ROMAN or IME_CMODE_FULLSHAPE or IME_CMODE_KATAKANA or IME_CMODE_JAPANESE |
| 全角英数 | 0b0001_1000 | IME_CMODE_ROMAN or IME_CMODE_FULLSHAPE |
| 半角カタカナ | 0b0001_0011 | IME_CMODE_ROMAN or IME_CMODE_KATAKANA or IME_CMODE_JAPANESE |
| 半角英数 | 0b0001_0000 | IME_CMODE_ROMAN |
あれ?Microsoft IMEでかな入力でもローマ字入力でもIME_CMODE_ROMANが変化しないのはなんでだろ?
変換モードの変更は以下のように記述できる.
set-variable -name IMC_SETCONVERSIONMODE -value 0x02 -option constant
$mode = 0x19
$null = [Win32.Ime]::SendMessage($ime_handle, $WM_IME_CONTROL, $IMC_SETCONVERSIONMODE, $mode);
変換先はひらがな(0x19)に設定している.
うーん...半角英数→スクリプト実行→変換モード変化なし...
ただし,内部的には変更されてるんだよな...

set-variable -name WM_IME_CONTROL -value 0x0283 -option constant
set-variable -name IMC_GETCONVERSIONMODE -value 0x01 -option constant
set-variable -name IMC_SETCONVERSIONMODE -value 0x02 -option constant
set-variable -name IMC_GETOPENSTATUS -value 0x05 -option constant
set-variable -name IMC_SETOPENSTATUS -value 0x06 -option constant
$ime_code = @"
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
[DllImport("imm32.dll")]
public static extern IntPtr ImmGetDefaultIMEWnd(IntPtr hWnd);
"@
if(!('Win32.Ime' -as [type])) {
Add-Type $ime_code -Name Ime -Namespace Win32
}
$window_handle = [Win32.Ime]::GetForegroundWindow()
$ime_handle = [Win32.Ime]::ImmGetDefaultIMEWnd($window_handle)
$mode = [Win32.Ime]::SendMessage($ime_handle, $WM_IME_CONTROL, $IMC_GETCONVERSIONMODE, 0);
Write-Output "変更前:$mode"
$null = [Win32.Ime]::SendMessage($ime_handle, $WM_IME_CONTROL, $IMC_SETCONVERSIONMODE, $Args[0]);
$mode2 = [Win32.Ime]::SendMessage($ime_handle, $WM_IME_CONTROL, $IMC_GETCONVERSIONMODE, 0);
Write-Output "変更後:$mode2"
MicrosoftIMEに変えて実行したらうまく行った.
ひらがな→スクリプト実行→半角カタカナ
半角カタカナ→スクリプト実行→ひらがな

GoogleIMEのオープンソース版であるMozcでも試してみる.
書いてある手順に従って進める.
Build
> git clone https://github.com/google/mozc.git -b master --single-branch --recursive
> cd mozc/src/third_party
> git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
> python3 -m pip install six
x64_x86 Cross Tools Command Prompt for VS 2019を立ち上げ,以降はその中で作業する.
> cd **/mozc/src
> python3 build_mozc.py gyp --noqt --msvs_version=2019
> python3 build_mozc.py build -c Release package
いくつかエラーが出るので場当たり的に対処(詳細は後々追記します).
> python3 build_mozc.py clean
> python3 build_mozc.py gyp --noqt --msvs_version=2019
> python3 build_mozc.py build -c Release package
無事ビルドできた.
Install
生成された以下のファイルをC:\Program Files (x86)\Mozcに入れる.
- mozc\src\out_win\Release\mozc_broker32.exe
- mozc\src\out_win\Release_x64\mozc_broker64.exe
- mozc\src\out_win\Release\mozc_cache_service.exe
- mozc\src\out_win\Release\mozc_renderer.exe
- mozc\src\out_win\Release\mozc_server.exe
- mozc\src\out_win\Release\mozc_tool.exe
- mozc\src\out_win\Release\mozc_ja_tip32.dll
- mozc\src\out_win\Release_x64\mozc_ja_tip64.dll
その後,管理者権限でターミナルを開き,以下の内容を実行する.
$ regsvr32 "C:\Program Files (x86)\Mozc\mozc_ja_tip32.dll"
$ regsvr32 "C:\Program Files (x86)\Mozc\mozc_ja_tip64.dll"
何事も無ければ無事にMozcがIMEの欄に追加されているはず
MozcでもIMC_SETCONVERSIONMODEが効かない...