読者です 読者をやめる 読者になる 読者になる

atelier:mitsuba

i love UI/UX, Blend, XAML, Behavior, P5, oF, Web, Tangible Bits and Physical computing. なにかあればお気軽にご連絡ください。atelier@c-mitsuba.com

アプリ内スクリーンショットを撮れるカスタムビヘイビアつくってみた

Silverlight WindowsPhone7
Windows Phone AdventCalender 5日目の記事だよ!
http://atnd.org/events/22351

アプリ内スクリーンショットの撮り方は以前MSの高橋さんが紹介していました。
http://blogs.msdn.com/b/shintak/archive/2011/09/18/10213126.aspx
今回はそれを参考にカスタムビヘイビア化してみました。
正確にはカスタムトリガーアクションですね。
トリガーアクションを開発するテンプレートはだいたい一緒で、トリガーアクションを継承し、Invokeに実際の処理を描くだけです。


前に作ったOpenWebBrowserTaskBehaviorとほとんど一緒ですね。
http://d.hatena.ne.jp/c-mitsuba/20111023/1319311161


とりあえずソース

using System;
using System.Net;
using System.IO;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Interactivity;
using Microsoft.Xna.Framework.Media;
using System.Windows.Media.Imaging;

namespace euphoriaBehaviorsLibrary
{
    public class SaveScreenShotAction : TargetedTriggerAction<DependencyObject>
    {
        protected override void Invoke(object parameter)
        {
            WriteableBitmap bitmap = new WriteableBitmap((UIElement)base.Target, null);
            MemoryStream stream = new MemoryStream();
            bitmap.SaveJpeg(stream, bitmap.PixelWidth, bitmap.PixelHeight, 0, 100);
            using (MediaLibrary medialib = new MediaLibrary())
                medialib.SavePicture(DateTime.Now.ToString("yyMMddHHmmss"), stream.ToArray());
            MessageBox.Show("Saved");

        }
    }
}

簡単ですね!


解説すると、まずこのクラスはTargetedTriggerActionですよーと書きます。

public class SaveScreenShotAction : TargetedTriggerAction<DependencyObject>

このTargetTriggerActionはTriggerActionと違って、共通プロパティでコントロールを指定することができます。Blendで選択すると、共通プロパティパネルが確認できますね。


指定したコントロールはbase.Targetで取得することができます。

WriteableBitmap bitmap = new WriteableBitmap((UIElement)base.Target, null);

base.Targetが非常に便利で、まずはTargetNameに指定したオブジェクトが返って来ます。TargetNameが指定されていなければAssoviatedObject(TargetObject)が返って来ます。
base.TargetNameとかbase.TargetObjectとかも取得できますが、とりあえずbase.Targetを指定しておけばいいので楽ですね。
ちなみにbase.TargetはプロパティなのでDependencyObject型です。


あとは高橋さんのソースそのままです。
ボタンコントロールにSaveScreenShotActionを設定して、TargetNameにLayoutRootを指定すれば、いま画面に表示されているスクリーンショットが撮影できます。
また、Targetに適当なGridを指定してやれば、そのGridだけのスクリーンショットを撮影するができます。
さらに画面内に表示されていないPanoramaItemなんかも、撮影することができます。


ぷろぐらみんぐとか全然わかんないし、ぶれんどのぽとぺたでスクリーンショットとれるなんて素敵すぎるわー


尚、今回開発したSaveScreenShotActionはeuphoria : Behavior and Style Template Library for Windows Phoneにまとめています。
http://euphoria.codeplex.com/
使ってみたい方は、ダウンロードしてDLLを参照に追加するだけで、BlendのAssetから利用できますよ。


補足:
このカスタムトリガーアクションを開発するにあたって、シャッターボタンでアクションを発火させるカスタムトリガーも作りたかったんですが、カメラプレビューをVideoBrushに繋げないとシャッターのイベントをハンドリングできないとのことで、うまく行きませんでした。
そんなことしなくても、普通にイベントとして取得できればいいんですけどねぇ。。。