アプリからチャームを開くには?[Win 8]WinRT/Metro TIPS

Windows 8.1向けのWindowsストア・アプリではチャームに対するスタンスに変化した。Win 8アプリからチャームを開く方法を解説。

» 2013年08月19日 14時02分 公開
[山本康彦BluewaterSoft]
WinRT/Metro TIPS
業務アプリInsider/Insider.NET

powered by Insider.NET

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

連載目次

 ユーザーがアプリを操作するときに、チャームを出して使う場面がある。そのことに気付いてもらえないと、アプリの機能を使ってもらえない。それは避けたいと思うだろう。何とかならないだろうか?

 Windows 8(以降、Win 8)向けのWindowsストア・アプリ(以降、Win 8アプリ)では、明言されていなかったとは思うが「チャームの操作は共通でユーザーはそれを知っているのだから、余分なUIは付けるな」というのがマイクロソフトのスタンスだった。しかし、Windows 8.1(以降、Win 8.1)向けのWindowsストア・アプリ(以降、Win 8.1アプリ)では、そのスタンスに変化が見られる。そこで本稿では、Win 8アプリからチャームを開く方法を解説する。本稿のサンプルは「Windows Store app samples:MetroTips #49(Windows 8版)」からダウンロードできる。

事前準備

 Win 8アプリを開発するには、Win 8とVisual Studio 2012(以降、VS 2012)が必要である。これらを準備するには、第1回のTIPSを参考にしてほしい。本稿では64bit版Win 8 ProとVS 2012 Express for Windows 8を使用している。

検索UXとヘルプUXの変化

 Win 8.1アプリでマイクロソフトのスタンスが変わったことは、検索とヘルプのユーザー・エクスペリエンスの変化で分かる。

 Win 8アプリでは、アプリ内の検索機能を呼び出すには検索チャームを使うように言われていたし、ヘルプ画面を出すのは設定チャームからと指導されていた。ところが、Win 8.1アプリでは、アプリ内の検索のためには画面の右上付近に検索ボックス・コントロールを配置して使えということになった(検索チャームからは不可)。また、マイクロソフト製のアプリを見ると、Win 8.1アプリのみならずWin 8アプリまでもが、アプリ・バーの右端に[ヘルプ]ボタンを持つようになってきている。これらのことから、チャームからアプリを操作させることにこだわらない、という方向にマイクロソフトのスタンスが変化したものと推察される*1

チャームから行うアプリ操作

 Win 8アプリでは次の表に示した操作をチャームから行うことになっている。アプリからそれらの操作を手助けするとしたら何ができるかを、表の右に記載した。

チャーム ユーザー操作 アプリでサポートできること
検索 アプリ内検索 検索チャームを開く(Win 8)
検索ボックスを用意する(Win 8.1)
共有 共有に送る 共有チャームを開く
デバイス 印刷など 印刷チャーム(後述)を開く
設定 オプション設定やヘルプ表示など アプリ・バーなどにコマンド・ボタンを配置する
チャームから行うアプリの操作と、アプリでサポートできること

 表の最下段、オプション設定やヘルプ表示などをアプリ・バーから行う方法はお分かりだろうと思う。すでに設定チャームからオプション設定画面やヘルプ画面を出しているなら、同じ機能をアプリ・バーにも用意する。あるいは、オプション設定のうち頻繁に使う機能は、個別にアプリ・バーに用意してもよい。なお、チャームからの操作に慣れているユーザーのために、設定チャーム側の既存の機能は削らずに残しておいてほしい。

 それでは残りの3つ、検索/共有/印刷のチャームをアプリから開く方法を、これから解説していこう。ユーザーに代わってチャームを開くだけなのだが、それぞれで微妙に方法が異なるのだ。

ベースとなるサンプル・アプリの作成

 サンプルということで、検索などを実際に処理するところまでは実装しない。それぞれのチャームを開けるようにする最小限の実装だけを行う。

 検索チャームを開くアプリは、マニフェストに宣言が必要だ。共有チャームは、開くだけならアプリ側の対応はいらない。デバイス・チャームは、ここでは印刷を使うことにするが、それにはアプリ側で印刷の準備が必要になる。

 まず検索チャーム。実際に検索できるアプリを作るには検索コントラクトの実装が必要だが、アプリから検索チャームを開くだけならそれは不要だ。マニフェストの設定だけ行えばよい。VS 2012のソリューション・エクスプローラで「Package.appxmanifest」ファイルをダブル・クリックして開き、その[宣言]タブの「使用可能な宣言」ドロップダウンで[検索]を選び[追加]ボタンをクリックして完了だ(次の画像)。

マニフェスト・エディタの[宣言]タブの「使用可能な宣言」ドロップダウンで[検索]を選ぶ マニフェスト・エディタの[宣言]タブの「使用可能な宣言」ドロップダウンで[検索]を選ぶ

 次に、印刷の準備。これは少々面倒で、コードビハインドにコードを記述する必要がある。まず、次に示すコードを追加する。これらは、印刷に必要なオブジェクトと、印刷コントラクトから呼び出されるイベント・ハンドラだ。

private Windows.UI.Xaml.Printing.PrintDocument _printDocument;
private Windows.Graphics.Printing.IPrintDocumentSource _printDocumentSource;

private void PreparePrint()
{
  Windows.Graphics.Printing.PrintManager.GetForCurrentView()
    .PrintTaskRequested += pm_PrintTaskRequested;

  _printDocument = new Windows.UI.Xaml.Printing.PrintDocument();
  _printDocument.Paginate += _printDocument_Paginate;
  _printDocument.GetPreviewPage += _printDocument_GetPreviewPage;
  _printDocument.AddPages += _printDocument_AddPages;

  _printDocumentSource = _printDocument.DocumentSource;
}

void pm_PrintTaskRequested(Windows.Graphics.Printing.PrintManager sender,
                           Windows.Graphics.Printing.PrintTaskRequestedEventArgs args)
{
  // このハンドラは通常、ユーザーが[デバイス]チャームをタップすると呼び出される。
  // 最低限、以下の実装がないと印刷チャームが開かない。
  args.Request.CreatePrintTask("印刷のサンプル", req =>
  {
    req.SetSource(_printDocumentSource);
  });
}

void _printDocument_Paginate(object sender, Windows.UI.Xaml.Printing.PaginateEventArgs e)
{
  // (ダミー)
}
void _printDocument_GetPreviewPage(object sender, Windows.UI.Xaml.Printing.GetPreviewPageEventArgs e)
{
  // (ダミー)
}
void _printDocument_AddPages(object sender, Windows.UI.Xaml.Printing.AddPagesEventArgs e)
{
  // (ダミー)
}

Private _printDocument As Windows.UI.Xaml.Printing.PrintDocument
Private _printDocumentSource As Windows.Graphics.Printing.IPrintDocumentSource

Private Sub PreparePrint()
  AddHandler _
    Windows.Graphics.Printing.PrintManager.GetForCurrentView() _
      .PrintTaskRequested, AddressOf pm_PrintTaskRequested

  _printDocument = New Windows.UI.Xaml.Printing.PrintDocument()
  AddHandler _printDocument.Paginate, AddressOf _printDocument_Paginate
  AddHandler _printDocument.GetPreviewPage, AddressOf _printDocument_GetPreviewPage
  AddHandler _printDocument.AddPages, AddressOf _printDocument_AddPages

  _printDocumentSource = _printDocument.DocumentSource
End Sub

Private Sub pm_PrintTaskRequested(sender As Windows.Graphics.Printing.PrintManager, _
                                  args As Windows.Graphics.Printing.PrintTaskRequestedEventArgs)
  ' このハンドラは通常、ユーザーが[デバイス]チャームをタップすると呼び出される。
  ' 最低限、以下の実装がないと印刷チャームが開かない。
  args.Request.CreatePrintTask("印刷のサンプル", _
    Sub(req)
      req.SetSource(_printDocumentSource)
    End Sub
  )
End Sub

Private Sub _printDocument_Paginate(sender As Object, e As Windows.UI.Xaml.Printing.PaginateEventArgs)
  ' (ダミー)
End Sub
Private Sub _printDocument_GetPreviewPage(sender As Object, e As Windows.UI.Xaml.Printing.GetPreviewPageEventArgs)
  ' (ダミー)
End Sub
Private Sub _printDocument_AddPages(sender As Object, e As Windows.UI.Xaml.Printing.AddPagesEventArgs)
  ' (ダミー)
End Sub

印刷に必要なオブジェクトと、印刷コントラクトから呼び出されるイベント・ハンドラを準備する(上:C#、下:VB)
「(ダミー)」の部分は、本来は印刷に必要な処理を記述するべきところ。ここでは、チャームを開くところまで動けばよいので、そのコードは書いてない。

 そうしたら、上のPreparePrintメソッドを、画面の初期化時に呼び出す(次のコード)。

PreparePrint();

PreparePrint()

画面の初期化時に印刷の準備を行う(上:C#、下:VB)
このコードを記述する場所は、LoadStateメソッド(LayoutAwarePageクラスを継承した場合)またはOnNavigatedToメソッド(継承しない場合)である。

 ここまでで実行してみて、手動で検索/共有/デバイスのチャームを出せることを確認しておいてほしい。それぞれの機能は実装していないので実行こそできないものの、チャームは出せる。次の画像は、デバイス・チャームを出して、そこからプリンタを選んだときのものだ。

デバイス・チャームでプリンタを選んだところ
印刷処理を実装していないのでプレビューは表示されないものの、印刷チャームは表示される。 デバイス・チャームでプリンタを選んだところ 印刷処理を実装していないのでプレビューは表示されないものの、印刷チャームは表示される。

コマンド・ボタンを配置する

 それでは、チャームを開くためのコマンド・ボタンを画面に配置しよう。共有チャームと印刷チャームを開くボタンは、アプリ・バーに置く。検索チャームを開くボタンは、Win 8.1アプリ*2に合わせて、検索アイコンを持つ四角いボタンを画面の右上に配置する。

……省略……
<!-- アプリ・バーを追加
    ルートになるGridの手前、</Page.Resources>タグ(もしあれば)の後に記述 -->
<Page.BottomAppBar>
  <AppBar>
    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
      </Grid.ColumnDefinitions>
      <StackPanel Orientation="Horizontal"/>
      <StackPanel Grid.Column="1" HorizontalAlignment="Right" Orientation="Horizontal">
        <Button Tapped="printButton_Tapped" Content="&#xE1A5;" AutomationProperties.Name="印刷"
                Style="{StaticResource AppBarButtonStyle}" />
        <Button Tapped="shareButton_Tapped" AutomationProperties.Name="共有"
                Style="{StaticResource ReshareAppBarButtonStyle}" />
      </StackPanel>
    </Grid>
  </AppBar>
</Page.BottomAppBar>

……省略……

<!-- Back button and page title -->
<Grid Background="#00a2e8">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="Auto"/><!-- 検索ボタンを置くカラムを追加 -->
  </Grid.ColumnDefinitions>
  <Button x:Name="backButton" ……省略…… />
  <TextBlock x:Name="pageTitle" Grid.Column="1" ……省略…… />
  <!-- 検索ボタンを追加 -->
  <Button Grid.Column="2"  Content="&#xE000;" Tapped="searchButton_Tapped"
    Width="44" Height="42" Background="Blue" Margin="10,10,40,0"
    FontFamily="Segoe UI Symbol" Foreground="White"
    Padding="0" FontSize="20" FontWeight="Light" />
</Grid>
……省略……

チャームを開くコマンド・ボタンを画面に配置した(XAML)
印刷ボタンと共有ボタンのStyleプロパティに適用しているスタイルは、StandardStyles.xamlファイルに定義されているもの(スタイルがコメントアウトされている場合は、これを解除する必要もある)。このファイルがプロジェクトにない場合は、別途スタイル指定を作成してほしい。
また、検索ボタンに使う検索アイコンは、画像ではなく「Segoe UI Symbol」フォントを使う。

*2 マイクロソフト製Win 8.1アプリ(Preview版)を見ると、全て右上にSearchBoxコントロール(Windows.UI.Xaml.Controls名前空間)が配置されている。それらのアプリの中には、ビューの幅が狭いときにSearchBoxコントロールの入力欄を隠してボタンだけの表示にしているものもある。そこで、SearchBoxコントロールが使えないWin 8アプリでは、ボタンだけを同じように配置すればよいだろう。


検索チャームを開くには?

 まず、SearchPaneクラス(Windows.ApplicationModel.Search名前空間)のGetForCurrentViewメソッドで、現在の画面に割り当てられているSearchPaneオブジェクトを取得する。得られたSearchPaneオブジェクトのShowメソッドを呼び出せば、検索チャームが開いた状態になる(次のコード)。

private void searchButton_Tapped(object sender, RoutedEventArgs e)
{
  Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().Show();
}

Private Sub searchButton_Tapped(sender As Object, e As TappedRoutedEventArgs)
  Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().Show()
End Sub

検索チャームを開くコード(上:C#、下:VB)
なお、検索チャームは開くが、本稿では検索コントラクトの実装をしていないので、検索チャームから検索を実行しても、何も起こらない。
また、Win 8.1では、手動で検索チャームを開くと「すべての場所」(Bingとローカル・ファイル)が検索範囲に選択された状態になっているが、このコードを実行すると検索範囲としてこのアプリが選択された状態で検索チャームが開く*3

共有チャームを開くには?

 DataTransferManagerクラス(Windows.ApplicationModel.DataTransfer名前空間)のShowShareUIメソッドを呼び出すだけでよい(次のコード)。

private void shareButton_Tapped(object sender, TappedRoutedEventArgs e)
{
  Windows.ApplicationModel.DataTransfer.DataTransferManager.ShowShareUI();
}

Private Sub shareButton_Tapped(sender As Object, e As TappedRoutedEventArgs)
  Windows.ApplicationModel.DataTransfer.DataTransferManager.ShowShareUI()
End Sub

共有チャームを開くコード(上:C#、下:VB)
なお、共有チャームは開くが、本稿では共有コントラクトの実装をしていないので、共有チャームには「このアプリでは共有できません」とだけ表示される(Win 8の場合。Win 8.1では画面キャプチャが共有に送られる)。

印刷チャームを開くには?

 Win 8では、デバイス・チャームを開けばプリンタを選択できた。ところが、Win 8.1(Preview版で確認)では、デバイス・チャームを開くと[再生]/[印刷]/[表示]というリンクが並んでいて、そこで[印刷]をタップするとようやくプリンタの一覧が出てくる。そのWin 8.1のプリンタ一覧を「印刷チャーム」と呼ぶことにする。Win 8では、「デバイス・チャーム」=「印刷チャーム」と考える。

 印刷チャームを開くには、PrintManagerクラス(Windows.Graphics.Printing名前空間)のShowPrintUIAsyncメソッドを呼び出せばよい。ただし、async/await(VBではAsync/Await)の指定も必要だ(次のコード)。

private async void printButton_Tapped(object sender, TappedRoutedEventArgs e)
{
  await Windows.Graphics.Printing.PrintManager.ShowPrintUIAsync();
}

Private Async Sub printButton_Tapped(sender As Object, e As TappedRoutedEventArgs)
  Await Windows.Graphics.Printing.PrintManager.ShowPrintUIAsync()
End Sub

印刷チャームを開くコード(上:C#、下:VB)
なお、印刷チャームは開くが、本稿では印刷コントラクトの実装をしていないので、プリンタを選んでも印刷はできない。
また、このコードをWin 8.1で実行すると、デバイス・チャームではなく印刷チャームが直接開く。

実行結果

 以上で完成だ(次の画像)。

サンプル・アプリを起動したところ&#xD;&#xA;右上に検索チャームを開くボタンがある。アプリ・バーには、共有チャームと印刷チャームを開くボタンが配置されている。 サンプル・アプリを起動したところ 右上に検索チャームを開くボタンがある。アプリ・バーには、共有チャームと印刷チャームを開くボタンが配置されている。

 それぞれのボタンをタップすると自動的にそれぞれのチャームが開くことを確かめてほしい。

まとめ

 コードからチャームを開くことは難しくない。それは、Win 8アプリに慣れたユーザーにとっては大きなお世話かもしれない。しかし、Win 8.1アプリではチャームの地位が低下し、ユーザーがチャームの操作に習熟していると仮定するのは難しくなる。Win 8.1から使い始めるユーザーのためには、チャームをコードからも開くようにするとよいだろう。

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

WinRT/Metro TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

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

メールマガジン登録

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