Storyboard の値をコードで動的に変更する

引き続き、
Windows 8 Store apps Advent Calendar : ATND
http://atnd.org/events/33803
の16日目のネタです。

ちょっと、人数が足りないようなので、じゃあ「タイマーを使わない時計アプリの紹介を」ってのを思いついたので立候補したのですが…

アナログ時計を作ろう! (プログラミングの知識がある方向け)
http://technet.microsoft.com/ja-jp/subscriptions/hh524813.aspx

にすでにあるじゃん orz ってことで、自己却下。storyboard を使うと、プログラム内でタイミング制御をしないから楽なんですよね、ってのと、(たぶん)グラボの性能を引き出せるからプログラム内で制御するよりも軽くなるのでは?ってな想像です。

で、仕方がないので、手元の原稿から「Visual Studio 2012 でスナップ対応の画面を作る」ってネタを出そうと思ったのですが、

WinRT/Metro TIPS:ビューの切り替えを実装するには?[Win 8] – @IT
http://www.atmarkit.co.jp/ait/articles/1209/27/news139.html

ってのに、すでに詳しいページがあってですね。ええ、これで十分だからまあ良いかと…。LayoutAwarePage クラスを継承する「基本ページ」に切り替えておくと、VisualStateManager が、XAML の中のコードから引き出してくれる、ってのと、Visual Studio 2101 と Blend には、これを作成するための特別な「デバイス」表示があって、そこで「状態記録の有効化」をしておくと、見た目通りに作れて便利。ってな具合なのです。

で、ネタかぶりってことで、storyboard の値をプログラム内で、動的に変えるって技…というかノウハウを紹介します。

麻雀パイコントロールを作ったときに悩んだのが、「捨て牌」の動作です。「一萬」を捨ているときと、左端の「1筒」を捨てる時では、捨てる開始位置が違うわけで、これそれぞれに storyboard を作らないとだめなのか…と最初、うんざりしてしまました。まあ、Blend でちまちまと 13 牌分作ってもよいのですが、ちょっとでも場所がずれるとだめとか、そもそも自牌コントロールとして、13 牌はまとめてつくってあるわけで、捨てる先の河の位置を考えると、ちまちま作るのはダメなのかと。

で、次に考えたのが、このあたりの storyboard をプログラム内で作る方法です。
捨て牌のアニメーションを blend で作って後に、ちまちまと C# のプログラムコードに直して、Storyboard を起動させればよいかと。

しかしですね、

<Storyboard x:Name="sbAnimePai">
	<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="animeImagePai">
		<EasingDoubleKeyFrame x:Name="startPosX"  KeyTime="0" Value="892.537">
			<EasingDoubleKeyFrame.EasingFunction>
				<BackEase EasingMode="EaseInOut"/>
			</EasingDoubleKeyFrame.EasingFunction>
		</EasingDoubleKeyFrame>
		<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0">
			<EasingDoubleKeyFrame.EasingFunction>
				<BackEase EasingMode="EaseInOut"/>
			</EasingDoubleKeyFrame.EasingFunction>
		</EasingDoubleKeyFrame>
	</DoubleAnimationUsingKeyFrames>
	<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="animeImagePai">
        <EasingDoubleKeyFrame x:Name="startPosY"  KeyTime="0" Value="458.208">
			<EasingDoubleKeyFrame.EasingFunction>
				<BackEase EasingMode="EaseInOut"/>
			</EasingDoubleKeyFrame.EasingFunction>
		</EasingDoubleKeyFrame>
		<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0">
			<EasingDoubleKeyFrame.EasingFunction>
				<BackEase EasingMode="EaseInOut"/>
			</EasingDoubleKeyFrame.EasingFunction>
		</EasingDoubleKeyFrame>
	</DoubleAnimationUsingKeyFrames>
	<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)" Storyboard.TargetName="animeImagePai">
		<EasingDoubleKeyFrame KeyTime="0" Value="-360">
			<EasingDoubleKeyFrame.EasingFunction>
				<BackEase EasingMode="EaseInOut"/>
			</EasingDoubleKeyFrame.EasingFunction>
		</EasingDoubleKeyFrame>
		<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0">
			<EasingDoubleKeyFrame.EasingFunction>
				<BackEase EasingMode="EaseInOut"/>
			</EasingDoubleKeyFrame.EasingFunction>
		</EasingDoubleKeyFrame>
	</DoubleAnimationUsingKeyFrames>
</Storyboard>

動きをチェックしながら作った、storyboard を手作業で C# のプログラムコードに直すは、結構手間です。しかも、Blend で回転やら移動やら BackEase やらと、いろいろなエフェクトを加えたので、なにがなにやら…って具合。しかも、プログラムのコードに落とした後、さらに Blend で直した日には、もう一度プログラムコードを手作業で直さないといけない、という辛い作業が待っています。これじゃあ、とても手軽に storyboard を使う、とは言えませんね。

で、最終的にどうしたのかというと、結果的には簡単でした。
Storyboard の変更したい箇所に「名前」(x:Name)を付ければ良かったのです。先の XAML をよくみると、「x:Name=”startPosX”」と「x:Name=”startPosY”」というふたつの名前がついてあります。自分の牌から出す場所が変更になるので、開始位置だけをプログラムで変更できれば良いのです。

XAML コントロールに名前を付けられるのは普通なのですが、この手の storyboard の要素にも名前が付けられるし、それをコードから参照できます。と言いますか、XAML コードのどの要素についても名前が付けられるわけですね、なるほど。

private void OnPaiToKawa(double x, double y, ImageSource image)
{
	// 移動開始位置を設定
    x += Canvas.GetLeft(myPai);
    y += Canvas.GetTop(myPai) ;
    startPosX.Value = x;
    startPosY.Value = y;
	// 牌の画像を設定
    animeImagePai.Source = image;
	// アニメーション開始
    sbAnimePai.Begin();
}

そんな訳で、開始位置を指定するだけになるので、プログラムコードは簡単になります。
Blend で作った Storyboard もそのまま活用できます、という両方の良いところが使えるようになります。

storyboard でアニメーションを作ったときの手順としては、

  1. 大まかな動きを Blend で作成する。
  2. 開始位置など、プログラムで制御したい部分に名前を付けておく。
  3. 再び、Blend で細かいアニメーションを追加していく。

という具合です。

こんな風に、Blend の Storyboard とプログラムコードの直書き(というか値の変更)ができますよ、っていう話です。
本来は、この storyboard 部分を別リソースにしたいんですけどね。このあたりは調査中。

カテゴリー: 雑談 | Storyboard の値をコードで動的に変更する はコメントを受け付けていません

Windows ストア アプリでパラパラアニメを動かそう

Windows 8 Store apps Advent Calendar : ATND
http://atnd.org/events/33803

の 15 日目のネタですね。本当は「親馬鹿アプリ」のほうにする予定だったのですが、ずるずる状態になってしまったので、以前ブログに書こうと思っていたネタを掘り出してきました。

最初に言うと「書こうと思っていた」というのは、まだ調査途中で「本当にこれが効率的なのか?」、「定番なのか?」ってのがわからないので、保留にしていたわけで…ええ、忘れていたのもぽちぽちなのですが、まあ、年末だし蔵出しということで。

さて、パラパラアニメといえば「アニメgif」なのですが、いろいろ調べてみると、WPF でうまく表示する方法がありません。いや、探せば「MediaElement」を使う方法がでているので、Windows ストア アプリでも使えるのかもしれません(試しておりません)。ですが、今回はもうちょっと違った方法を取ります。

よくゲームアプリで使われている手法で、俗に「うなぎの画像」と呼ばれる…って呼びませんね、なんと言うのかわからないのですが、横に長い画像を使います。ひとつひとつのセルを横につなげて、表示したい位置をスライドさせるという手法ですね。実は、C++/CX のほうには、これが使える Bitmap オブジェクトがあってそれが「ウリ」だったりすのですが、果たして C# にはあるのか?って、のを夏のセッションを聞いたときに思ったのですが、そのところはちょっと不明です。

ちなみに C# で WritableBitmap を作る方法は、

byte配列からWriteableBitmapオブジェクトを作成する – 酢ろぐ
http://d.hatena.ne.jp/ch3cooh393/20120802/1343892131

を参照ということで。

この「うなぎ画像」を使うと便利なのは、

  • それぞれのセルがひとつに連なっているので、管理が簡単?
  • 複数のセルを読み込まないで済むので、ロード時間が少なくて済む。

ってところです。実際、やってみるとわかるのですが、60 枚近い画像を切り替えるのと、1枚の画像をクリップしながら表示するのでは、CPU への影響が格段に違い、アニメーションもスムースになります。

というわけで、ざっと作り方を紹介。

■うなぎ画像を作る。

適当に Form アプリで「うなぎ画像」を作るツールを作ります。

private void button1_Click(object sender, EventArgs e)
{
    int w = 46*60;
    int h = 46;

    for (int n = 1; n <= 6; n++)
    {
        Bitmap allBmp = new Bitmap(w, h);
        Graphics g = Graphics.FromImage(allBmp);
        for (int i = 1; i <= 60; i++)
        {
            string p = string.Format(@"\temp\balls\{0}\{1:00}.png", n,i);
            Bitmap bmp = new Bitmap(p);
            g.DrawImage(bmp, 46 * (i - 1), 0, 46, 46);
        }
        allBmp.Save(string.Format( @"\temp\ball{0}.png",n));
    }
}

画像自体は、とあるゲームからパクってきたものです。
画像サイズが、46×46 固定なのは、まあ、ツールなので。

■アニメ用のユーザーコントロールを作る

いくつか試したのですが、ユーザーコントロールを作るのが一番楽です。

<UserControl
    x:Class="AniBallControls.AniBall"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:AniBallControls"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="92"
    d:DesignWidth="92">
	<UserControl.Resources>
        <Storyboard x:Name="sbAnime" RepeatBehavior="Forever">
			<DoubleAnimationUsingKeyFrames x:Name="keyFrames1" 
				Storyboard.TargetProperty="(Canvas.Left)" 
				Storyboard.TargetName="img">
                <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
		</Storyboard>
	</UserControl.Resources>
    <Canvas>
        <Image x:Name="img" Source="ms-appx:///balls/ball1.png" 
			Width="5520" Height="92" 
			Canvas.Left="0" Canvas.Top="0"/>
        <Canvas.Clip>
            <RectangleGeometry Rect="0,0,92,92"></RectangleGeometry>
        </Canvas.Clip>
    </Canvas>
</UserControl>

46×46 では、デモ用には小さかったので、96×96 に拡大しています。
storyboard を使ってアニメーションさせていますが、中身は後からプログラムで書きます。最初はツールを使って XAML に書いていたのですが、プログラムで書けることが分かったので実行時に書き込みます。
Canvas の上に乗っけて、Canvas.Clip しているところがミソですね。たぶん、WPF とか Silverlight での定番の処理だと思うのですが、似たようなは見つかりませんでした。他にいい方法があるのかも? この clip 位置を、スライドさせる(実際には Image オブジェクトの位置をずらす)ことで、アニメーションができます。

デザイナで見ると、うまくクリップされていることがわかります。本当は横に長い画像なのですが、一番左のセルだけがクリップされています。

で、実際にアニメーションさせるコードがこちら。

public sealed partial class AniBall : UserControl
{
    public AniBall()
    {
        this.InitializeComponent();
    }

    private Size _imageSize = new Size(92, 92);
    private int _curIndex = -1;
    private int _imageCount = 60;

    public ImageSource Source 
    {
        get { return this.img.Source; }
        set { this.img.Source = value; }
    }

    public void Start()
    {
        var kf = this.keyFrames1;
        kf.KeyFrames.Clear();
        for (int i = 0; i < _imageCount; i++)
        {
            var dd = new DiscreteDoubleKeyFrame();
            dd.Value = -_imageSize.Width * i;
            dd.KeyTime = new TimeSpan(10 * 1000 * i * (1000/60)); // 1/60 sec
            kf.KeyFrames.Add(dd);
        }
        this.sbAnime.Begin();
    }
    public void Stop()
    {
        this.sbAnime.Stop();
    }

    private void onTimer(object sender, object e)
    {
        _curIndex++;
        if (_curIndex >= _imageCount)
            _curIndex = 0;
        Canvas.SetLeft(this.img, - _imageSize.Width * _curIndex);
    }
}

普通の storyboard では、開始位置と終了位置を連続につなぎますが(直線とかスプラインとか)、ぱらぱらアニメの場合は、とびとびの値にします。この飛び飛びの値を作るのが DiscreteDoubleKeyFrame クラスですね。これは Blend の Storyboard でも変更できるので、ちまちま 60 フレーム作ることも可能なのですが…面倒なので、プログラムでやります。

この ontimer の負荷がどのくらいかというと、

なところで、3% 以下ですね。ひとつのアニメなので、複数配置したときはどうなるのかは検証していませんが、普通のアニメGIFっぽいことをしたいのであれば、これで OK かと。
ちなに、60 枚の画像切り替えをすると、CPU は 3% 程度で同じなのですが、画面の駒落ちが発生します。どうやら、Image.Source に設定するときが重いらしく、そのあたりの負荷を減らすためにも、一枚のうなぎ画像を使ったほうがよいみたいです。

■メインページを作る

テスト用のメインページには、こんな風に貼り付けます。ユーザーコントロールはツールバーに出てくるので、普通にドラッグ&ドロップすれば ok.

<local:AniBall x:Name="aniBall1" Source="ms-appx:///balls/ball1.png"
    HorizontalAlignment="Left" Height="100" 
                Margin="251,266,0,0" VerticalAlignment="Top" Width="100"/>

タップイベントを設定しておいて、開始と終了を制御します。

AniBall curBall = null;
private void aniBall_Tapped(object sender, TappedRoutedEventArgs e)
{
	if (curBall != null)
	{
		curBall.Stop();
		curBall = null;
	}
	else
	{
		curBall = sender as AniBall;
		curBall.Start();
	}
}

実は、Storyboard が実行中かどうかを取れるので、それをプロパティにすれば良いのですが…まあ、デモなので、これで。

■実行してみる

動かしてみると、結構スムースにくるくると回ります。これだったらゲームに使えるよねっていう感じで、これぐらいだったら、DirectX + C++/CX を使う必要はあるまい(本来はこれが目的)、っていう感じで動きます。

ちなみに、Image コントロールは、透過PNG を扱えるので、背景を付けることもできます。

これができると、パズルゲームぐらいならば、C# で書けそうですよね…って感じですかね。年末年始の休みを利用して、ひとついかがでしょうか? ええ、私は、たぶんお仕事かと orz.

カテゴリー: C#, windows 8 | Windows ストア アプリでパラパラアニメを動かそう はコメントを受け付けていません

Windows ストア アプリで親馬鹿アプリを作ろうッ!!!(準備編)

ふと、思いついたネタです…続くかどうかわかりませんが…ちなみに、アプリ自体はできています。

クリスマスに向けて、親馬鹿アプリを作ってクリスマスプレゼントの代わりにしよう企画~~~ぱぶぱふ~、ってことで、思いついたのでブログネタにしておきます。

絵本を読んでいて常々気になっていたのが、自分の娘や息子向けに作るというパターンです。絵の場合は、絵本を作ればいいけど、じゃあ、プログラマの親の場合はどうするのか?ってことで、じゃあ、自分の子供向けにアプリを作ればいいじゃないか?、ってところに至りました。

が、ノートパソコンは壊されると怖いし、デスクトップアプリだといまいち食いつきが悪いし、iPad のアプリでもいいんですが実機に乗せるには年会費が掛かるし(まあ、私の場合は払っているからいいんでけど)…ってことで、Windows 8 のタブレット PC の子供用アプリを作ります。

タブレット PC の値段が~、ってことなのですが、私の手元にあるのは acer w500。android のほうだと20,000円ってところなのですが、そこは windows 7 のほうの 40,000円のほうを買って、windows 8 に乗せ換えます。

[win8] Acer w500 に windows 8 cp をクリーンインストール(続き) | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/3304

なんかを参考にしてドライバーを入れ替えてください。

さて、どうせ家庭内で使うアプリ(しかも子供向け)なので、準備するものとしては、

  • タブレット PC 実機(もちろん windows 8)
  • Visual Studio 2012(Express でもok) + Widnows 8 マシン
  • 子供の写真(デジカメとか)
  • 子供の食いつきそうな版権もの(きかんしゃトーマスとかミッフィーとか)

ってところですかね。どこにも公開しないので、個人情報とか版権とか無視です。ええ、私家版ですから。

で、作ったアプリがこれ。スライドパズルです。

image

image

よく見ると、英語で「Shaffle」とか「Reset」とか書いてありますが、まあ、小2の娘はボタンを押せばなんとかわかるみたい。2歳児の息子は、16ピースだと難しいらしいのですが、ぽちぽちと正しい位置に置く(2つのピースをタップして、交換させます)をやろうとはしています。なので、4ピースぐらいにするのを計画中。

プログラム的には、MVVM っぽい形にしているのですが、失敗中。そのあたりも含めて、ソースコードを後日に公開します。プログラム自体は、C# で 300行弱といったところです。ピースと、ピースをまとめたボード、というユーザーコントロールを作っているので、画像の差し替えは比較的楽かな、とおもっているのですが…プログラム上

  • 画像の大きさが固定になっている
  • ピースの数が16ピース固定になっている

という問題があって(私家版なのでこれで良いのですが)、さきほどの2歳児用の4ピース版を作るためには…うーんと唸っている途中です。あと、画像自体はリソース組み込みなので、本当は SkyDrive に配置して、子供に選ばせたいですよね、とか考えてみたり。

と、サンデープログラマっぽいことができるのが、Windows ストア アプリの良いところかなあと気づいたりしております。

カテゴリー: C#, windows 8 | Windows ストア アプリで親馬鹿アプリを作ろうッ!!!(準備編) はコメントを受け付けていません

[win8] パンダ福笑いのインターフェースを考える

[win8] パンダ福笑いを作るために ManipulationDelta を使う | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/3877

の続きをざっくりと。プログラム的には、ManipulationDelta あたりを使って作るので、パーツのドラッグは簡単にできます。なぜ、手あるいは指でドラッグすることを考えるのかというと、iPad の初代を買ったときの動機から変わっていないのですが、

image

  • ディスプレイに直接タッチするのは、「直感的」である。
  • ディスプレイの操作に「記号」を持ち込まない。

というのが、子供用(あるいは幼児用)のインターフェースを考えるときの基本かなと感じています。うちの小2の娘は、生まれたころからパソコンがあるわけで、そのあと保育園のころから iPad が出てきたという感じです。つまりインターフェースとしては、マウスで画面を操作するの次に、タッチオペレーションが入るわけです。

マウスを使ってパソコンを操作できる時期ってのは、内田春菊の「わたしたちは繁殖している」を読むと分かる通り、2歳児でもできます。うちの場合は、3歳ごろからできたかなって感じです。マウスだと、マウス自体とマウスポインターが離れているから、という話が多いのですが、子供のとっては、

  • 無意識にマウス自体と、マウスポインタの動きを結びつける。

な感じで「無意識に」結び付けています。車のハンドルが、車自身を左右に動かすと直感的にわかる通り、マウスを動かすとマウスポインターが動くというのは比較的わかりやすいようです。マウスのクリックも意外とわかりやすいみたいです。手が小さいので、マウスボタンを押すときにマウス自体が動いてしまうのが工学的な難点ですかね。

ところが、もっと3歳児をみていると、もっと問題があって、

  • ボタンなどに書かれている「記号」がわからない

というのがあります。記号というのは「START」とか「STOP」とかのアルファベットもありますが、「1」とか「0」とかも記号です。実は「○」はわかりやすいのですが、「×」がわからなかったり「△」が難しかったりします。「×」がわからないので、ウィンドウを閉じる、という操作がなかなか覚えられないのですね。このあたり「記号」≒「言語」のところに関連していくので、年齢があがってきて、ひらがなを覚えると、「×」の意味がわかってきます。なので、目の前にある「記号」が大人にとって、どれだけ簡単であっても、それは「記号」としての「意味」がある限り、言語的に通じないために、コンピュータを操作できないというジレンマに陥ります。これは、Windows でも Mac でも同じみたいです。

その中で比較的わかりやすいのが、

  • 色を配置させる
  • ピクト(簡略化された絵を利用する)

色のほうは、まずは安全のために「信号機」を覚えさせます。赤がとまれ、緑あるいは青ですすめですね。このあたり、各国で色に対する「意味」が異なるので、それに沿う必要はないのですが、おおまかに「色」付きのボタンを配置させると、「何色のボタンを押す」ということで教えやすいのです。

もうひとつは、ピクトを使います。うちの2歳児はなぜかパス亭に表示されている「バスの絵」と実際のバスを即座に結び付けました。形が似ているという意識のなかの「似ている」を即座に判断するわけです。本物の写真から、ある特徴を誇張させたもの、ある特徴を取り出したもの、という具合ですね。

この「色」とか「ピクト(特徴の漫画化)」のところは、実は「記号」よりも成長の前段階にあるので、4歳児ぐらいまでには最適だと思っています。ある程度、ひらがなが「ひらがな」であることを理解して、「読む」という行為と別のものに置き換えて「理解する」という行為ができると、デザイン的な記号がわかってくるのですが、それ以前は、それが「記号」かどうかすらわからないのです。なので、子供向けには、下手なデザインをするよりも、「色」なり「ピクト」なりが重要かなと。

このあたり、もう別の日にもうちょっと続けます。

カテゴリー: windows 8 | [win8] パンダ福笑いのインターフェースを考える はコメントを受け付けていません

12/1 に八王子で「フューチャーワークス カンファレンスを開催」

直前の告知…と云いますか、準備不足と言いますか。時間の都合のつく方は是非。

13:00 から受付開始、13:30 からスタートという具合です。

講演もそうなんですが、リンクスさん提供のデモ機で実演するのと、その後の懇親会が主目的だったりします。日経BPさん、秀和システムさん、コルセアさんにプレゼントなど頂きましたので、それだけ欲しいッ!!! って物欲の方も歓迎です。もちろん、iPad mini のプレゼン目当てでも ok。

では、明日、八王子の「日本工学院八王子専門学校」にて。アクセスマップなんかは↓からどうぞ。

PP-Club Future work Conference 会場までのアクセス
http://musty2.hac.neec.ac.jp/events/ppc1_access/access.html

カテゴリー: 勉強会 | 12/1 に八王子で「フューチャーワークス カンファレンスを開催」 はコメントを受け付けていません

[win8] QX エディタを windows 8 のスタート画面に追加する方法

何も、QX Editor に限らないのですが、普通のデスクトップアプリのツール(インストーラがなくて、Program Files フォルダに入らないツール)は、Win キーの検索では引っかからないので、ならば、スタート画面にショートカットを置けばよいのだ、ということに気づいた、という話。

[win8] Windows 8 でアプリの検索 | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/3897

これの応用技です。

まず、QX Editor のショートカットを作ります。私の場合、c:\tools\newqx フォルダにおいてあるので、アプリの検索に引っかからないんですよね。

image

右クリックして「スタート画面にピン留め」を選択します。

image

こんな風にスタート画面に

image

ここで、アイコンをクリックしてもいいのですが、面倒なので、Win キーを押したあとに、いきなり「qx」と打てば、

image

と検索にマッチしたら「Enter」キーで実行という具合。

image

なるほど、これだとわざわざデスクトップに戻らなくてもいいし、他の名前でマッチングさせるのも簡単です。たとえば「リモートデスクトップ接続」って、「remote」では検索ができなくて「リモート」とカタカナで打たないと検索にマッチングしないのですが、「remote desktop」とかいう名前でショートカットを作って、スタート画面に置いておけばアプリの検索にマッチングさせることができる訳です。

カテゴリー: windows 8 | [win8] QX エディタを windows 8 のスタート画面に追加する方法 はコメントを受け付けていません

[win8] SkyDrive の活用法をいくつか紹介

最近は、大きなファイルを転送するのに、宅ファイル便や、その他のストレージサービスを必要としなくなりました、で、もっぱら SkyDrive でやりとりです、という話を。

image

SkyDrive を使う前は、Dropbox を使っていたのですが、iPhone, iPad で SkyDrive が使えるよ、ってことが分かってから、mac にも SkyDrive がはいっています。

■Mac から画面キャプチャ, プログラムのソースを win 8 に。

Mac で撮った画面キャプチャをがんがんと SkyDrive に入れます。多少、タイムラグがあるのですが、Windows 8 のフォルダーで受け取ります。

image

メインで使っているのが Windows 8 マシンなので、Mac のほうは執筆のため、iPhone プログラミング用ってことで Xcode ぐらいしか入っていません(ためしに、Excel だけ入れた覚えが)。
なので、画像の編集やら、ファイル名の変更、ソースコードの修正なんかは Windows のほうでやるわけです。

image

 

■Excel の予定表を iPhone で確認する

これも iPhone 絡みですが、SkyDrive のアプリを iPhone に入れておくと、Excel の閲覧ができます。編集はできないのですが、閲覧で十分です。そもそも、あの小さな画面で、全体の更新は無理なので、そのあたりは「閲覧」に特化したほうがよいかと。

image

なので、特に Excel 互換アプリをいれずに、SkyDrive から直接閲覧だけをさせています。外でみられるし、いろいろ確認ができるので便利です。更新自体は、パソコンのほうで Excel で編集すれば OK ってことで。

■メールの添付がわりに使う。他人と共有する。

ブラウザのほうからですが、フォルダの共有をしておくと、大きなファイルをメールに添付せずにすみます。以前は、宅ふぁいる便とかストレージサービスを利用しているたのですが(SkyDrive 自体もストレージサービスなんですが)、ここで、共有のフォルダの URL を取得して、短縮した後にメールに URL を貼ります。

image

相手に見せるだけであれば、閲覧だけで。何か返してもらう場合には、編集可能の URL を送ります。

■写真フォルダとして使う

一番、お手軽なのが写真フォルダの公開ですね。身内だけに公開したい場合には、URL だけメールで知らせれば OK です。パソコンで見ていれば、元の大きさでダウンロードができるので、プリンターに印刷するのも自由というわけで。まあ、セキュリティ的にどうとか…という話もあるので、期間限定にしておくと無難かと。下記は、うちの娘の保育園のときの集まりです。

image

デスクトップ版の IE で見ると、こんな風にブラウジングできます。

image

ちなみに、Windows 8 の SkyDrive では、全画面でカーソルを使って閲覧できます。一応、スナップにも対応しています。

image

こんな感じで使っているよ、という紹介でした。

カテゴリー: 雑談 | 1件のコメント

[win8] OpenStreamForWriteAsync は上書きモードで開くので注意せよ

StorageFile の Open は、通常の Open/Close とちょっと違う | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/3880

の続きです。

Windows ストア アプリでは、fopen/fclose のようにファイル名を指定して、ファイルの読み書きができません。サンドボックス的なセキュリティを維持するために常に StorageFile クラスを使います。このクラスは、アプリ ローカルのフォルダから直接作るか、ピッカー(FileSavePicker など)を使って作ります。

ってのが前回の話で、FileSavePicker から戻ってきたときには、ファイルが既に作られています、ってのがちょっとした「落とし穴」なのです。

■ピッカーで保存先のファイルを選択

ピッカーを使って、デスクトップに保存するファイルを選んでね、ってのが次のコードです。

private StorageFile _file;
/// <summary>
/// ファイル選択のみ
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void Button_Click_0(object sender, RoutedEventArgs e)
{
	// FileSavePicker を用意する
	var picker = new FileSavePicker();
	picker.CommitButtonText = "データを保存する";
	picker.DefaultFileExtension = ".txt";
	picker.FileTypeChoices.Add("テキスト形式", new string[] { ".txt" });
	picker.SuggestedStartLocation = PickerLocationId.Desktop;
	picker.SuggestedFileName = "Sample.txt";
	// FileSavePicker を出して、ファイルを指定する。
	StorageFile file = await picker.PickSaveFileAsync();
	if (file == null)
	{
		// キャンセルされたときは何もしない
		return;
	}
	_file = file;
}

ピッカーの PickSaveFileAsync メソッドの戻り値は、StorageFile オブジェクトなので、キープしておくと、あとから利用できます。いわゆる2度目に「保存」ボタンを押したときには、ユーザーに問い合わせをしない、ことが可能です。上書き保存ってやつです。

ここで、保存先のファイルってのは新規ファイルとは限らなくて、存在するファイル(中身があるファイル)でも ok なわけです。まあ、そうですよね。なので PickSaveFileAsync メソッドからの戻りは、

1.PickSaveFileAsync が作った空ファイル(サイズ 0 のファイル)
2.元からある、いくらかのサイズのファイル。
3.元からある、サイズ 0 のファイル

ここで、1 と 3 の区別(新規ファイルなのか、既存ファイルなのか)がつかないのが問題…になるかもしれんッ!!! と思ったわけですが、これから上書きしようとするわけだし、どっちでも構わないんじゃない?というのが設計思想のようです。

■保存するモデル

アプリのデータを DataModel にしておきます。

public class DataModel : BindableBase
{
	private int _id;
	public int ID
	{
		get { return _id; }
		set { _id = value; this.SetProperty(ref this._id, value); }
	}
	private string _name;
	public string Name
	{
		get { return _name; }
		set { _name = value; this.SetProperty(ref this._name, value); }
	}
}

画面のほうには、適宜 Binding を書く、というパターンですね。
クラスにしておくとシリアライズが楽なので。Windows ストア アプリの場合は、DataContractSerializer を使うと便利です。

■DataContractSerializer を使う

モデルデータを、そのままシリアライズするのが一番楽です。既に用意されている DataContractSerializer を使って、WriteObject メソッドを使って XML 形式で書き込めば okですね。

private async void Button_Click_1(object sender, RoutedEventArgs e)
{
	StorageFile file = this._file;	// 選択済み
	var data = new DataModel()
	{
		ID = 10,
		Name = "masuda tomoaki"
	};
	// これは正常に動く
	using (var stream = await file.OpenStreamForWriteAsync())
	{
		var serializer = new DataContractSerializer(typeof(DataModel));
		serializer.WriteObject(stream, data);
	}
}

ただ、DataContractSerializer クラスで書き出す XML って、改行とかインデントがついていなくて、デバッグに不都合があるのです。
なので、XmlWriter を使えば整形できるのでは?と思ったのが、ハマリどころです。

■XmlWriter を使う

XmlWriter を使って整形(改行やインデント)を使いながら、書き出します。

private async void Button_Click_2(object sender, RoutedEventArgs e)
{
	StorageFile file = this._file;	// 選択済み

	var data = new DataModel()
	{
		ID = 10,
		Name = "masuda tomoaki"
	};
	// これは正常に動く
	using (var stream = await file.OpenStreamForWriteAsync())
	{
		var serializer = new DataContractSerializer(typeof(DataModel));
		// ストリームを切り詰める
		stream.SetLength(0);		// これが必須
		// インデント等を設定する
		var st = new XmlWriterSettings();
		st.Indent = true;
		st.IndentChars = "\t";
		st.Async = false;        // 書き込み時に async を使わない
		using (var xw = XmlWriter.Create(stream, st))
		{
			serializer.WriteObject(xw, data);
		}
	}
}

この中で「stream.SetLength(0)」ってのがあります。これ、ファイルは「新規だ」と思っていると、実は違っていて「既存のファイル」かもしれないのです。で、既存のファイルを OpenStreamForWriteAsync メソッドで開くと、中身はそのままオープンって具合なわけです。

なので、もし既存のファイルよりも短い XML を書き込んだ場合、最後の閉じタグの後ろにゴミが残るんですよね…これはかなりはまりました。
fopen 関数だと、新規オープンなのか、追加オープンなのかの選択があるのですが、実は OpenStreamForWriteAsync には、その選択肢がないのです。さらに、PickSaveFileAsync では、新規のファイルでも 0 バイトのファイルができるし。
OpenStreamForWriteAsync の場合は、ファイルをオープンすると、先頭にカーソル位置が置かれるのですが、これは既存ファイルをオープンしたときも先頭にカーソルがあります。ってのが落とし穴ですね。

なので、この変な状態を解決するために「新規ファイル」として扱うためには「stream.SetLength(0)」のように、ストリームの長さを 0 に初期化する必要があるのです。

■テキストファイルに保存

そんな訳で、メモ帳のようなテキストファイルを扱うアプリを作ると更にはまります。

private async void Button_Click_3(object sender, RoutedEventArgs e)
{
	StorageFile file = this._file;	// 選択済み
	// 実は上書きモードでオープンしている
	using (var stream = await file.OpenStreamForWriteAsync())
	{
		// 新規扱いの場合は、サイズを 0 にする必要あり
		stream.SetLength(0);

		using (var writer = new StreamWriter(stream))
		{
			// テキストをそのまま書き込み
			writer.Write(text1.Text);
		}
	}
}

毎回、全体を保存するから、StreamWriter クラスの Write メソッドで書き出せば ok … と思いきや、この「stream.SetLength(0)」を忘れると、もともとあったファイル長さよりも文章(text1.Text)の方が短い場合には、後ろにごみが残るのです。

■Stream にも StreamWriter にも Close がない

で、Stream も StreamWriter も Close がありません。Open したら Close したくなるものなのですが、まあ、開きっぱなしでいいみたいです。というか、using で範囲を決めないとダメかもしれませんね。
テキストの書き込みだと、StreamWriter クラスの using で抜けるときに、同時に Stream のほうも閉じてくれます…と云いますか、閉じてしまいます。これは、以前からの仕様だったような気がします。

なので、ファイルの後ろを切り詰めようとして次のように書くとエラーになります。

private async void Button_Click_3(object sender, RoutedEventArgs e)
{
	StorageFile file = this._file;	// 選択済み
	// 実は上書きモードでオープンしている
	using (var stream = await file.OpenStreamForWriteAsync())
	{
		using (var writer = new StreamWriter(stream))
		{
			// テキストをそのまま書き込み
			writer.Write(text1.Text);
		}
		// 現在位置で切り詰める
		stream.SetLength( stream.Position );	// ★
	}
}

★の位置では、stream が閉じられちゃっているので、SetLength できません。
下記のように、StreamWriter のブロックで SetLength するとうまく動きます。

private async void Button_Click_3(object sender, RoutedEventArgs e)
{
	StorageFile file = this._file;	// 選択済み
	// 実は上書きモードでオープンしている
	using (var stream = await file.OpenStreamForWriteAsync())
	{
		using (var writer = new StreamWriter(stream))
		{
			// テキストをそのまま書き込み
			writer.Write(text1.Text);
			// 現在位置で切り詰める
			stream.SetLength( stream.Position );	// ★
		}
	}
}

これもなんか変な仕様ですよね…と思いつつ、まぁ、いいかと。

OpenStreamForWriteAsync メソッドに、新規バージョンと追加バージョンがあればわかりやすいんですがね。

・OpenStreamForNewWriteAsync()
・OpenStreamForAppendWriteAsync()

のような名前にすればよかったのに。。。まあ、拡張メソッドを2,3行書けば、済むはなしなんですが。

カテゴリー: C#, windows 8 | 1件のコメント

[win8] コントロールパネルの表示方法

もともと、Windows 7 でもコントロールパネルを「クラシック表示」にしているので、あれ?どこに行ったっけ?というよりも「コントロールパネル」自身の構造を知っているので、メインのコントロールパネルを開けばなんとかなるのですが…、じゃあ、Windows 8 ではコントロールパネル自身はどうやって開くのか?っていうのを、忘れるのでメモがてらに。

Win + I キーを押すと、左に設定画面がでるので、ここに「コントロールパネル」が…あるのです。

image

あるけど…忘れますよね。ショートカットはショートカットなので、あまり覚えてられないので…

デスクトップの画面の左下で右クリックすると、コントロールパネルもろもろのメニューが出ます。

image

まあ、わかりやすいと言えば、わかりやすいですね。スタートボタンの代わりのような気もするし、よくわからないコンピュータの設定関係は、ここにある、と覚えておけばいいわけです。

が、もうひとつ、いいことがあって、Win キーを押して、スタート画面で「コントロール」で検索させます。ほら、コントロールパネルがありますね。

image

まあ、もっといいほうほうは、この「コントロール パネル」を右クリックして、アプリ バーを出して、「スタート画面にピン留め」するのがいいですね。

image

こんな風に、スタート画面においておけば忘れないでしょう。たぶん(置いたこと自体を忘れる可能性もありますが)。

image

まあ、そんなときは、

[win8] Windows 8 でアプリの検索 | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/3897

で書いたように、「設定」から検索するってのがおすすめです。

カテゴリー: windows 8 | [win8] コントロールパネルの表示方法 はコメントを受け付けていません

[win8] Windows 8 でアプリの検索

Windows 8 に「スタート」ボタンは要らない、という構造 | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/3711

で、「Windows 8 はひょっとしてキーボードが主流?」ってところを書きましたが、実際のところどうやって、つかうのか?ということをいくつか。最近、Windows 8 に移行させて、Visual Studio + QX + まめ5File  + Excel などなど、と併用しているときの感想です。

Windows 7 でおなじみだった「スタートボタン」がなくなって「スタート画面」になったわけですが、このスタート画面を使って「アプリを探し出す」ってことをやってません。強いて言えば、Win キーを押したときに、左にあるボタンのいくつか、を目標にしてクリックします。

image

この画面でいえば、左上の「デスクトップ」だけですね w 。画面が真っ黒なのは、背景画像を「黒」にしているからです。

さて、他はどうしているかとうと、デスクトップのアイコンから…って訳ではなくて、スタート画面の検索機能を直接使います。Win キーを押して、直接「vi」と打てば、

image

こんな風に、Visual Studio 2012 が見つかります。

image

Excel の場合は、「Ex」と打ったぐらいで、見つかります。

image

これは「設定」の場合も同じで、左のアイコンを「設定」にして切り替えれば、たとえばマウス関係を調べたいときには、「mouse」にすれば、

image

こんな感じで絞り込めます。という話です。アプリ名とだいたいの設定で絞り込んでいくと、わかりやすいし、おおまかな検索から絞り込めるので、重宝しています。

カテゴリー: windows 8 | 2件のコメント