拙作のVaNTを仕事でずっと使っていますが、以前から気になっていた問題を修正したv0.10.2をリリースしました。VaNTの[ヘルプ]>[アップデートを確認]から最新版に更新してください。
初めてVaNTをインストールする方は、サイドメニューのダウンロードリンクからどうぞ。
問題
VaNTが隠れている状態でホットキーを使って呼び出した際、最前面にVaNTが表示されてもVaNTの中にフォーカスが入らず、何かキーを入力しても直前まで開いていたウィンドウ内に入力されてしまうという問題です。
この問題が発生するときは、タスクバーのVaNTのアイコンが以下のように点滅した状態になっていました。
原因
この問題はずっと原因不明だったのですが、
こちらの奮闘記録を参考にさせていただき、根本的な原因は不明ですがWindows APIのSetForegroundWindowが失敗する場合があるということが分かりました。
上記の記事では、このSetForegroundWindowを3回連続で呼んで成功したら終了というコードにして対応されていました。
VaNTでも真似をしてみたのですが、私の環境では3回では全然足りなかったので、とりあえず100回くらい連続実行するとどこかで成功するという感じでした。この回数は環境ごとに調整できたほうが良いかもしれないので、設定ファイルで持つようにしてデフォルト値を1000にしておきました。
結局対応に必要なコードは以下になりました。
// 外部プロセスのメイン・ウィンドウを起動するためのWin32 API
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
/// <summary>
/// Windowフォームアクティブ化処理
/// </summary>
/// <param name="handle">フォームハンドル</param>
/// <returns>true : 成功 / false : 失敗</returns>
private static bool ForceActive(IntPtr handle)
{
bool isSuccess = false;
// ウィンドウをフォアグラウンドに持ってくる
isSuccess = SetForegroundWindow(handle);
return isSuccess;
}
上記を定義しておき、実際にホットキーが押されたときに以下のコードを実行するようにしました。
for (int i = 0; i < Properties.Settings.Default.ActivateWithHotkeyRetryTimes; i++)
{
if (ForceActive(this.Handle)) break;
}
変更のためのGUIを持たない「ActivateWithHotkeyRetryTimes」という隠し設定値を用意して、この回数を上限にしてSetForegroundWindowを繰り返し呼び出します。
こうすると一瞬タスクバーのアイコンが点滅する状態になっても、すぐにVaNTにフォーカスが移るようになりました。
コメント