◆ 特定の処理をしてウィンドウを開くとすでにあったウィンドウが裏側に行く
◆ そのウィンドウのテキストボックスで 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 を切り替えようとすると 切り替えできません

対処

シンプルなコードで再現できたものの これらの処理はライブラリや共通処理として実際に必要だから行われているわけで 消したら動くようになる部分を消して対処ともいかないのですよね

このコードをいじって 再現しなくなるかつ元コードにも反映できるものを探すしかなさそうです