範囲選択部分の作成
前ページまでで、画像表示部分が完成しました。次は、トリミング領域を指定するための定義を行います。トリミングは画面上をタップしてからパンすると、その領域の外側がグレー表示されるようにします。
範囲表示にはComponentOne Studio for Windows PhoneのC1DockPanelを使います。
<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値を画面上の操作(ジェスチャ)に応じて変化させ、範囲指定ができるようにしています。
範囲指定を行うコード
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
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に値を供給してます。

