範囲選択部分の作成
前ページまでで、画像表示部分が完成しました。次は、トリミング領域を指定するための定義を行います。トリミングは画面上をタップしてからパンすると、その領域の外側がグレー表示されるようにします。
範囲表示には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に値を供給してます。