WinForms で IME が効かなくなる
◆ 特定の処理をしてウィンドウを開くとすでにあったウィンドウが裏側に行く
◆ そのウィンドウのテキストボックスで IME を有効にできない
◆ そのウィンドウのテキストボックスで IME を有効にできない
関連:
WinForms アプリで IME が効かなくなることがある
WinForms アプリで IME が効かなくなることがある (続き)
WinForms でウィンドウが勝手に裏側に移動する
確実に再現できる手順が見つかったので 関係なさそうなところを削っては再現することを確認しながら できるだけシンプルな再現できるコードを作ります
その結果 ライブラリ依存なしの WinForms 単体で簡単に再現できることがわかったのですが……
なぜか別の PC では再現しません
もう少し調べると原因は他の起動中アプリケーションで エクセルなどが開かれてると関係ないアプリケーションの IME にも影響を与えてました
IME が使えなくなる方の PC はエクセルを起動したままでした
これまでも Excel2013 以降では なぜかエクセルを開いてると別アプリが不安定になることはあったので なんかそういうものだと思ってましたが IME が使えない原因がエクセルとは思いませんでした
エクセルを閉じると無事その PC でも再現しなくなりました
原因となるアプリケーションはエクセルだけではなく 私の環境だと PDF Viewer でも再現しました
しかし 機能を削っていく前の状態では複数の PC で再現することは確認していました
エクセルとか開いてない PC もあったはずです
もう一度調べると完全な状態のものはエクセルなど他のソフトを閉じていても再現しました
エクセルなどを開いてない状態で また機能削っていく作業は辛いのでここで一旦中断
その後 またやってみると 再現する状況ではウィンドウが裏側に移動してしまう問題も起きていました
それが起きないときは IME が効かない状態にもなってません
ただ面倒なのでやる気が出ずに 2 回目中断
この記事はその続きです
別の PC で 1 から作っても再現しましたし ビルドした exe を Windows Sandbox に入れて実行しても再現しました
.NET Framework の WinForms でバージョンはとりあえず 4.6.1
バージョン依存じゃなくて他のバージョンでも再現しました
まず Form を 4 つ (Form1 ~ Form4) と UserControl を 2 つ (UserControl1, UserConrol2) を新規作成します
UserControl1 をパネルに追加してます
Load や FormClosing でよくわからないことをしてますが ライブラリや共通処理で実行されていたものから 無くても再現する部分を消していった結果です
ただし UserControl1 の代わりに UserConrol2 にします
VisualStudio のデバッグ実行なら VisualStudio のウィンドウがあるのでなくても大丈夫です
起動すると Form1 が開かれるのでボタンをクリックします
Form2 が開いたら UserControl1 のボタンがあるので それをクリックします
Form3 が開かれますが この時点で Form1 がエクスプローラや VisualStudio のウィンドウの裏側に移動します
エクスプローラなどが全画面表示だと見えなくなってるはずです
Form3 と Form2 を閉じて Form1 をタスクバーから選んでウィンドウを前面に出します
テキストボックスにフォーカスして IME を切り替えようとすると 切り替えできません
このコードをいじって 再現しなくなるかつ元コードにも反映できるものを探すしかなさそうです
WinForms アプリで IME が効かなくなることがある
WinForms アプリで IME が効かなくなることがある (続き)
WinForms でウィンドウが勝手に裏側に移動する
ここまで
WinForms アプリでなぜか IME が効かなくなることがあったので調べてみました確実に再現できる手順が見つかったので 関係なさそうなところを削っては再現することを確認しながら できるだけシンプルな再現できるコードを作ります
その結果 ライブラリ依存なしの WinForms 単体で簡単に再現できることがわかったのですが……
なぜか別の PC では再現しません
もう少し調べると原因は他の起動中アプリケーションで エクセルなどが開かれてると関係ないアプリケーションの IME にも影響を与えてました
IME が使えなくなる方の PC はエクセルを起動したままでした
これまでも Excel2013 以降では なぜかエクセルを開いてると別アプリが不安定になることはあったので なんかそういうものだと思ってましたが IME が使えない原因がエクセルとは思いませんでした
エクセルを閉じると無事その PC でも再現しなくなりました
原因となるアプリケーションはエクセルだけではなく 私の環境だと PDF Viewer でも再現しました
しかし 機能を削っていく前の状態では複数の PC で再現することは確認していました
エクセルとか開いてない PC もあったはずです
もう一度調べると完全な状態のものはエクセルなど他のソフトを閉じていても再現しました
エクセルなどを開いてない状態で また機能削っていく作業は辛いのでここで一旦中断
その後 またやってみると 再現する状況ではウィンドウが裏側に移動してしまう問題も起きていました
それが起きないときは IME が効かない状態にもなってません
ただ面倒なのでやる気が出ずに 2 回目中断
この記事はその続きです
確実に再現させれた
やらないといいつつも暇だし なんか気になるしと続きをやってしまって 今度は無事どの PC でも再現できるコードになりました別の PC で 1 から作っても再現しましたし ビルドした exe を Windows Sandbox に入れて実行しても再現しました
作り方
新規にプロジェクトを作ります.NET Framework の WinForms でバージョンはとりあえず 4.6.1
バージョン依存じゃなくて他のバージョンでも再現しました
まず Form を 4 つ (Form1 ~ Form4) と UserControl を 2 つ (UserControl1, UserConrol2) を新規作成します
Form1
テキストボックスとボタンを配置して ボタンをクリックすると Form2 を開くコードを書きます private void button1_Click(object sender, EventArgs e)
{
new Form2().Show();
}
Form2
パネルを配置して コンストラクタを下のように拡張します public Form2()
{
InitializeComponent();
var control = new UserControl1();
control.Visible = false;
this.panel1.Controls.Add(control);
this.Load += (sender, e) =>
{
var form = new Form4();
form.Show(this);
form.Refresh();
control.Enabled = true;
control.Visible = true;
form.Close();
};
this.FormClosing += (sender, e) =>
{
this.panel1.Controls.Remove(control);
control.Dispose();
};
}
UserControl1 をパネルに追加してます
Load や FormClosing でよくわからないことをしてますが ライブラリや共通処理で実行されていたものから 無くても再現する部分を消していった結果です
UserControl1
ボタンを配置してクリックすると Form3 をダイアログ表示します private void button1_Click(object sender, EventArgs e)
{
new Form3().ShowDialog(this.ParentForm);
}
Form3
Form2 と同じ変更を加えますただし UserControl1 の代わりに UserConrol2 にします
UserConrol2
変更なしの初期状態ですForm4
変更なしの初期状態です手順
適当にエクスプローラなどを開いておきますVisualStudio のデバッグ実行なら VisualStudio のウィンドウがあるのでなくても大丈夫です
起動すると Form1 が開かれるのでボタンをクリックします
Form2 が開いたら UserControl1 のボタンがあるので それをクリックします
Form3 が開かれますが この時点で Form1 がエクスプローラや VisualStudio のウィンドウの裏側に移動します
エクスプローラなどが全画面表示だと見えなくなってるはずです
Form3 と Form2 を閉じて Form1 をタスクバーから選んでウィンドウを前面に出します
テキストボックスにフォーカスして IME を切り替えようとすると 切り替えできません
対処
シンプルなコードで再現できたものの これらの処理はライブラリや共通処理として実際に必要だから行われているわけで 消したら動くようになる部分を消して対処ともいかないのですよねこのコードをいじって 再現しなくなるかつ元コードにも反映できるものを探すしかなさそうです