Archive for 2012年3月

Data Binding

2012年3月30日

デフォルトでは、Mode=OneWay

<Grid x:Name=”ContentPanel” Grid.Row=”1″ Margin=”12,0,12,0″ Loaded=”ContentPanel_Loaded”>
    <StackPanel Name=”stackPanel1″>
        <TextBox Name=”textBox1″ Text=”{Binding TimeString, Mode=TwoWay}”/>
                <Button Content=”Button” Name=”button1″  Click=”button1_Click” />
        <TextBox Name=”textBox2″ Text=”{Binding X, Mode=TwoWay}”/>
    </StackPanel>
</Grid>

using System;
using System.Windows;
using Microsoft.Phone.Controls;
using System.Windows.Threading;
using Microsoft.Devices.Sensors;
using System.ComponentModel;

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

        private void ContentPanel_Loaded(object sender, RoutedEventArgs e)
        {
            ContentPanel.DataContext = new MyTime();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            ((MyTime)ContentPanel.DataContext).TimeString = DateTime.Now.ToLongTimeString();
            ((MyTime)ContentPanel.DataContext).X += 1;
        }
    }

    public class MyTime : INotifyPropertyChanged
    {
        private String _timeString;
        public event PropertyChangedEventHandler PropertyChanged;

        public String TimeString
        {
            get { return _timeString; }
            set
            {
                _timeString = value;
                NotifyPropertyChanged(“TimeString”);
            }
        }

        private double _x;
        public double X
        {
            get { return _x; }
            set
            {
                _x = value;
                NotifyPropertyChanged(“X”);
            }
        }

        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

DispatcherTimer

2012年3月30日

毎回、面倒なので。

using System.Windows.Threading;

DispatcherTimer timer = new DispatcherTimer();

private void ContentPanel_Loaded(object sender, RoutedEventArgs e)
{
    timer.Interval = new TimeSpan(0, 0, 1);
    timer.Tick += new EventHandler(timer_Tick);
    timer.Start();
}

void timer_Tick(object sender, EventArgs e)
{
    …
}

GeoCoordinateWatcher

2012年3月28日

System.Deviceを参照に追加する必要があります。

using System;
using System.Windows;
using Microsoft.Phone.Controls;
using System.Device.Location;

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

GeoCoordinateWatcher geoWatcher = new GeoCoordinateWatcher();

private void button1_Click(object sender, RoutedEventArgs e)
{
geoWatcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(geoWatcher_PositionChanged);
geoWatcher.Start();
}

void geoWatcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
this.textBox1.Text = String.Format(“Latitude: {0:F13}\r\n” +
“Longitude: {1:F13}\r\n” +
“Altitude: {2}\r\n” +
“Course: {3}\r\n” +
“Speed: {4}\r\n” +
“HorizontalAccuracy: {5}\r\n” +
“VerticalAccuracy: {6}\r\n” +
“{7}”,
e.Position.Location.Latitude,
e.Position.Location.Longitude,
e.Position.Location.Altitude,
e.Position.Location.Course,
e.Position.Location.Speed,
e.Position.Location.HorizontalAccuracy,
e.Position.Location.VerticalAccuracy,
e.Position.Timestamp);
}
}
}

WritableBitmap

2012年3月28日

It’s just for my memo.

using System;
using System.Windows;
using System.Windows.Media.Imaging;
using Microsoft.Win32;

namespace WritableBitmap
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        WriteableBitmap srcWritableBitmap;
        WriteableBitmap destWritableBitmap;

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            LoadImage();
            Process();
        }

        float[,] filter = {
                          { 1 / 25f, 1 / 25f, 1 / 25f, 1 / 25f, 1 / 25f },
                          { 1 / 25f, 1 / 25f, 1 / 25f, 1 / 25f, 1 / 25f },
                          { 1 / 25f, 1 / 25f, 1 / 25f, 1 / 25f, 1 / 25f },
                          { 1 / 25f, 1 / 25f, 1 / 25f, 1 / 25f, 1 / 25f },
                          { 1 / 25f, 1 / 25f, 1 / 25f, 1 / 25f, 1 / 25f }
                          };

        private void Process()
        {
            int width = srcWritableBitmap.PixelWidth;
            int height = srcWritableBitmap.PixelHeight;
            int bytesPerPixel = srcWritableBitmap.Format.BitsPerPixel / 8;

            int srcPtr = (int)srcWritableBitmap.BackBuffer;
            int destPtr = (int)destWritableBitmap.BackBuffer;

            for (int y = 2; y < height-2; y++)
                for (int x = 2; x < width-2; x++)
                    for (int col = 0; col < bytesPerPixel; col++)
                    {
                        int destIndex = destPtr + width * bytesPerPixel * y + bytesPerPixel * x + col;

                        if (y < height/3 || y > (height/3)*2)
                        {
                            float v = 0f;

                            for (int yy = -2; yy <= 2; yy++)
                                for (int xx = -2; xx <= 2; xx++)
                                {
                                    int srcIndex = srcPtr + width * bytesPerPixel * (y + yy) + bytesPerPixel * (x + xx) + col;

                                    float filterValue = filter[yy + 2, xx + 2];

                                    unsafe
                                    {
                                        v = v + (*((byte*)srcIndex) * filterValue);
                                    }
                                }
                            v = Math.Abs(v);
                            v = (v > 255) ? 255 : v;
                            unsafe
                            {
                                *((byte*)destIndex) = (byte)v;
                            }
                        }
                        else
                        {
                            int srcIndex = srcPtr + width * bytesPerPixel * y + bytesPerPixel * x + col;
                            unsafe
                            {
                                *((byte*)destIndex) = *((byte*)srcIndex);
                            }
                        }
                    }
            resultImage.Source = destWritableBitmap;
        }

        private void LoadImage()
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = “Bitmap files|*.bmp;*.png;*.jpeg;*.jpg;*.gif;*.tiff;*.tif;*.wdp|” +
                         “BMP files (*.bmp)|*.bmp|” +
                         “PNG files (*.png)|*.png|” +
                         “JPEG files (*.jpeg, *.jpg)|*.jpeg;*.jpg|” +
                         “GIF files (*.gif)|*.gif|” +
                         “TIFF files (*.tiff, *.tif)|*.tiff;*.tif|” +
                         “Windows Media Player files (*.wdp)|*.wdp|” +
                         “All files (*.*)|*.*”;

            if ((bool)dlg.ShowDialog())
            {
                srcImage.Source = null;
                srcWritableBitmap = null;
                BitmapFrame frame = null;

                try
                {
                    frame = BitmapFrame.Create(new Uri(dlg.FileName), BitmapCreateOptions.None,
                                                                      BitmapCacheOption.None);
                }
                catch (Exception exc)
                {
                    MessageBox.Show(exc.Message, Title);
                    return;
                }

                srcWritableBitmap = new WriteableBitmap(frame);

                if (srcWritableBitmap.Format.BitsPerPixel != 8 &&
                    srcWritableBitmap.Format.BitsPerPixel != 24 &&
                    srcWritableBitmap.Format.BitsPerPixel != 32)
                {
                    MessageBox.Show(“Bitmap must have 8 or 24 bits or 32 bits per pixel”, Title);
                    srcWritableBitmap = null;
                    return;
                }
                srcImage.Source = srcWritableBitmap;
                destWritableBitmap = srcWritableBitmap.Clone();
            }
        }
    }
}

Metroなクラウディアさん

2012年3月25日

Atelier:Mitsuba 

http://d.hatena.ne.jp/c-mitsuba/20120321

http://dl.dropbox.com/u/1321204/cloudia_metro.ai

どこかで見たので、拾いに行ったらば、なかなか見つからずだいぶ探してしまったので・・・メモ。

image

Windows Phone 7 で効果音を鳴らす

2012年3月25日

Windows Phone 7 で効果音を鳴らす方法

プロジェクトのフォルダー(ここでは、Audio)を作成し、音声ファイルを登録する。

image

ビルドアクションは、”Resource” にセットする。

image

XAMLでMediaElement を配置し、次のコードを呼ぶだけ。

mediaElement1.Source = new Uri(“Audio/37ah.wav”, UriKind.Relative);
mediaElement1.Play();

この時、,戻るボタンを長押しすることによって高速なタスク切り替えが可能ですが、この処理はかなり特殊なことを行っているようで、 MediaElelement の Source を再セットしないと音が鳴らないようです。

Windows Phone 7 アナログクロックを作ってみました

2012年3月24日

アナログ時計を作ろう! (プログラミングの知識がある方向け)

を見ながら、Windows Phone アナログクロックを作ってみました。

30分ぐらいで、できてしまいました。

ストーリーボードで時計の秒針を描画しているので、秒針がとても滑らかに動きます。

解説ページのおわりの部分に、「このアナログ時計は、針を動かす部分は XAML に全て任せてしまう作りになっています。Windows Phone アプリケーションの開発では、こういった発想、閃きが大切になってくるのではないでしょうか。」とコメントしてありますが、その通りですね。XAML をいかに使いこなせるかが、すごく重要ですね。

image

それから、今回のアナログクロックを実機で動作させてみたところ、いったん別のアプリを起動して、もとのアナログクロックに制御を戻すと、時間がずれてしまう問題があることがわかりました。この原因は、他のアプリケーションに切り替わってDeactivate されると、ストーリーボードの更新が停止するためです。その後、Activate されて制御が戻ると、ストーリーボードの時計が止まったところから、描画が再開されるため、時間がずれたまま時計が表示されてしまいます。

対応としては、Windows Phone に画面制御が戻った段階で、LayoutUpdated イベントが発生しますので、そこでもう一度クロックをセットしなおしてあげればよいと思います。コードはつぎのようになります。

using System;
using Microsoft.Phone.Controls;

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

        private void PhoneApplicationPage_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            SecondMove.Begin();
            MinutesMove.Begin();
            HourMove.Begin();
        }

        private void PhoneApplicationPage_LayoutUpdated(object sender, EventArgs e)
        {
            SetClock();
        }

        private void SetClock()
        {
            int second = DateTime.Now.Second;
            SecondMove.Seek(new TimeSpan(0, 0, second));
            int minutes = DateTime.Now.Minute;
            MinutesMove.Seek(new TimeSpan(0, minutes, second));
            int hour = DateTime.Now.Hour;
            HourMove.Seek(new TimeSpan(hour, minutes, second));
        }
    }
}

Windows Phone 加速度センサー

2012年3月24日

Windows Phoneアプリケーション開発入門

CH3COOH(酢酸)の第24回 加速度センサーを使ってみよう! を参考に、初めてのWindows Phone センサーアプリを同じように作ってみました。

エミュレータで、簡単にデバイスの方向をセットすることができます。

image

それにしたがって、どのような方向にデバイスが向いているのか、リアルタイムでエミューレーションできるのは知っていましたが、実際に動かしてみると、やっぱりすごいなぁ・・・

image

なお、accelerometer.ReadingChanged メソッドが、accelerometer.CurrentValueChanged に変更になっていたので、それに伴って少し実装を変える必要がありました。一応 2012/3 時点での対応コードをメモっておきます。

using System;
using System.Windows;
using Microsoft.Phone.Controls;
using Microsoft.Devices.Sensors;

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

        Accelerometer accelerometer;

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            // インスタンスの生成
            accelerometer = new Accelerometer();
            // 加速度センサの値が変化時した際に通知されるイベントにハンドラを登録
            accelerometer.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<AccelerometerReading>>(accelerometer_CurrentValueChanged);       
            // 加速度センサデバイスのデータ取得の開始
            accelerometer.Start();
        }

        void accelerometer_CurrentValueChanged(object sender, SensorReadingEventArgs<AccelerometerReading> e)
        {
            // 別スレッドからのアクセスになるのでInvoke
            Deployment.Current.Dispatcher.BeginInvoke(() => MyReadingChanged(e));
        }

        void MyReadingChanged(SensorReadingEventArgs<AccelerometerReading> e)
        {
            XTextBlock.Text = e.SensorReading.Acceleration.X.ToString(“0.00”);
            YTextBlock.Text = e.SensorReading.Acceleration.Y.ToString(“0.00”);
            ZTextBlock.Text = e.SensorReading.Acceleration.Z.ToString(“0.00”);
        }

        private void PhoneApplicationPage_Unloaded(object sender, RoutedEventArgs e)
        {
            // 加速度センサデバイスのデータ取得の終了
            accelerometer.Stop();
            accelerometer = null;
        }
    }
}

Windows Phone 7 向けの初めての XNA アプリケーションを作成する

2012年3月20日

遅ればせながら、Windows Phone 7 の開発をしてみることにしました。試しに、http://msdn.microsoft.com/ja-jp/events/ff728584.aspx
に従って、初めてのWindows Phone 7 XNA アプリケーションを作ってみました。

あとから気が付きましたが、英語版のビデオを大西さんが日本語版で作り直していたんですね。日本語版はこちら XNA と Windows Phone 7 です。

XNA and Windows Phone 7

すごく簡単にできてしまうんですね。おまけに、Phone 7 のエミュレーターがヌルヌル動くのにはびっくりしました。

少し調べてみると、先日お亡くなりになられたマイクロソフトの川西さんのブログで、XNA 2D ゲーム チュートリアル (Windows Phone 7)の記事を見つけました。もっといろいろ教えてほしかったのですが、残念です。

パワポ職人芸シリーズ

2012年3月19日

日本マイクロソフトのエバンジェリスト長沢智治さんのブログより。

■パワポ職人芸シリーズ:
パワポ職人芸 Vol.1 – 図形の合成を活用せよ
パワポ職人芸 Vol.2 – グループ化と白黒/グレースケールの罠にはまらない
パワポ職人芸 Vol.3 – 画像のトリミングと背景の削除を活用せよ
パワポ職人芸 Vol.4 – アニメーションを使わないアニメーションを活用せよ
パワポ職人芸 Vol.5 – PowerPoint で動画作成せよ ~ JaSST’12 Tokyo セッション資料を公開

■パワポ職人芸 番外編