검색결과 리스트
draggableCanvas에 해당되는 글 2건
글
Draggable Canvas ver 0.9
목차
앞서 시리즈로 계속 포스팅 하던 것을 정리해 보았습니다.
요약하자면, Canvas 형태로서, TreeView 처럼 Element 들이 Hierarchy 를 가지면서 노출됩니다. 마우스 왼쪽 버튼을 이용해서 이동이 가능하며, 마우스 가운데 버튼을 누른채로 Canvas 를 이동시킬 수 있습니다. 더불어 마우스의 휠을 이용하여 Zoom In/Out 을 할 수 있습니다.
개요
이전 포스팅에서 구현했던 것들을 mix 해서 만들었습니다.
ver 0.9 라고 명시한 것은, 아직 알수 없는 버그들이 존재할 수 있기 때문도 있지만, Zoom 의 Origin 이 고정되어 있기 때문입니다. 화면 한 가운데를 Origin 으로 하여, ZoomIn/Out 하고 싶었는데 아직은 미구현 상태이네요. 다음에 기회가 된다면 이 기능 또한 넣어 보도록 하겠습니다.
소스코드입니다.
namespace 라든지 일부 경로는 본인에게 맞게 수정하여야 할지 모릅니다.
[Main]
<Window x:Class="TestMain.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sw="http://wpf.sungwook.kim/common"
Title="MainWindow" Height="350" Width="525">
<sw:DraggableCanvas Background="#AAAAAA">
<TreeViewItem Canvas.Left="10" Canvas.Top="10">
<TreeViewItem.Header>
<Border BorderBrush="White" BorderThickness="3">
<Grid Width="150" Height="150" Background="Red"/>
</Border>
</TreeViewItem.Header>
<TreeViewItem Canvas.Left="170">
<TreeViewItem.Header>
<Grid Width="150" Height="150" Background="Orange"/>
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem Canvas.Left="350">
<TreeViewItem.Header>
<Grid Width="100" Height="100" Background="Yellow"/>
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem Canvas.Left="10" Canvas.Top="200">
<TreeViewItem.Header>
<Border BorderBrush="White" BorderThickness="3" >
<Grid Width="150" Height="150" Background="Green" />
</Border>
</TreeViewItem.Header>
<TreeViewItem Canvas.Left="200" >
<TreeViewItem.Header>
<Grid Width="150" Height="150" Background="Blue"/>
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem Canvas.Left="0" Canvas.Top="100">
<TreeViewItem.Header>
<Grid Width="100" Height="100" Background="Purple"/>
</TreeViewItem.Header>
</TreeViewItem>
</TreeViewItem>
</TreeViewItem>
<TreeViewItem>
<TreeViewItem Canvas.Left="380" Canvas.Top="210">
<Grid Background="Navy" Width="100" Height="100"/>
</TreeViewItem>
</TreeViewItem>
</sw:DraggableCanvas>
</Window>
[DragOnCanvasBehavior.cs]
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
namespace SW.Common.Behaviors
{
public class DragOnCanvasBehavior : Behavior<FrameworkElement>
{
public FrameworkElement BaseElement
{
get { return (FrameworkElement)GetValue(BaseElementProperty); }
set { SetValue(BaseElementProperty, value); }
}
// Using a DependencyProperty as the backing store for BaseUIElement. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BaseElementProperty =
DependencyProperty.Register("BaseElement", typeof(FrameworkElement), typeof(DragOnCanvasBehavior), new PropertyMetadata(null));
public FrameworkElement Target
{
get { return (FrameworkElement)GetValue(TargetProperty); }
set { SetValue(TargetProperty, value); }
}
// Using a DependencyProperty as the backing store for Target. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TargetProperty =
DependencyProperty.Register("Target", typeof(FrameworkElement), typeof(DragOnCanvasBehavior), new PropertyMetadata(null));
protected override void OnAttached()
{
this.AssociatedObject.MouseLeftButtonDown += OnMouseLeftButtonDown;
base.OnAttached();
}
protected override void OnDetaching()
{
this.AssociatedObject.MouseLeftButtonDown -= OnMouseLeftButtonDown;
base.OnDetaching();
}
private Point _initMousePosition;
private Point _initItemPosition;
private bool _onDrag = false;
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (this._onDrag == false)
{
FrameworkElement captureBase = (this.BaseElement ?? this.AssociatedObject);
captureBase.MouseMove += OnMouseMove;
captureBase.MouseLeftButtonUp += OnMouseLeftButtonUp;
FrameworkElement target = (this.Target ?? this.AssociatedObject);
this._onDrag = true;
this._initMousePosition = e.GetPosition(captureBase);
double x = Canvas.GetLeft(target);
double y = Canvas.GetTop(target);
x = double.IsNaN(x) ? 0 : x;
y = double.IsNaN(y) ? 0 : y;
this._initItemPosition = new Point(x, y);
captureBase.CaptureMouse();
}
}
private void OnMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed && this._onDrag == true)
{
FrameworkElement captureBase = (this.BaseElement ?? this.AssociatedObject);
FrameworkElement target = (this.Target ?? this.AssociatedObject);
Vector delta = e.GetPosition(captureBase) - this._initMousePosition;
Canvas.SetLeft(target, this._initItemPosition.X + delta.X);
Canvas.SetTop(target, this._initItemPosition.Y + delta.Y);
}
}
private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
this._onDrag = false;
FrameworkElement captureBase = (this.BaseElement ?? this.AssociatedObject);
captureBase.ReleaseMouseCapture();
captureBase.MouseMove -= OnMouseMove;
captureBase.MouseLeftButtonUp -= OnMouseLeftButtonUp;
}
}
}
[DraggableCanvas.cs]
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Xaml;
namespace SW.Common.Controls
{
[TemplatePart(Name = "PART_RootCanvas", Type = typeof(MovableCanvas))]
public class DraggableCanvas : TreeView
{
public double ZoomRate
{
get { return (double)GetValue(ZoomRateProperty); }
set { SetValue(ZoomRateProperty, value); }
}
// Using a DependencyProperty as the backing store for ZoomRate. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ZoomRateProperty =
DependencyProperty.Register("ZoomRate", typeof(double), typeof(DraggableCanvas), new PropertyMetadata(1.0));
public double ZoomInterval
{
get { return (double)GetValue(ZoomIntervalProperty); }
set { SetValue(ZoomIntervalProperty, value); }
}
// Using a DependencyProperty as the backing store for ZoomInterval. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ZoomIntervalProperty =
DependencyProperty.Register("ZoomInterval", typeof(double), typeof(DraggableCanvas), new PropertyMetadata(0.02));
public double MaxZoomRate
{
get { return (double)GetValue(MaxZoomRateProperty); }
set { SetValue(MaxZoomRateProperty, value); }
}
// Using a DependencyProperty as the backing store for MaxZoomRate. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MaxZoomRateProperty =
DependencyProperty.Register("MaxZoomRate", typeof(double), typeof(DraggableCanvas), new PropertyMetadata(3.0));
public double MinZoomRate
{
get { return (double)GetValue(MinZoomRateProperty); }
set { SetValue(MinZoomRateProperty, value); }
}
// Using a DependencyProperty as the backing store for MinZoomRate. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MinZoomRateProperty =
DependencyProperty.Register("MinZoomRate", typeof(double), typeof(DraggableCanvas), new PropertyMetadata(0.5));
private MovableCanvas _rootCanvas = null;
static DraggableCanvas()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DraggableCanvas), new FrameworkPropertyMetadata(typeof(DraggableCanvas)));
}
public override void OnApplyTemplate()
{
DependencyObject canvas = this.GetTemplateChild("PART_RootCanvas");
if (canvas is MovableCanvas == false) { throw new XamlParseException("'PART_RootCanvas' cannot be found."); }
this._rootCanvas = canvas as MovableCanvas;
base.OnApplyTemplate();
}
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
if (e.Delta > 0)
{
double zoomRate = this.ZoomRate + this.ZoomInterval;
this.ZoomRate = (zoomRate > this.MaxZoomRate ? this.MaxZoomRate : zoomRate);
}
else if (e.Delta < 0)
{
double zoomRate = this.ZoomRate - this.ZoomInterval;
this.ZoomRate = (zoomRate < this.MinZoomRate ? this.MinZoomRate : zoomRate);
}
base.OnMouseWheel(e);
}
public void MoveTo(FrameworkElement item)
{
if (item == null) { return; }
Point itemCenter = new Point();
if(item is TreeViewItem && (item as TreeViewItem).HasHeader == true && (item as TreeViewItem).Header is FrameworkElement)
{
FrameworkElement targetElement = (item as TreeViewItem).Header as FrameworkElement;
itemCenter = item.TranslatePoint(new Point(targetElement.ActualWidth / 2, targetElement.ActualHeight / 2), this);
} else {
Rect bounds = VisualTreeHelper.GetDescendantBounds(item);
itemCenter = item.TranslatePoint(new Point(bounds.Width / 2, bounds.Height / 2), this);
}
this._rootCanvas.OffsetX = (this._rootCanvas.ActualWidth / 2) - (itemCenter.X - this._rootCanvas.OffsetX);
this._rootCanvas.OffsetY = (this._rootCanvas.ActualHeight / 2) - (itemCenter.Y - this._rootCanvas.OffsetY);
}
}
}
[DraggableCanvas.xaml]
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SW.Common.Controls"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:sw="http://wpf.sungwook.kim/common">
<Style TargetType="{x:Type local:DraggableCanvas}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeView}">
<ControlTemplate.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Canvas x:Name="PART_Canvas">
<ContentPresenter Content="{TemplateBinding Header}" ContentTemplate="{TemplateBinding HeaderTemplate}"
Canvas.Left="{Binding (Canvas.Left)}"
Canvas.Right="{Binding (Canvas.Right)}"
Canvas.Top="{Binding (Canvas.Top)}"
Canvas.Bottom="{Binding (Canvas.Bottom)}">
<i:Interaction.Behaviors>
<sw:DragOnCanvasBehavior BaseElement="{Binding RelativeSource={RelativeSource AncestorType=local:MovableCanvas}}"
Target="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem}}"/>
</i:Interaction.Behaviors>
</ContentPresenter>
<ItemsPresenter/>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
</ControlTemplate.Resources>
<local:FlottingGrid x:Name="PART_FlottingGrid"
GridOffsetX="{Binding ElementName=PART_RootCanvas, Path=OffsetX}"
GridOffsetY="{Binding ElementName=PART_RootCanvas, Path=OffsetY}"
ZoomRate="{Binding RelativeSource={RelativeSource AncestorType=local:DraggableCanvas}, Path=ZoomRate}"
Background="{TemplateBinding Background}">
<local:MovableCanvas Background="Transparent" x:Name="PART_RootCanvas" IsItemsHost="True"
MovingRatio="{Binding RelativeSource={RelativeSource AncestorType=local:DraggableCanvas}, Path=ZoomRate}">
<local:MovableCanvas.LayoutTransform>
<ScaleTransform ScaleX="{Binding RelativeSource={RelativeSource AncestorType=local:DraggableCanvas}, Path=ZoomRate}"
ScaleY="{Binding RelativeSource={RelativeSource AncestorType=local:DraggableCanvas}, Path=ZoomRate}"/>
</local:MovableCanvas.LayoutTransform>
</local:MovableCanvas>
</local:FlottingGrid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
[FlottingGrid.cs]
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace SW.Common.Controls
{
public class FlottingGrid : Grid
{
public double ZoomRate
{
get { return (double) GetValue(ZoomRateProperty); }
set { SetValue(ZoomRateProperty, value); }
}
// Using a DependencyProperty as the backing store for ZoomRate. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ZoomRateProperty =
DependencyProperty.Register("ZoomRate", typeof(double), typeof(FlottingGrid), new FrameworkPropertyMetadata(1.0, FrameworkPropertyMetadataOptions.AffectsRender));
public int CellCount
{
get { return (int) GetValue(CellCountProperty); }
set { SetValue(CellCountProperty, value); }
}
// Using a DependencyProperty as the backing store for CellCount. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CellCountProperty =
DependencyProperty.Register("CellCount", typeof(int), typeof(FlottingGrid), new FrameworkPropertyMetadata(10, FrameworkPropertyMetadataOptions.AffectsRender));
public double CellSize
{
get { return (double) GetValue(CellSizeProperty); }
set { SetValue(CellSizeProperty, value); }
}
// Using a DependencyProperty as the backing store for CellSize. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CellSizeProperty =
DependencyProperty.Register("CellSize", typeof(double), typeof(FlottingGrid), new FrameworkPropertyMetadata(20.0, FrameworkPropertyMetadataOptions.AffectsRender));
public Brush GridBrush
{
get { return (Brush) GetValue(GridBrushProperty); }
set { SetValue(GridBrushProperty, value); }
}
// Using a DependencyProperty as the backing store for GridBrush. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GridBrushProperty =
DependencyProperty.Register("GridBrush", typeof(Brush), typeof(FlottingGrid), new FrameworkPropertyMetadata(new SolidColorBrush(Color.FromArgb(60, 0, 0, 0)), FrameworkPropertyMetadataOptions.AffectsRender));
public Brush CellBrush
{
get { return (Brush) GetValue(CellBrushProperty); }
set { SetValue(CellBrushProperty, value); }
}
// Using a DependencyProperty as the backing store for CellBrush. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CellBrushProperty =
DependencyProperty.Register("CellBrush", typeof(Brush), typeof(FlottingGrid), new FrameworkPropertyMetadata(new SolidColorBrush(Color.FromArgb(60, 0, 0, 0)), FrameworkPropertyMetadataOptions.AffectsRender));
public double GridBorder
{
get { return (double) GetValue(GridBorderProperty); }
set { SetValue(GridBorderProperty, value); }
}
// Using a DependencyProperty as the backing store for GridBorder. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GridBorderProperty =
DependencyProperty.Register("GridBorder", typeof(double), typeof(FlottingGrid), new FrameworkPropertyMetadata(1.0, FrameworkPropertyMetadataOptions.AffectsRender));
public double CellBorder
{
get { return (double) GetValue(CellBorderProperty); }
set { SetValue(CellBorderProperty, value); }
}
// Using a DependencyProperty as the backing store for CellBorder. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CellBorderProperty =
DependencyProperty.Register("CellBorder", typeof(double), typeof(FlottingGrid), new FrameworkPropertyMetadata(1.0, FrameworkPropertyMetadataOptions.AffectsRender));
public double GridOffsetX
{
get { return (double) GetValue(GridOffsetXProperty); }
set { SetValue(GridOffsetXProperty, value); }
}
// Using a DependencyProperty as the backing store for GridOffsetX. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GridOffsetXProperty =
DependencyProperty.Register("GridOffsetX", typeof(double), typeof(FlottingGrid), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));
public double GridOffsetY
{
get { return (double) GetValue(GridOffsetYProperty); }
set { SetValue(GridOffsetYProperty, value); }
}
// Using a DependencyProperty as the backing store for GridOffsetY. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GridOffsetYProperty =
DependencyProperty.Register("GridOffsetY", typeof(double), typeof(FlottingGrid), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));
public double ZoomCenterX
{
get { return (double) GetValue(ZoomCenterXProperty); }
set { SetValue(ZoomCenterXProperty, value); }
}
// Using a DependencyProperty as the backing store for ZoomCenterX. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ZoomCenterXProperty =
DependencyProperty.Register("ZoomCenterX", typeof(double), typeof(FlottingGrid), new FrameworkPropertyMetadata(0.5, FrameworkPropertyMetadataOptions.AffectsRender));
public double ZoomCenterY
{
get { return (double) GetValue(ZoomCenterYProperty); }
set { SetValue(ZoomCenterYProperty, value); }
}
// Using a DependencyProperty as the backing store for ZoomCenterY. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ZoomCenterYProperty =
DependencyProperty.Register("ZoomCenterY", typeof(double), typeof(FlottingGrid), new FrameworkPropertyMetadata(0.5, FrameworkPropertyMetadataOptions.AffectsRender));
protected virtual double MaxZoomRate { get { return 4.0; } }
protected virtual double MinZoomRate { get { return 0.5; } }
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
double intervalOfMaxZoomRate = this.MaxZoomRate - this.MinZoomRate;
double translatedZoomRate = this.ZoomRate;
if (this.ZoomRate <= this.MinZoomRate) { translatedZoomRate += intervalOfMaxZoomRate; }
else if (this.ZoomRate >= this.MaxZoomRate) { translatedZoomRate -= intervalOfMaxZoomRate; }
double scaledCellSize = this.CellSize * translatedZoomRate;
double scaledGridSize = scaledCellSize * this.CellCount;
double templateSize = scaledGridSize + (this.GridBorder / 2);
//double offsetX = (this.ZoomCenterX * this.ActualWidth);
//double offsetY = (this.ZoomCenterY * this.ActualHeight);
double offsetX = 0.0;
double offsetY = 0.0;
DrawingBrush imageBrush = new DrawingBrush() {TileMode = TileMode.Tile, Viewbox = new Rect(0, 0, templateSize, templateSize), Viewport = new Rect(offsetX + this.GridOffsetX, offsetY + this.GridOffsetY, templateSize, templateSize), ViewportUnits = BrushMappingMode.Absolute, ViewboxUnits = BrushMappingMode.Absolute};
DrawingGroup drawingGroup = new DrawingGroup();
Brush cellBrush = this.CellBrush.Clone();
double cellBrushOpacity = cellBrush.Opacity * (1.0 - ((this.MaxZoomRate - translatedZoomRate) / intervalOfMaxZoomRate));
cellBrush.Opacity = cellBrushOpacity;
Brush borderBrush = this.GridBrush.Clone();
double borderBrushOpacity = borderBrush.Opacity * (this.MaxZoomRate - translatedZoomRate) / intervalOfMaxZoomRate;
borderBrush.Opacity = borderBrushOpacity;
Pen gridPen = new Pen(this.GridBrush, this.GridBorder);
Pen cellPen = new Pen(cellBrush, this.CellBorder);
using(DrawingContext context = drawingGroup.Open())
{
context.DrawLine(gridPen, new Point(scaledGridSize, 0), new Point(scaledGridSize, templateSize));
context.DrawLine(gridPen, new Point(0, scaledGridSize), new Point(templateSize, scaledGridSize));
for(int c = 1; c < this.CellCount; c++)
{
var offset = (double) ((int) (scaledCellSize * c));
context.DrawLine(cellPen, new Point(offset, 0), new Point(offset, templateSize));
}
for(int r = 1; r < this.CellCount; r++)
{
var offset = (double) ((int) (scaledCellSize * r));
context.DrawLine(cellPen, new Point(0, offset), new Point(templateSize, offset));
}
}
imageBrush.Drawing = drawingGroup;
dc.DrawRectangle(imageBrush, null, new Rect(0, 0, this.ActualWidth, this.ActualHeight));
}
}
}
[MovableCanvas]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using MS.Internal;
namespace SW.Common.Controls
{
public class MovableCanvas : Canvas
{
public double OffsetX
{
get { return (double)GetValue(OffsetXProperty); }
set { SetValue(OffsetXProperty, value); }
}
// Using a DependencyProperty as the backing store for OffsetX. This enables animation, styling, binding, etc...
public static readonly DependencyProperty OffsetXProperty =
DependencyProperty.Register("OffsetX", typeof(double), typeof(MovableCanvas), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsMeasure));
public double OffsetY
{
get { return (double)GetValue(OffsetYProperty); }
set { SetValue(OffsetYProperty, value); }
}
// Using a DependencyProperty as the backing store for OffsetY. This enables animation, styling, binding, etc...
public static readonly DependencyProperty OffsetYProperty =
DependencyProperty.Register("OffsetY", typeof(double), typeof(MovableCanvas), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsMeasure));
public double MovingRatio
{
get { return (double)GetValue(MovingRatioProperty); }
set { SetValue(MovingRatioProperty, value); }
}
// Using a DependencyProperty as the backing store for MovingRatio. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MovingRatioProperty =
DependencyProperty.Register("MovingRatio", typeof(double), typeof(MovableCanvas), new PropertyMetadata(1.0));
public Cursor CursorOnMove
{
get { return (Cursor)GetValue(CursorOnMoveProperty); }
set { SetValue(CursorOnMoveProperty, value); }
}
// Using a DependencyProperty as the backing store for Cursor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CursorOnMoveProperty =
DependencyProperty.Register("CursorOnMove", typeof(Cursor), typeof(MovableCanvas), new PropertyMetadata(Cursors.ScrollAll));
private Point _initMousePosition;
private Point _initItemPosition;
private bool _onDrag = false;
private Cursor _prevCursor;
protected override void OnMouseDown(MouseButtonEventArgs e)
{
if (this._onDrag == false && e.MiddleButton == MouseButtonState.Pressed)
{
this._onDrag = true;
this._prevCursor = this.Cursor;
this.Cursor = this.CursorOnMove;
this._initMousePosition = e.GetPosition(this);
this._initItemPosition = new Point(this.OffsetX, this.OffsetY);
this.CaptureMouse();
}
base.OnMouseDown(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.MiddleButton == MouseButtonState.Pressed && this._onDrag == true)
{
Vector delta = e.GetPosition(this) - this._initMousePosition;
this.OffsetX = this._initItemPosition.X + delta.X * this.MovingRatio;
this.OffsetY = this._initItemPosition.Y + delta.Y * this.MovingRatio;
}
base.OnMouseMove(e);
}
protected override void OnMouseUp(MouseButtonEventArgs e)
{
this._onDrag = false;
this.Cursor = this._prevCursor;
this.ReleaseMouseCapture();
base.OnMouseUp(e);
}
protected override Size ArrangeOverride(Size arrangeSize)
{
foreach (UIElement element in this.InternalChildren)
{
if (element != null)
{
double x = 0.0;
double y = 0.0;
double left = Canvas.GetLeft(element);
if (!double.IsNaN(left))
{
x = left * this.MovingRatio;
}
else
{
double right = Canvas.GetRight(element) * this.MovingRatio;
if (!double.IsNaN(right))
x = arrangeSize.Width - element.DesiredSize.Width - right;
}
double top = Canvas.GetTop(element);
if (!double.IsNaN(top))
{
y = top * this.MovingRatio;
}
else
{
double bottom = Canvas.GetBottom(element) * this.MovingRatio;
if (!double.IsNaN(bottom))
y = arrangeSize.Height - element.DesiredSize.Height - bottom;
}
element.Arrange(new Rect(new Point((x + this.OffsetX) / this.MovingRatio, (y + this.OffsetY) / this.MovingRatio), element.DesiredSize));
}
}
return arrangeSize;
}
}
}
'Microsoft > WPF' 카테고리의 다른 글
TextBox 의 내용이 짤릴 경우에만, ToolTip 보이기 (2) | 2014.12.26 |
---|---|
360 파노라마 뷰어 (4) | 2014.12.19 |
편집용 Canvas 만들기 (0) | 2014.11.16 |
Expanding Canvas 만들기 2 (0) | 2014.11.16 |
격자 배경 그리기 (0) | 2014.11.14 |
RECENT COMMENT