SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

現役エンジニア直伝! 「現場」で使えるコンポーネント活用術(ComponentOne Studio)

画像処理ができるWindows Phoneアプリケーションを作ろう

~ComponentOne Studio for Windows Phoneを活用したアプリ例~

  • このエントリーをはてなブックマークに追加

範囲選択部分の作成

 前ページまでで、画像表示部分が完成しました。次は、トリミング領域を指定するための定義を行います。トリミングは画面上をタップしてからパンすると、その領域の外側がグレー表示されるようにします。

 範囲表示にはComponentOne Studio for Windows PhoneのC1DockPanelを使います。

図4 範囲選択の表示
図4 範囲選択の表示
リスト8 範囲選択の表示
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,0,0" 
      VerticalAlignment="Top" HorizontalAlignment="Left"
      Height="535" Width="456">
    <Image x:Name="C1Sample_Image" Stretch="None" Tap="C1Sample_Image_Tap"  />
    <my:C1DockPanel x:Name="Selection_Panel">
        <Border my:C1DockPanel.Dock="Top" 
                Height="{Binding Top}" VerticalAlignment="Top"
                Background="{StaticResource MaskBrush}" />
        <Border my:C1DockPanel.Dock="Bottom" 
                Height="{Binding Bottom}" VerticalAlignment="Bottom"
                Background="{StaticResource MaskBrush}" />
        <Border my:C1DockPanel.Dock="Left" 
                Width="{Binding Left}" HorizontalAlignment="Left"
                Background="{StaticResource MaskBrush}" />
        <Border my:C1DockPanel.Dock="Right" 
                Width="{Binding Right}" HorizontalAlignment="Right"
                Background="{StaticResource MaskBrush}" />
    </my:C1DockPanel>
    <my:C1ProgressBar x:Name="Now_ProgressBar" IsIndeterminate="True" />
</Grid>

 C1DockPanelは画面の上下左右の辺にドッキングしたパネルコントロールです。XAML定義では、上下のパネルではHeightプロパティを、左右のパネルではWidthプロパティをBindingしてこのBinding値を画面上の操作(ジェスチャ)に応じて変化させ、範囲指定ができるようにしています。

範囲指定を行うコード

リスト9-1 範囲選択の表示(Visual Basic)
Private Selection As SelectionSize
Private ActureSize As Rect
Private PointStart As New Point
Private PointEnd As New Point
Private WithEvents GestureListener As C1.Phone.C1GestureListener

' コンストラクター
Public Sub New()
InitializeComponent()
Me.IsNewPageInstance = True
Me.ApplicationBar.IsMenuEnabled = True
Me.Now_ProgressBar.IsIndeterminate = False
Me.GestureListener = C1.Phone.C1GestureService.GetGestureListener(Me.C1Sample_Image)
End Sub

''' <summary>
''' 選択範囲の指定を開始する
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub GestureListener_DragStarted(sender As Object,
                                    e As C1.Phone.C1DragStartedGestureEventArgs) _
                                Handles GestureListener.DragStarted
Me.ActureSize = New Rect((CType(Me.C1Sample_Image.Parent, Grid).ActualWidth - Me.C1Sample_Image.ActualWidth) / 2, _
                         (CType(Me.C1Sample_Image.Parent, Grid).Height - Me.C1Sample_Image.ActualHeight) / 2, _
                         Me.C1Sample_Image.ActualWidth, _
                         Me.C1Sample_Image.ActualHeight)
Me.PointStart = e.GetPosition(Me.C1Sample_Image)
Me.PointEnd = e.GetPosition(Me.C1Sample_Image)
Call UpdateSelection(Me.PointStart, Me.PointEnd)
End Sub

''' <summary>
''' 選択範囲指定中の描画を行う
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub GestureListener_DragDelta(sender As Object,
                                  e As C1.Phone.C1DragDeltaGestureEventArgs) _
                              Handles GestureListener.DragDelta
Me.PointEnd = e.GetPosition(Me.C1Sample_Image)
Call UpdateSelection(Me.PointStart, Me.PointEnd)
End Sub

''' <summary>
''' 選択範囲の終わりを検出する
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub GestureListener_DragCompleted(sender As Object,
                                      e As C1.Phone.C1DragCompletedGestureEventArgs) _
                                  Handles GestureListener.DragCompleted
Me.PointEnd = e.GetPosition(Me.C1Sample_Image)
Call UpdateSelection(Me.PointStart, Me.PointEnd)
End Sub

''' <summary>
''' 選択範囲を更新する
''' </summary>
''' <param name="selectStart"></param>
''' <param name="selectEnd"></param>
''' <remarks></remarks>
Private Sub UpdateSelection(ByVal selectStart As Point, ByVal selectEnd As Point)
selectStart.X = Math.Min(Math.Max(selectStart.X, 0), Me.ActureSize.Width)
selectEnd.X = Math.Min(Math.Max(selectEnd.X, 0), Me.ActureSize.Width)
selectStart.Y = Math.Min(Math.Max(selectStart.Y, 0), Me.ActureSize.Height)
selectEnd.Y = Math.Min(Math.Max(selectEnd.Y, 0), Me.ActureSize.Height)
Me.Selection = New SelectionSize(Me.ActureSize, _
                                 New Point(Math.Round(Math.Min(selectStart.X, selectEnd.X)), _
                                           Math.Round(Math.Min(selectStart.Y, selectEnd.Y))), _
                                 New Point(Math.Round(Math.Max(selectStart.X, selectEnd.X)), _
                                           Math.Round(Math.Max(selectStart.Y, selectEnd.Y))))
Call UpdateMask()
End Sub

''' <summary>
''' トリミングエリアを描画する
''' </summary>
''' <remarks></remarks>
Private Sub UpdateMask()
Me.Selection_Panel.DataContext = Me.Selection
End Sub
リスト9-2 範囲選択の表示(C#)
private SelectionSize Selection;
private Rect ActureSize;
private Point PointStart = new Point();
private Point PointEnd = new Point();
private C1.Phone.C1GestureListener GestureListener;

// コンストラクター
public MainPage()
{
    InitializeComponent();
    this.IsNewPageInstance = true;
    this.ApplicationBar.IsMenuEnabled = true;
    this.Now_ProgressBar.IsIndeterminate = false;
    this.GestureListener = C1.Phone.C1GestureService.GetGestureListener(this.C1Sample_Image);
}

/// <summary>
/// 選択範囲の指定を開始する
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void GestureListener_DragStarted(System.Object sender,
     C1.Phone.C1DragStartedGestureEventArgs e)
{
    this.PointStart = e.GetPosition(this.C1Sample_Image);
    this.PointEnd = e.GetPosition(this.C1Sample_Image);
    UpdateSelection(this.PointStart, this.PointEnd);
}

/// <summary>
/// 選択範囲指定中の描画を行う
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void GestureListener_DragDelta(System.Object sender,
     C1.Phone.C1DragDeltaGestureEventArgs e)
{
    this.PointEnd = e.GetPosition(this.C1Sample_Image);
    UpdateSelection(this.PointStart, this.PointEnd);
}

/// <summary>
/// 選択範囲の終わりを検出する
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void GestureListener_DragCompleted(System.Object sender,
     C1.Phone.C1DragCompletedGestureEventArgs e)
{
    this.PointEnd = e.GetPosition(this.C1Sample_Image);
    UpdateSelection(this.PointStart, this.PointEnd);
}

/// <summary>
/// 選択範囲を更新する
/// </summary>
/// <param name="selectStart"></param>
/// <param name="selectEnd"></param>
private void UpdateSelection(Point selectStart, Point selectEnd)
{
    selectStart.X = Math.Min(Math.Max(selectStart.X, 0), this.ActureSize.Width);
    selectEnd.X = Math.Min(Math.Max(selectEnd.X, 0), this.ActureSize.Width);
    selectStart.Y = Math.Min(Math.Max(selectStart.Y, 0), this.ActureSize.Height);
    selectEnd.Y = Math.Min(Math.Max(selectEnd.Y, 0), this.ActureSize.Height);
    this.Selection = new SelectionSize(this.ActureSize,
                                     new Point(Math.Round(Math.Min(selectStart.X, selectEnd.X)), 
                                               Math.Round(Math.Min(selectStart.Y, selectEnd.Y))), 
                                     new Point(Math.Round(Math.Max(selectStart.X, selectEnd.X)), 
                                               Math.Round(Math.Max(selectStart.Y, selectEnd.Y))));
    UpdateMask();
}

/// <summary>
/// トリミングエリアを描画する
/// </summary>
private void UpdateMask()
{
    this.Selection_Panel.DataContext = this.Selection;
}

 描画範囲の指定にはC1.Phone.C1GestureListenerを使用します。DragStartedイベントで範囲指定の開始検知を行いDragCompletedイベントで範囲指定の終了を検知します。もちろん範囲を指定中もDragDeltaイベントにより常時UpdateSelectionプロシージャを呼び出すようになってます。

 UpdateSelectionプロシージャの中ではマスク範囲を掲載してその結果をC1DockPanelのDataContextに設定してXAML上のBindingに値を供給してます。

次のページ
トリミング機能の実装

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
現役エンジニア直伝! 「現場」で使えるコンポーネント活用術(ComponentOne Studio)連載記事一覧

もっと読む

この記事の著者

初音玲(ハツネアキラ)

 国内SIerのSEでパッケージ製品開発を主に行っており、最近は、空間認識や音声認識などを応用した製品を手掛けています。 個人的には、仕事の内容をさらに拡張したHoloLensなどのMRを中心に活動しています。 Microsoft MVP for Windows Development ブログ:http://hatsune.hatenablog.jp/

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/6628 2012/06/21 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング