WPF で TextBox 毎にフォーカス時の IME の変換モードを設定するコードです。
かなり稀だとは思いますが、要件として実際存在するそうです。
まず、普通に XAMLで設定する XAML コードです。
普通に、ドキュメントに載っているマニュアル通りの方法です。
<StackPanel> <!-- IME を無効にする --> <TextBox InputMethod.IsInputMethodEnabled="False" /> <!-- ひらがな --> <TextBox InputMethod.PreferredImeState="On" InputMethod.PreferredImeConversionMode="FullShape,Native"/> <!-- 全角カタカナ --> <TextBox InputMethod.PreferredImeState="On" InputMethod.PreferredImeConversionMode="Katakana,FullShape"/> <!-- 全角英数 --> <TextBox InputMethod.PreferredImeState="On" InputMethod.PreferredImeConversionMode="Alphanumeric,FullShape"/> <!-- 半角カタカナ --> <TextBox InputMethod.PreferredImeState="On" InputMethod.PreferredImeConversionMode="Katakana,Native"/> <!-- 半角英数 --> <TextBox InputMethod.PreferredImeState="On" InputMethod.PreferredImeConversionMode="Alphanumeric"/> </StackPanel>
これが正しい方法だと思うのですが、実際に動作させると動作に問題があります。
全角英数の次に全角カタカナの項目に移動した場合に IME のモードが、全角カタカナに変更されません。
発生条件としては、上記の通り、全角英数の次に全角カタカナの項目に移動する場合で、この組み合わせでのみ発生します。
この問題を回避するコードを書いてみました。軽く動かしたところは上手く動いてくれています。
TextBox を拡張した独自コントロールクラスを作るアプローチで挑んでみました。
要点は、GotFocus イベントと LostFocus の処理です。
全角英数項目の LostFocus で IME を別のものに一度変更し、全角カタカナ項目の GotFocus で非同期処理で IME を全角カタカナに変更します。
LostFocus、GotFocus、非同期処理、の3つのどれか一つがかけても上手く行きませんでした。
// IME の設定の種類 internal enum ImeMode { DoNotCare, Disabled, Hiragana, FullKana, FullAlphaNum, HalfKana, HalfAlphaNum } // IME を指定可能な TextBox internal class ImeModeTextBox : TextBox { // IME の設定の種類 public ImeMode ImeMode { get; set; } = ImeMode.DoNotCare; // コンストラクタ public ImeModeTextBox() { // 初期化 this.Initialized += (sender, e) => { switch (this.ImeMode) { case ImeMode.Disabled: // Disabled InputMethod.SetIsInputMethodEnabled(this, false); break; case ImeMode.Hiragana: // 全角ひらがな InputMethod.SetPreferredImeState(this, InputMethodState.On); InputMethod.SetPreferredImeConversionMode(this, ImeConversionModeValues.FullShape | ImeConversionModeValues.Native); break; case ImeMode.FullKana: // 全角カナ InputMethod.SetPreferredImeState(this, InputMethodState.On); InputMethod.SetPreferredImeConversionMode(this, ImeConversionModeValues.Katakana | ImeConversionModeValues.FullShape); break; case ImeMode.FullAlphaNum: // 全角英数 InputMethod.SetPreferredImeState(this, InputMethodState.On); InputMethod.SetPreferredImeConversionMode(this, ImeConversionModeValues.Alphanumeric | ImeConversionModeValues.FullShape); break; case ImeMode.HalfKana: // 半角カナ InputMethod.SetPreferredImeState(this, InputMethodState.On); InputMethod.SetPreferredImeConversionMode(this, ImeConversionModeValues.Katakana | ImeConversionModeValues.Native); break; case ImeMode.HalfAlphaNum: // 半角英数 InputMethod.SetPreferredImeState(this, InputMethodState.On); InputMethod.SetPreferredImeConversionMode(this, ImeConversionModeValues.Alphanumeric); break; } // 全角英数項目 -> 全角カナ項目 のフォーカス移動時の問題を回避 // 全角カナ項目側の処理 if (this.ImeMode == ImeMode.FullKana) { this.GotFocus += async (sender_, e_) => { await Dispatcher.InvokeAsync(() => { InputMethod.Current.ImeConversionMode = ImeConversionModeValues.Katakana | ImeConversionModeValues.FullShape; }); }; }; // 全角英数項目 -> 全角カナ項目 のフォーカス移動時の問題を回避 // 全角英数項目側の処理 if (this.ImeMode == ImeMode.FullAlphaNum) { this.LostFocus += (sender_, e_) => { InputMethod.Current.ImeConversionMode = ImeConversionModeValues.Alphanumeric; }; }; }; } }
この拡張 TextBox コントロールを使った XAML です。
<Window x:Class="WpfApplication.Window" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApplication" mc:Ignorable="d" Title="Window" Height="300" Width="300"> <StackPanel> <!-- IME を無効にする --> <local:ImeModeTextBox ImeMode="Disabled"/> <!-- ひらがな --> <local:ImeModeTextBox ImeMode="Hiragana"/> <!-- 全角カタカナ --> <local:ImeModeTextBox ImeMode="FullKana"/> <!-- 全角英数 --> <local:ImeModeTextBox ImeMode="FullAlphaNum"/> <!-- 半角カタカナ --> <local:ImeModeTextBox ImeMode="HalfKana"/> <!-- 半角英数 --> <local:ImeModeTextBox ImeMode="HalfAlphaNum"/> </StackPanel> </Window>
これで上手く動いてくれました。