タイトルバーにUIコントロールを配置するには?[Windows 10 UWPアプリ開発]WinRT/Metro TIPS(2/2 ページ)

» 2015年10月14日 05時00分 公開
[山本康彦BluewaterSoft/Microsoft MVP for Windows Platform Development]
前のページへ 1|2       

高さと幅を調節するには?

 上に述べた問題を解決するには、作成したタイトルバーの高さと幅を適切な値に調整すればよい。それには、CoreApplicationViewTitleBarクラスのLayoutMetricsChangedイベントを利用する。

 ウィンドウが表示されるときや、デスクトップモードとタブレットモードの切り替えのときなどにLayoutMetricsChangedイベントが発生する。イベントハンドラーの引数にはCoreApplicationViewTitleBarオブジェクトが渡されるので、そのプロパティを見てタイトルバーのUIの寸法を調整できる(次のコード)。なお、コメント中の数字は冒頭で紹介した手順の各ステップに対応している。

private void SetTitleBar()
{
  ……省略……
  // 【2】 作ったUIをタイトルバー部分に「押し出す」
  coreTitleBar.ExtendViewIntoTitleBar = true;
  appTitleBar.ButtonBackgroundColor = Windows.UI.Colors.Transparent;

  // 【3】高さと幅を調節する
  coreTitleBar.LayoutMetricsChanged
    += CoreTitleBar_LayoutMetricsChanged;
}

// タイトルバーの寸法が変わったとき
private void CoreTitleBar_LayoutMetricsChanged(
    Windows.ApplicationModel.Core.CoreApplicationViewTitleBar sender,
    object args)
{
  // タイトルバーの高さ
  myTitleBar.Height = sender.Height;

  // タイトルバーの左右に確保するスペース
  myTitleBar.Padding 
    = new Thickness(
            sender.SystemOverlayLeftInset,
            0.0,
            sender.SystemOverlayRightInset,
            0.0
          );
}

Private Sub SetTitleBar()
  ……省略……
  ' 【2】 作ったUIをタイトルバー部分に「押し出す」
  coreTitleBar.ExtendViewIntoTitleBar = True
  appTitleBar.ButtonBackgroundColor = Windows.UI.Colors.Transparent

  ' 【3】高さと幅を調節する
  AddHandler coreTitleBar.LayoutMetricsChanged,
    AddressOf CoreTitleBar_LayoutMetricsChanged
End Sub

' タイトルバーの寸法が変わったとき
Private Sub CoreTitleBar_LayoutMetricsChanged(
    sender As Windows.ApplicationModel.Core.CoreApplicationViewTitleBar,
    args As Object)

  ' タイトルバーの高さ
  myTitleBar.Height = sender.Height

  ' タイトルバーの左右に確保するスペース
  myTitleBar.Padding _
    = New Thickness(
            sender.SystemOverlayLeftInset,
            0.0,
            sender.SystemOverlayRightInset,
            0.0
          )
End Sub

タイトルバーのUIの寸法を調整するコードの例(上:C#/下:VB)
前述した「SetTitleBar」メソッドの末尾に、LayoutMetricsChangedイベントにハンドラーを結び付けるコードを追加した。また、そのハンドラーとして、CoreTitleBar_LayoutMetricsChangedメソッドを追加した。

 これで、次の画像のようになる。

タイトルバーらしくなった(デスクトップでの実行) タイトルバーらしくなった(デスクトップでの実行)
検索ボックスがシステムの[×]ボタンなどの左に移動した。また、タイトルバーの高さも、以前と同じになった。
なお、検索ボックスの位置が左に寄りすぎという感じがする。システムが最小化ボタンのさらに左にもう一つボタンを出すことがあるので、そのためのスペースだろうと思われる(Windows 8.x用のストアアプリをWindows 10で実行すると全画面化ボタンが表示される。「WinRT/Metro TIPS:コードから設定チャームやアプリバーを開くには?[ユニバーサルWindowsアプリ開発]」の冒頭の画像を参照)。

 見た目はタイトルバーらしくなった。タイトル文字列のところをマウスでドラッグすれば、ウィンドウが移動できる。

 ところが、これで検索してみようとして検索ボックスをクリックしても、検索ボックスにフォーカスが当たらないのである。検索ボックスでのマウス操作も、ウィンドウの移動になってしまうのだ。もともとのタイトルバーの範囲が、あいかわらずタイトルバーとして扱われているようだ(=ウィンドウの移動のために使われる)。

検索ボックスをマウスでクリックできるようにするには?

 検索ボックスをマウスでクリックできるようにするには、それ以外の部分(ここではその左のタイトル文字列)が移動に使うための領域であるとシステムに教えればよい。

 次のコードのようにして、タイトル文字列が入っている「titleGrid」だけをタイトルバーとして扱うように指定する。

private void SetTitleBar()
{
  ……省略……
  // 【3】高さと幅を調節する
  coreTitleBar.LayoutMetricsChanged
    += CoreTitleBar_LayoutMetricsChanged;

  // 【4】検索ボックスをマウスでクリックできるようにする
  Window.Current.SetTitleBar(titleGrid);
}

Private Sub SetTitleBar()
  ……省略……
  ' 【3】高さと幅を調節する
  AddHandler coreTitleBar.LayoutMetricsChanged,
    AddressOf CoreTitleBar_LayoutMetricsChanged

  ' 【4】検索ボックスをマウスでクリックできるようにする
  Window.Current.SetTitleBar(titleGrid)
End Sub

「titleGrid」だけをタイトルバーとして扱うように指定するコードの例(上:C#/下:VB)
太字の部分を追加した。「titleGrid」の部分だけをタイトルバーとして扱うように指定することで、それ以外の部分(ここでは検索ボックス)はマウスでドラッグしてウィンドウを移動することはできなくなる(そのコントロール本来の動きに戻る)。

 これで検索ボックスにキー入力できるようになった。

 最後に、ウィンドウがフォーカスを失った(=他のアプリをアクティブにした)ときの挙動が残っている。このままでは、フォーカスを失ってもタイトルバーの色が変化しないので、識別しにくいのだ。

ウィンドウのフォーカス状態に応答するには?

 Windowクラス(Windows.UI.Xaml名前空間)のActivatedイベントで処理すればよい。

 イベントハンドラーの中で、タイトルバーとその背景色のopacity(不透明度)を変更すると、フォーカスを失ったウィンドウらしく見えるようになる(次のコード)。

private void SetTitleBar()
{
  ……省略……
  // 【4】検索ボックスをマウスでクリックできるようにする
  Window.Current.SetTitleBar(titleGrid);

  // 【5】ウィンドウのフォーカス状態に応答する
  Window.Current.Activated += Current_Activated;
}

private void Current_Activated(object sender,
                Windows.UI.Core.WindowActivatedEventArgs e)
{
  if (e.WindowActivationState 
      != Windows.UI.Core.CoreWindowActivationState.Deactivated)
  {
    // ウィンドウがフォーカスを受け取ったとき
    myTitleBar.Opacity = 1.0;
    myTitleBar.Background.Opacity = 1.0;
  }
  else
  {
    // ウィンドウがフォーカスを失ったとき
    myTitleBar.Opacity = 0.5;
    myTitleBar.Background.Opacity = 0.0;
  }
}

Private Sub SetTitleBar()
  ……省略……
  ' 【4】検索ボックスをマウスでクリックできるようにする
  Window.Current.SetTitleBar(titleGrid)

  ' 【5】ウィンドウのフォーカス状態に応答する
  AddHandler Window.Current.Activated, AddressOf Current_Activated
End Sub

Private Sub Current_Activated(sender As Object,
              e As Windows.UI.Core.WindowActivatedEventArgs)
  If (e.WindowActivationState _
        <> Windows.UI.Core.CoreWindowActivationState.Deactivated) Then
    ' ウィンドウがフォーカスを受け取ったとき
    myTitleBar.Opacity = 1.0
    myTitleBar.Background.Opacity = 1.0
  Else
    ' ウィンドウがフォーカスを失ったとき
    myTitleBar.Opacity = 0.5
    myTitleBar.Background.Opacity = 0.0
  End If
End Sub

ウィンドウのフォーカス状態でタイトルバーの見掛けを変えるコードの例(上:C#/下:VB)
前述した「SetTitleBar」メソッドの末尾に、Activatedイベントにハンドラーを結び付けるコードを追加した。また、そのハンドラーとして、Current_Activatedメソッドを追加した。

実行結果

 それでは実行してみよう。ところで、今回作ったコードはユニバーサルである。つまり、Mobileデバイスでもエラーにはならない。デスクトップでのウィンドウ表示と、Mobileデバイス(エミュレーター)での実行結果を一緒にご覧に入れよう(次の画像)。

実行結果(デスクトップとMobileエミュレーター)
実行結果(デスクトップとMobileエミュレーター)
実行結果(デスクトップとMobileエミュレーター) 実行結果(デスクトップとMobileエミュレーター)
上: 起動直後。Mobileでは、青色の部分の高さがXAMLコードで指定したままになっている(=高さと幅を調節するコードが働いていない)。
中: タイトル文字列の部分をクリック/タッチ。デスクトップではドラッグしてウィンドウを移動できる(検索ボックスからフォーカスは外れない)。Mobileでは、検索ボックスからフォーカスが外れる。
下: デスクトップで他のアプリにフォーカスを移動した。ウィンドウのタイトルバーから色が消えて表示が薄くなっているので、アクティブでないと一見して分かる。なお、Mobileでは、アプリが表示されたままの状態で他のアプリにフォーカスが移ることはない。

 また、PCでタブレットモードに切り替えると次の画像のようになる。システムの[×]ボタンなどは消えているが、タイトルバーを出す操作(マウスならば画面上端をホバー)で[×]ボタンだけが出てくる。

タブレットモードでの実行(デスクトップ)
タブレットモードでの実行(デスクトップ) タブレットモードでの実行(デスクトップ)
上: 通常時。
下: タイトルバーを出す操作をしたときは[×]ボタンだけが出てくる。タイトルバー領域に配置したUIが隠されることはない。

まとめ

 タイトルバーにUIコントロールを配置するには、多くのことに対応しなければならないので少々面倒であるが、それぞれの処理は難しくない。また、ユニバーサルに作れて、Mobileデバイスではタイトルバーの部分がそのまま表示される。

「WinRT/Metro TIPS」のインデックス

WinRT/Metro TIPS

前のページへ 1|2       

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。