« 【#UWP】 15063用の Acrylic Effect を、ちゃんと実装してみる | トップページ | 【#UWP】 ビットマップの表示色を変える (Win2D.uwp 経由で Direct2D を使う) »

2017年8月16日 (水)

【#UWP】 CompactOverlay モード: Picture in Picture というか、「最前面に表示」するウィンドウを作る

UWP アプリをやってると、 Windows Forms や WPF の TopMost プロパティが懐かしくなることってありますよね f(^^;

Creators Update (Version 1703, build 15063) から、 UWP アプリでも可能になりました♪

20170816_compactoverlaymode01
上の画像で、左上に赤丸の付いたウインドウ (この後で紹介するコード) と画面右上にある青色のウインドウが最前面に表示されています。 最大化した Visual Studio は、 インテリセンスのポップアップが出ているので、 これがアクティブな (フォーカスを持った) ウインドウです。 その手前に 2 つのウインドウが表示されているのです。

この「常に手前に表示」機能を実装したアプリの例


これをやるには、 ApplicationView クラスの TryEnterViewModeAsync メソッドを使います。

その使い方を説明する前に、 この CompactOverlay モードの動作を紹介しておきましょう。

こんなアプリを作りました。 これは通常モードのときのウインドウです。 表示エリアの左上に赤丸を置きました。 左下のボタンで、 モードを切り替えます。
20170816_compactoverlaymode02a

そして、 CompactOverlay モードに入ると、 ウインドウの位置は必ず画面右上に移動されます (最初の画像にあるように、 その後で動かすのは OK)。
20170816_compactoverlaymode03

また、 モードに入る前のウインドウサイズは無視されて、 デフォルトでは上の画像のようなサイズになります (後のコードのところで説明しますが、 ある程度はサイズ指定可能)。

CompactOverlay モードの状態でリサイズしてみると、 最大は 500 x 384 epx、 最小は 150 x 150 epx みたいです (最小サイズは、 モードに入るときにサイズ指定していると 150 x 150 まで小さく出来ない --- バグか仕様か不明)。

最前面モードでの最大サイズ
20170816_compactoverlaymode05a

最前面モードでの最小サイズ
20170816_compactoverlaymode04a

上の 2 つの画像は、 いずれもウインドウがアクティブな状態です。

あれっ!? 気付きました?
左上の赤丸が居なくなっちゃってます!!

じつは、 CompactOverlay モードでは、 Page の領域にタイトルバーが被さっているんです。

ウインドウがアクティブじゃなくなると (他のアプリにフォーカスを移すと)、 次の画像のようにタイトルバーが消えて、 Page 全体が見えるようになります。
20170816_compactoverlaymode06a

でも、 アクティブじゃないときでも、 マウスをホバーさせると↓この通り。
20170816_compactoverlaymode07a

つまり、 最前面モードを使うなら、 画面上端 30epx 程度には UI や重要な情報を置いちゃダメ、 ということですね。

あるいは、 DraggableWindow でやったように、 Page をタイトルバーにまで押し出すか、 です。 ただし、 それをやっても、 アクティブ時やマウスホバー時に [X] ボタンは出る↓のでご注意を。

20170816_compactoverlaymode09a 20170816_compactoverlaymode10a

 
なお、 複数のウインドウが CompactOverlay モードになっているときは、 最後にアクティブにしたウインドウが最前面になります。
20170816_compactoverlaymode08


■ 最前面にするには?

こちらのブログ記事 "CompactOverlay mode – aka Picture-in-Picture" (2017/2/11) をお読みください。 ……といっても横文字なので、 簡単に紹介します。 f(^^;

CompactOverlay モードに切り替えるには、 ウインドウがアクティブな状態のときにTryEnterViewModeAsync メソッドを呼び出すだけです。

あ、 15063 以降じゃないと動きませんからね、 そこはご注意を。

bool modeSwitched
  = await ApplicationView.GetForCurrentView()
            .TryEnterViewModeAsync(ApplicationViewMode.CompactOverlay);

モード切り替えに成功すると true が返ってきます。 メソッドから返ってきた時点では、 ウインドウサイズは元のままのようです。


■ 最前面ウインドウのサイズを指定するには?

CompactOverlay モードに入るとき、 ウインドウサイズを指定できます。 ただし、先に紹介した最小・最大サイズを超える値を指定すると無視されるようです。

ViewModePreferences compactOptions
  = ViewModePreferences.CreateDefault(ApplicationViewMode.CompactOverlay);
Size desiredSize = ……略……;
compactOptions.CustomSize = desiredSize;
bool modeSwitched
  = await ApplicationView.GetForCurrentView()
            .TryEnterViewModeAsync(ApplicationViewMode.CompactOverlay, compactOptions);


■ 最前面モードから抜けるには?

これまた、 TryEnterViewModeAsync メソッドを呼び出すだけです。 通常モードに戻ったとき、 ウインドウの位置とサイズは、 CompactOverlay モードに入る前の状態に復元されます。

bool modeSwitched
  = await ApplicationView.GetForCurrentView()
            .TryEnterViewModeAsync(ApplicationViewMode.Default);


■ 起動時に最前面モードにするには?

Page のコンストラクターや OnNavigatedTo メソッドで TryEnterViewModeAsync メソッドを呼び出してもダメなようです。 ウインドウが最初にアクティブになったときに呼び出してやったら、 動きました。
ただし、 これでストアの審査に通るかどうかは知らない (汗; 通りました♪

public MainPage()
{
  this.InitializeComponent();

  ……略……

  bool isFirstActivate = true;
  Window.Current.Activated += async (s, e) =>
  {
    if (e.WindowActivationState == CoreWindowActivationState.CodeActivated
        && isFirstActivate)
    {
      isFirstActivate = false;

      // ウインドウが初めてアクティブになったとき、 CompactOverlay にする。
      await ApplicationView.GetForCurrentView()
        .TryEnterViewModeAsync(ApplicationViewMode.CompactOverlay);
    }
  };
}


■ サンプルコード

以上のサンプルコードは GitHub の https://github.com/biac/blogcode/tree/master/TopMostWindow に置いてあります。

 

|

« 【#UWP】 15063用の Acrylic Effect を、ちゃんと実装してみる | トップページ | 【#UWP】 ビットマップの表示色を変える (Win2D.uwp 経由で Direct2D を使う) »

プログラミング」カテゴリの記事

* プログラミング ( Metro スタイル )」カテゴリの記事

コメント

この記事へのコメントは終了しました。

トラックバック


この記事へのトラックバック一覧です: 【#UWP】 CompactOverlay モード: Picture in Picture というか、「最前面に表示」するウィンドウを作る:

« 【#UWP】 15063用の Acrylic Effect を、ちゃんと実装してみる | トップページ | 【#UWP】 ビットマップの表示色を変える (Win2D.uwp 経由で Direct2D を使う) »