VB2005:Dialogを表示するとIMEが無効になる
ことがあることになることもある(T-T)。
えーとこれちょっとややこしいので、まず再現手順から。
- 「新しいプロジェクト」で「Windowsアプリケーション」を作成。
- Form1にTextBox×1、OpenFileDialog×1を載せる。
- TextBoxにフォーカスがある状態でOpenFileDialogを表示するようなロジックを組む。
- デバッグ実行。
- 半角/全角キーとかなんかそのへんでTextBoxを「ひらかな」入力状態に。
- OpenFileDialogを表示させて閉じる。
- TextBoxの入力状態が無効になる。
とりあえずその場しのぎでなんとかしようと思い。
TextBoxのImeModeChangedイベントでImeMode拾っといて、Dialog表示後に書き戻してやればいいかなーと。
そもそも半角/全角キーを切り替えてもTextBoxのImeModeが変化しねぇ!
どーいじってもNoControlのままじゃぁありませんか。
…んー、NoControl?
試しにTextBoxのImeModeの初期設定をOffにしてみると、無事ImeModeが実行時の操作に合わせて変化するように!ImeModeChangedイベントも発生するように!
あー、NoControlとOffの違いって、こーいぅところにあったわけですね。
てことは、DialogでIMEが無効になっちゃうのも、このへんが原因なのかもしれません。
では、TextBoxのImeModeをOffに設定し直して再チャレンジ。
- OpenFileDialogを表示させて閉じる。
- TextBoxの入力状態は「ひらかな」状態を保持。
おお、いい感じ。
- もう一度OpenFileDialogを表示させて閉じる。
- 以降、何度操作してもTextBoxの入力状態は無効になる。
…だめじゃん。
第一、Dialogが表示されたときにIMEがOffになっているのが気に食いません。
呼び出し元のTextBoxがHirakanaになってるんであれば、そこから呼ばれるDialogの初期状態もHirakanaになっていてほしいわけで。
いやいやいやちょっと待て。
どうしてDialogが「呼び出し元はTextBox」と判断すると決めてかかっているのだ私は。
どんなイベントからDialogを呼び出してもかまわないわけだから、TextBoxにフォーカスがあろうがなかろうがDialog側では気にしないよなー。
てことは、DialogはDialogの親コンテナからIMEの状態を引き継ぐのではないかと。
ってことは元凶はTextBoxではなくFormのImeModeなのではないかと。
確認してみたら確かにForm1のImeModeがNoControlに。
Form1のImeModeをOffにして実行したら、確かにImeの状態が保持されっぱなしに!DialLogもForm1のIME状態を引き継いで!Dialogを閉じても元のIME状態のままで!
くそー、ここらへんの関係がわかってなかっただけだったんだー。
ちなみに、TextBoxとかのImeModeは親コンテナからのアンビエントプロパティなので、初期設定のままいじらないでおくと、動作中は親コンテナ(ふつーはForm)のImeModeをそのまま引き継ぎながら動作します。つか、そのウィンドウでIMEの状態が保持されるってことですね。数値オンリーで強制的にIMEをDisableにしたいコントロールだけ別途設定するような使い方っすね。
一度個別設定したコントロールのImeModeを再び親コンテナと同期するように戻したい場合は、親コンテナと同じ設定にするのではなく、右クリックして「リセット」します。
親コンテナと同じ設定にしてもImeModeプロパティは太字のままで、これは「たまたま親コンテナと同じ設定が選択されているかもしれないけど、これはおいらのオリジナル設定なんだよー」と主張しているわけです。「リセット」すると太字が解除されて、コントロールを載せた時の初期値に戻るわけです。ImeModeはアンビエントプロパティなので、その初期値は「親コンテナの設定を引き継ぎ続ける」ってことになります。上記の例で言えば、実行時にTextBoxのImeModeを手動で変更すると、実際に変更されるのはFormであり、TextBoxはその瞬間瞬間のFormのImeModeに影響される、ってこってすね。
Formやコントロールの作成時初期値がNoControlなのがややこしくなっている原因ですが、IMEを積極的に使わない国のことも考えると、まぁ「影響されない」NoControlであることは妥当かなぁという気もします。
つことで今回の結論は、
- IMEの制御は原則Formで。
- IMEを考慮するなら作成時初期値はNoControlではなくOffで。