UWP を Continuum に完全対応させるには?

#wpjp #wpdev_jp

UWPをContinuum に対応させるための方法をエバンジェリストの佐藤さんがまとめてくれました。

Continuum for Phone (電話用の Continuum) に対応したアプリを作成する

すいません。佐藤さんのネタをそのままパクッて簡略化してまとめます。サンプルや詳細な解説はぜひ、上記の佐藤さんの記事をご覧ください。(GitHubでサンプルも公開されています)

■ Continuum に対応するには

UWPを作ればOKです。

 

いま外部モニタかデバイスかどちらにいるか判断する

UIViewSettings.GetForCurrentView().UserInteractionMode の値が
UserInteractionMode.Mouse なら外部モニター
UserInteractionMode.Touch ならデバイス側で表示されてます。

画面サイズが変わった時などにこれで判断して、画面のデザインを変えたりするのがベター。

 

外部モニタとデバイスの両方に2つの別の画面を表示する

手順は4つかな?

  1. 外部モニター用のページを作る

    普通にページ(XAMLビュー)を追加するだけです。

  2. 今の画面のIDを取得する

    ApplicationView.GetForCurrentView().Id で取れます。

  3. 新しい画面を作って、その画面のIDを取得する

    画面(View)を作るには、Frameを作ってPageクラスにNavigateして、Activeにする。
    つまり App.xaml.cs でやっていることと同じです。
    そのまま2と同じ要領で画面ID取得できます。

    var rootFrame = new Frame();
    rootFrame.Navigate(typeof(ProjectionViewPage)); 
    Window.Current.Content = rootFrame; 
    Window.Current.Activate();
    int id = ApplicationView.GetForCurrentView().Id ;

    ただし、上記の処理をそのまま実行すると、新しい画面が今の画面とすり替わってしまうので、
    そうならないように(2つの画面が両方存在するよう)この処理は別のUIスレッドとして処理をします。

    await CoreApplication.CreateNewView().Dispatcher.RunAsync(
        CoreDispatcherPriority.Normal, () =>
        {
            :
        });

  4. デバイスと外部モニタにそれぞれの画面を出す

    2つの画面ができたら、StartProjectingAsync で画面のIDを指定するだけ。
    IDの順番は外部モニタに出す方、デバイスに出す方の順。

    await ProjectionManager.StartProjectingAsync(4のID, 2のID);

図解すると、こう。ちなみに、この画面IDをアプリ全体で覚えておけば、外部モニター側の画面を停止したり、デバイス側と外部モニター側の表示を入れ替えたりすることができるので、そういうことをやりたい場合は、覚えておくといいでしょう。(佐藤さんのサンプルが参考になります)

Continuum

グダグダ書いたけど、ソースコードで言えばこれだけ。2画面をどう生かすかはあなた次第。

private async void Projection_Click(object sender, RoutedEventArgs e)
{

    if (ProjectionManager.ProjectionDisplayAvailable)
    {
        int thisViewId = ApplicationView.GetForCurrentView().Id;
        int newViewId = 0;

        await CoreApplication.CreateNewView().Dispatcher.RunAsync(
            CoreDispatcherPriority.Normal, () =>
            {
                var rootFrame = new Frame();
                rootFrame.Navigate(typeof(ProjectionViewPage));
                Window.Current.Content = rootFrame;
                Window.Current.Activate();
                newViewId = ApplicationView.GetForCurrentView().Id;
            });

        await ProjectionManager.StartProjectingAsync(newViewId, thisViewId);
    }
}

 

 

おまけ Continuum に対応させない(外部モニターでは表示させない)

普通はあまりやらないだろうけど、どうしても Windows 10 Mobile 専用で、かつ大きな横型の画面には対応させたくない、って場合はこれね。スマフォ専用のゲームとかアプリとかそんな場合ね。

Package.appxmanifest をコードで表示して以下を追加

<Applications>
    <Application ...>
      <Extensions>
<mobile:Extension Category="windows.mobileMultiScreenProperties">
<mobile:MobileMultiScreenProperties RestrictToInternalScreen="true"/>
</mobile:Extension>
</Extensions>
    </Application>
  </Applications>