Silverlight 2で.NET技術をカッコよく使おう
連載インデックスへ

Silverlight 2で.NET技術をカッコよく使おう(4)

Silverlight 2で落書きアプリを作るための5つのテク


インフラジスティックス・ジャパン株式会社
デベロッパー エバンジェリスト 山田 達也
2009/4/27
連載「.NETを知らない人でも分かるSilverlight入門」の続編のSilverlight 2入門連載です。Silverlightで.NET技術をよりカッコよく簡単に使えるRIAを作ってみましょう。Silverlightそのものについて詳しく知りたい読者は、本稿と併せて特集「Silverlightは次世代のJavaScriptフレームワーク?」もご参照ください(編集部)

まずは、Silverlightで作る落書きアプリを試してみよう

 連載第2回の「無料Visual Studioで始めるSilverlight 2超入門」、第3回の「デザインツールで始めるSilverlightアニメ/グラフィック」では、Silverlight 2開発の基本と、コントロールアニメーションの基礎的な部分を説明しました。

 今回は、簡単なSilverlightアプリケーションのコードを例に取りながら、Silverlightの画面デザインに欠かせない要素を解説します。題材としては、下記のような簡単なお絵描きアプリケーションを作ります。

Silverlightの落書きアプリケーション(もっと大きな画面で見たい場合はこちらサンプルを動かすには、事前に実行環境のインストールが必要です。→ダウンロードページ

 このアプリケーションの主な機能は、次の3つです。

  • ローカルから選択した画像(JPGかPNG形式)の上に自由に落書きをする
  • 落書き用のペンの色と太さを自由に変更できる
  • 作った落書きデータをローカルに保存する

 今回はソースコードの説明が若干多くなっています。コードと動作を詳しく比べてみたい方は、ソースコードをダウンロードしてVisual StudioまたはVisual Web Developer上で動かしながら確認してください。以下、5つのテクニックに分けて解説します。

  1. インク機能でお絵描きをするには?
  2. テンプレートでコントロールの見た目を変えるには?
  3. コントロールの状態に応じた見た目を設定するには?
  4. 見た目をCSSのように独立して設定するには?
  5. 落書きをローカルPC上に保存するには?

【1】インク機能でお絵描きをするには?

 まずは、このアプリケーションの主な目的である、落書き機能の部分から実現してみましょう。

「手描き」を実現するためのコントロール「InkPresenter

 Silverlightでは、マウスやスタイラスといった入力デバイスを使った「手描き」を実現するためのコントロールとして「InkPresenter」が用意されています。このInkPresenterはCanvasと同様に、ほかのコントロールのコンテナとして機能しますが、同時に手描き入力された情報を保持できるコントロールです。

 このInkPresenterと画像表示用のImageコントロール、そして最低限必要なボタンを配置した例が、以下のXAMLです。

<UserControl x:Class="SimpleInkPresenter.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="350">
<StackPanel x:Name="LayoutRoot" Background="White">
<!-- InkPresenter -->
<InkPresenter x:Name="inkP" Width="400" Height="300"
MouseLeftButtonDown="inkP_MouseLeftButtonDown"
MouseMove="inkP_MouseMove"
MouseLeave="inkP_LostMouseCapture"
LostMouseCapture="inkP_LostMouseCapture">
<!-- このImageオブジェクトに選択した画像を設定します -->
<Image x:Name="image" Stretch="Fill" Width="400" Height="300" />
</InkPresenter>
<StackPanel Orientation="Horizontal" Height="40" >
<Button x:Name="imageSelect" Content="画像を選択" Width="100" Margin="2" Click="imageSelect_Click"></Button>
<Button x:Name="clearPaint" Content="落書きをクリア" Width="100" Margin="2" Click="clearPaint_Click"></Button>
<TextBlock x:Name="selectedImage"></TextBlock>
</StackPanel>
</StackPanel>
</UserControl>

Clickイベントに対してイベントハンドラを定義

 落書きアプリケーションにおける最初のユーザーの仕事は、落書き対象となる画像を選択することです。「OpenFileDialog」コントロールを使うことで、クライアント上の任意のファイルを選択し読み込めるので、ボタンのクリックイベントのタイミングでダイアログを表示し、ユーザーに選択を促すことにしましょう。

 次のコードでは、imageSelectボタンのClickイベントに対して以下のイベントハンドラを定義し、この中で選択されたファイルをBitmapImageオブジェクトに設定し、画面上のImageコントロールのソースとして設定しています。

// 画像を選択ボタン クリック
private void imageSelect_Click(object sender, RoutedEventArgs e)
{
this.selectedImage.Text = null;
OpenFileDialog dialog = new OpenFileDialog();
dialog.Multiselect = false; //単一選択
bool? dialogResult = dialog.ShowDialog();
if (!dialogResult.HasValue || !dialogResult.Value)
{
return; //ファイルが選択されなかったときは何もしない
}
try
{
//選択した画像ファイルを読み込み、
BitmapImage source = new BitmapImage();
source.SetSource(dialog.File.OpenRead());
//Imageのソースに設定
this.image.Source = source;

this.selectedImage.Text = dialog.File.Name;
}
catch
{
MessageBox.Show("画像が正しく読み込めませんでした");
}
}

マウスアクションに対応するイベントを手動でハンドル

 次に、InkPresenterの実装部分を詳しく見てみましょう。先ほどのXAMLの中に、InkPresenterのマウスイベントがいくつか定義されているのに気付いたかもしれませんが、InkPresenter上でのマウス(または、スタイラス)アクションに対応するイベントは手動でハンドルする必要があります。といっても、大して難しいことではなく、以下の流れに沿ってコーディングするだけです。

  1. InkPresenter上でマウスの左ボタンが押されたとき、新しく描画情報のオブジェクト(Stroke)を作成してInkPresenterのStrokesコレクションに追加
  2. InkPresenter上でマウスが移動されたとき、処理中のStrokeに現在の位置を追加
  3. InkPresenterからマウスが外れた、または左ボタンの押下が解除されたとき、現在のStrokeについての処理を完了

 コードにすると、以下のようになります。

//現在処理中のStrokeオブジェクトを保持します
private System.Windows.Ink.Stroke currentStroke;

//マウスが左クリックされたとき、InkPresenterに新しいStrokeを追加します
private void inkP_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.inkP.CaptureMouse();
currentStroke = new System.Windows.Ink.Stroke();
currentStroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(inkP));
currentStroke.DrawingAttributes.Color = Colors.Black;
currentStroke.DrawingAttributes.Width = 5;
currentStroke.DrawingAttributes.Height = 5;
inkP.Strokes.Add(currentStroke);
}
//マウスが移動されたとき、Strokeに新しいStylusPointを追加します
private void inkP_MouseMove(object sender, MouseEventArgs e)
{
if (currentStroke == null) return;
currentStroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(inkP));
}
//マウスのキャプチャを失ったとき、現在のStrokeに対する処理を終了します
private void inkP_LostMouseCapture(object sender, MouseEventArgs e)
{
currentStroke = null;
}

Strokesコレクションをクリア

 落書きのクリアボタンは単純に、Strokesコレクションをクリアします。

//落書きをやり直すために、InkPresenter.Strokesをクリアします
private void clearPaint_Click(object sender, RoutedEventArgs e)
{
this.inkP.Strokes.Clear();
}

いったん試してみよう

 コードばかりで退屈ですので、この辺りでいったんアプリケーションを実行してみましょう。好きな画像を選択して、マウスやスタイラスで落書きをしてみてください。

最低限の機能の落書きアプリケーション(もっと大きな画面で見たい場合はこちらサンプルを動かすには、事前に実行環境のインストールが必要です。→ダウンロードページ

 基本的な動作が実装できたので、次ページではペンの色や太さを変更する機能を加えてみましょう。

  1-2-3

 INDEX
Silverlight 2で.NET技術をカッコよく使おう(4)
Silverlight 2で落書きアプリを作るための5つのテク  
Page1
まずは、Silverlightで作る落書きアプリを試してみよう
【1】インク機能でお絵描きをするには?
  Page2
【2】テンプレートでコントロールの見た目を変えるには?
【3】コントロールの状態に応じた見た目を設定するには?
【4】見た目をCSSのように独立して設定するには?
コラム 「Silverlight 2開発でプログラマとデザイナの作業分担を明確にするために」
  Page3
【5】落書きをローカルPC上に保存するには?
Silverlight 3が発表! ベータ版はすでに利用可能



リッチクライアント&帳票 全記事一覧へ




HTML5 + UX フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

HTML5+UX 記事ランキング

本日 月間