瞬間的にウィンドウを非表示化したい
個人的な結論
- 非表示にこだわらない、アクティブウィンドウが変わってもよい
- WindowStateを使ったウィンドウの最小化で対応
- 絶対非表示、アクティブウィンドウ変わってほしくない
- Visibilityを使った非表示化とマジックナンバー的wait
---
どうすればウィンドウを非表示できるか
少し調べるとVisibilityプロパティをHiddenやCollapsedにすれば非表示出来ることは行き着くのだが、本当に非表示になったことを確認する方法が出てこない。
IsVisibleプロパティがそれっぽい。具体的には以下の記述がそれっぽい。
- IsVisible
- true if the element is visible; otherwise, false.
- Visibility
- Setting this property affects the value of IsVisible, which in turn may raise the IsVisibleChanged event.
IsVisibleがそれっぽいと言ったな、あれは嘘だ
説明だけみるとそうに間違いないのだが、UIが絡むからかそんなことはない。
例えば、スクリーンキャプチャする瞬間だけ非表示みたいな処理をしたい場合、CopyFromScreenの実行をIsVisibleChangedが発生するまで実行を遅延すれば良いように思える。
Visibility = Visibility.Collpsed;
…// ここでIsVisibleChangedの発生を待つ
graphics.CopyFromScreen(…);
…
Visibility = Visibility.Visible;
ところがどっこいやってみるとウィンドウは非表示になっておらず、ばっちりキャプチャされてしまう。デバッグモードで止めて確認して何度がっかりしたことか。問題設定的には以下と同じである
見えなきゃ良いんでしょ
じゃあ無理じゃんとなるんだけど、一応方法がないわけではない。非表示は諦めて最小化すればどうにかなるのである。
具体的にはWindowStateでウィンドウを最小化してStateChangedイベントを拾えば目的は達せられる。ちなみにShowInTaskbarがfalseだと左下に小さくなったウィンドウが表示されるのでそのときだけはShowInTaskbarをtrueにしておいた方が良いと思う。実際にやってみた感じだと一瞬タスクバーに追加されても復元されてもほとんど気づけないので実質非表示と同じだと言っても過言ではない。
だけどもだっけーど
はい、カンペキ、Minimizedでファイナルアンサーね。となったところで待ったをかけるのがアクティブウィンドウ問題である。
というのも最小化する方法だとNormalでウィンドウを復元したタイミングなのか、どこかでアクティブウィンドウが切り替わってしまうらしい。操作しているウィンドウと瞬間的に非表示するウィンドウが一致していることも多いのでその場合は問題ない。ただ、別ウィンドウがアクティブであってほしい場合には向かない。
そもそもVisibilityってどのくらいで反映されるの?
計ってないのでわからないです。ただ、手元の環境だと10ms待機(await Task.Delay(10);)でも十分だったということはお伝えしておきます(Stopwatchクラスでも11msと言っていたので時間的にはあってると思う)。
完全にwaitする術がない以上、機械的に1msの猶予も許さないとかでもない限り適当にwaitかければ良いのでは?というウチの環境では動く的な古のコーディングスタイルをおススメしなければならないことが心苦しい。
蛇足
IsVisibleをMVVM的にやろうとIsVisibleChangedイベントをEventTriggerでキャッチしようとしてもキャッチできない。
かなり前からあるのでもう修正してもらえないと思う。諦めてわざわざコードビハインドからViewModelのコマンド叩いたのに非表示になってないもんだからもうビックリだったね。
コメント
コメントを投稿