[WP] アプリケーション自身のスクリーンキャプチャ機能の実装

Windows Phone では スクリーンキャプチャを取ることはできませんが、アプリケーション自身に自分の画面を保存機能を持たせることができます。今回は、

  • ページタイトルをタップすると、画面全体のキャプチャ
  • シャッターボタンでもキャプチャできるようにする

の2つの機能を実装します。まずはUI側。ポイントは一つでカメラの生画像を受け取るための videoBrush を設定しています。その機能はいらないとは思いますが、シャッターボタンをハンドリングするために必要なので入れています。 (書籍14章) シャッターボタンのハンドリングが不要な場合は必要ありません。実際には機能はいらないのと思いますので、Rectangle 自体は Collaspsed に設定しています。image

<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
    <TextBlock x:Name="ApplicationTitle" . />
    <TextBlock x:Name="PageTitle" … Tap="PageTitle_Tap" />
</StackPanel>

<Grid x:Name="LayoutRoot">

                     :

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

        <Rectangle Visibility="Collapsed">
<Rectangle.Fill>
<VideoBrush x:Name="viewfinderBrush" Stretch="UniformToFill" />
</Rectangle.Fill>
</Rectangle>

    </Grid>
 
   <Grid.Background>
        <ImageBrush ImageSource="/ScreenCapture;component/background.jpg" />
    </Grid.Background>

</Grid>

そしてロジック側。OnNavigatedToで画面が遷移してからハンドリングを開始します。 (書籍12章)

シャッターボタンのハンドリングには、PhotoCamera のインスタンスを作成し、VideoBrushとつなげる必要があります。そして、CameraButtonクラスのShutterKeyPress イベントをハンドリングします。CameraButtonクラスはStaticなのでオブジェクトを作る必要はありません。 (書籍14章)

public partial class MainPage : PhoneApplicationPage
{
    // コンストラクター
    public MainPage()
    {
        InitializeComponent();
   }

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
PhotoCamera cam = new Microsoft.Devices.PhotoCamera();
CameraButtons.ShutterKeyPressed += new EventHandler(CameraButtons_ShutterKeyPressed);
viewfinderBrush.SetSource(cam);
}

    void CameraButtons_ShutterKeyPressed(object sender, EventArgs e)
{
TakeCapture();
}

    private void PageTitle_Tap(object sender, GestureEventArgs e)
{
TakeCapture();
}

    private void TakeCapture()
{
WriteableBitmap bitmap = new WriteableBitmap(this.LayoutRoot, null);
MemoryStream stream = new MemoryStream();

        bitmap.SaveJpeg(stream, bitmap.PixelWidth, bitmap.PixelHeight, 0, 80);

        using (MediaLibrary medialib = new MediaLibrary())
medialib.SavePicture(DateTime.Now.ToString("yyMMddHHmmss"), stream.ToArray());
MessageBox.Show("Saved");
}
}

110918202758画面キャプチャの実装はシンプルです。そもそも、画像を扱うための WriteableBitmap には画面の要素である UIElement から Bitmap を生成する機能があるため、画面のTopレベルである LayoutRoot をベースに Bitmap 作成すれば、それが画面キャプチャとなるためです。 (書籍7章)

作成したスクリーンショットは、XNAの機能であるMedia Libraryを使ってPicture ハブに登録しています。そのため、System.XNA.Framework の参照が必要です。 (書籍5章)

WritableBitmapはストリームを使ってJpeg保存します。 (書籍7章) 右の画像のようにスクリーンショットだけをjpeg画像としてPictureハブに登録することができます。

つまり、どのUIElementを使うかによって画面の一部分だけをキャプチャすることも出来ます。

 screencapture

ただ、シャッターボタンを使うために、特に使わないのに、VideoBrushを設定するのも効率的ではありません。ですから、キャプチャをするときにはメニューから「画面をキャプチャする」などで選択させ、その時に初めてハンドリングし、キャプチャをする旅に「キャプチャを終了しますか?」を確認したほうがいいですね。終了するとした場合は、VideoBrush と CameraButton ハンドリングを削除します。