MS_IMEControl - NetDevInfraWGinOSSConsortium/NetDevInfraWiki GitHub Wiki

IME制御

概要

IME 制御関係のトピック

ブラウザ

ime-mode

Internet Explorer と Firefox 3 以降で ime-mode プロパティで制御可能。

古いので、モダンブラウザでは IME 制御しないほうが良い。

補足(ime-mode は現在ほぼ死んでいる): 原文の「モダンブラウザでは
IME 制御しないほうが良い」という判断は、その後さらに正しくなった

ブラウザ ime-mode の対応
Internet Explorer 対応(IE 自体が 2022 年に終了
Firefox ime-mode: disabled のみ残存(他は無効)
Chrome / Edge / Safari 一度も実装されていない
【現在の結論】
   ・Chromium 系が大半を占める現在、ime-mode は【ほぼ効かない】
   ・仕様上も【非標準】(MDN も deprecated 扱い)
   ・「IE と Firefox だけ動く」= 挙動が環境で割れる
      → かえって【利用者を混乱させる】

とはいえ「電話番号欄で全角入力されて困る」という
業務上の要求は消えていない
。現在の解を次に示す。

JavaScriptで入力チェックや自動入力を行う。

補足(現在の実務的な解): **「入力させない」から
「入力された後に直す・検証する」**へ移ったのが現在である。

① 入力後に正規化する(最も現実的)

// 全角数字・記号を半角へ(電話番号、郵便番号、金額)
const toHalf = s => s.replace(/[-]/g,
    c => String.fromCharCode(c.charCodeAt(0) - 0xFEE0));

input.addEventListener('blur', e => { e.target.value = toHalf(e.target.value).trim(); });
【なぜ blur(フォーカスが外れた時)か】
   input イベントで即座に変換すると、
   【IME の変換中に文字が書き換わって入力が壊れる】★
     → 未確定状態を避けるため、確定後・離脱時に行う
     → 詳しくは [IME](MS_IME) の compositionstart / compositionend

② サーバ側で必ず検証する

// クライアント側の制御は「親切」であって「保証」ではない
[RegularExpression(@"^\d{2,4}-?\d{2,4}-?\d{3,4}$",
    ErrorMessage = "電話番号を半角数字で入力してください")]
public string Tel { get; set; }

inputmode でソフトウェア キーボードを誘導する(後述)

④ 自動カナ入力

原文の jquery.autoKana.js の系統は現在も有効な発想である
(氏名を入力すると、ふりがな欄に自動で入る)。

【仕組み】
   IME の変換前の【ローマ字・かな入力の打鍵】を拾い、
   ふりがな欄に転記する
     → compositionstart ~ compositionend の間の入力を見る

【注意点】
   ・【コピー&ペーストでは動かない】(打鍵がないため)
   ・スマートフォンの IME では拾えないことが多い ★
   ・したがって【あくまで補助】。ふりがなは必須項目として
     利用者が直せるようにしておく

現在は jQuery 非依存の後継(vanilla-autokana 等)がある。

inputmode

HTML5.1 の仕様として追加されているが、対応状況がまだらしい(2017/4)。

補足(inputmode は現在は主要ブラウザで使える): 原文が
「対応状況がまだらしい(2017/4)」と記録した時点から、
状況は改善した

【現在(Chrome / Edge / Safari / Firefox いずれも対応)】
   <input inputmode="numeric">   数字キーパッドを出す
   <input inputmode="tel">       電話番号用キーパッド
   <input inputmode="email">     @ が押しやすいキーボード
   <input inputmode="url">
   <input inputmode="decimal">   小数点付きの数値
   <input inputmode="search">
   <input inputmode="none">      ソフトキーボードを出さない

重要な限界:

・inputmode が効くのは【ソフトウェア キーボード(スマホ・タブレット)】
・【デスクトップの IME には影響しない】★
   → 「PC で全角になってしまう」問題は解決しない
・あくまで【入力しやすくする】ためのもので、
  入力される値を制限するものではない

type との使い分け:

<!-- ✗ 郵便番号に type="number" は不適切 -->
<!--    先頭 0 が消える、スピナーが出る、e が入力できる -->
<input type="number" name="zip">

<!-- ○ type は text、キーボードだけ数字にする -->
<input type="text" inputmode="numeric" pattern="\d{7}"
       autocomplete="postal-code" name="zip">

autocomplete 属性も併せて指定すると、
ブラウザの自動入力が効いて利用者の手間が減る
nametelemailpostal-codeaddress-level1 等)。

デスクトップ

TextBox.IMEMode を使用して、以下のように制御できる。

this.TextBox1.ImeMode = ImeMode.Hiragana;

補足(ImeMode はデスクトップでは今も有効): ブラウザと違い、
Windows FormsImeMode は現在も正しく動く
OS の IME を直接制御できるためである。

動作
ImeMode.NoControl 既定。制御しない(親から継承)
ImeMode.Hiragana ひらがな入力(氏名、住所)
ImeMode.Katakana 全角カタカナ
ImeMode.KatakanaHalf 半角カタカナ
ImeMode.Disable IME を無効にする(数値、コード)
ImeMode.Off IME をオフ(利用者が再度オンにできる)
ImeMode.Alpha 半角英数
【Off と Disable の違い】★ 実務で効く
   Off     … IME をオフにするが、利用者が【変換キーでオンにできる】
   Disable … IME 自体を【無効化】。利用者はオンにできない

 → 「絶対に半角しか受けない」欄は Disable
 → 「通常は半角だが、必要なら切り替えたい」欄は Off

フォーム全体に一括で設定することもできる。

// Form の ImeMode を設定すると、NoControl の子に継承される
this.ImeMode = ImeMode.Disable;
this.txtName.ImeMode = ImeMode.Hiragana;   // 氏名欄だけ個別に

注意点:

・ReadOnly / Enabled = false のコントロールでは効かない
・ComboBox の DropDownList スタイルでは意味を持たない
・【日本語版以外の Windows】では、IME が無いため無視される
   → 国際化する場合は [国際化対応項目](MS_InternationalizationItems) も参照

WPF の IME 制御(XAMLの書き方(2)

補足(WPF での書き方): WPF は
System.Windows.Input.InputMethod 添付プロパティで制御する
ImeMode という名前ではない)。

<!-- ひらがな入力にする -->
<TextBox InputMethod.PreferredImeState="On"
         InputMethod.PreferredImeConversionMode="Native,FullShape" />

<!-- IME を無効にする -->
<TextBox InputMethod.IsInputMethodEnabled="False" />
プロパティ 意味
IsInputMethodEnabled IME 自体の有効・無効ImeMode.Disable 相当)
PreferredImeState On / Off / DoNotCare
PreferredImeConversionMode 変換モードNative = かな、Alphanumeric = 英数、FullShape = 全角)
【対応表】
   ImeMode.Hiragana → PreferredImeState="On"
                      PreferredImeConversionMode="Native,FullShape"
   ImeMode.Disable  → IsInputMethodEnabled="False"
   ImeMode.Alpha    → PreferredImeConversionMode="Alphanumeric,HalfShape"

WinUI 3 / .NET MAUI でも同様の考え方だが、
プラットフォームごとに API が異なる。

別スレッドでウィンドウを実行した場合、IME制御がおかしくなる。

ウィンドウ・システム を参照)

補足(原因): この現象は、IME がスレッドに紐づいているために起きる。

【Win32 の前提】
   ・ウィンドウは【作成したスレッド】に属する(スレッド アフィニティ)
   ・メッセージ ループもそのスレッドで回る
   ・【IME のコンテキスト(HIMC)もスレッド単位】★

【別スレッドでウィンドウを作ると】
   ・そのスレッドの IME 状態は、メイン スレッドと独立になる
   ・フォーカス移動時の IME の引き継ぎが期待通りにならない
   ・「IME がオンにならない」「変換候補が出ない」等が起きる

対処の原則:

① 【UI は必ず 1 つのスレッド(UI スレッド)で作る】★
     → 別スレッドでウィンドウを作らない
② 時間のかかる処理は別スレッドへ、UI 更新は UI スレッドへ戻す
     Windows Forms: Control.Invoke / BeginInvoke
     WPF:           Dispatcher.Invoke / InvokeAsync
     現在:          【async/await】が最も素直
// ○ async/await なら、await の後は自動的に UI スレッドに戻る
private async void btnLoad_Click(object sender, EventArgs e)
{
    var data = await _service.LoadAsync();   // 別スレッドで実行
    grid.DataSource = data;                  // ← UI スレッドに戻っている
}

詳細は ウィンドウ・システム および
async/await を参照。

参考

Microsoft Learn

MDN


Tags: 移行, Windows, その他、開発の色々

⚠️ **GitHub.com Fallback** ⚠️