첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
본 블로그는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 블로그 콘텐츠 향상을 위해 쓰여집니다.

728x90
반응형

TestProject.zip
다운로드

▶ MainWindow.xaml

<Window x:Class="TestProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="800"
    Height="600"
    Title="사각형 이동/크기 조정하기">
    <Canvas Name="canvas"
        Background="Transparent"
        MouseDown="canvas_MouseDown"
        MouseMove="canvas_MouseMove"
        MouseUp="canvas_MouseUp">
        <Rectangle Name="rectangle"
            Canvas.Left="100"
            Canvas.Top="100"
            Width="200"
            Height="100"
            Stroke="Black">
            <Rectangle.Fill>
                <LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
                    <LinearGradientBrush.GradientStops>
                        <GradientStop Color="White" Offset="0" />
                        <GradientStop Color="Blue"  Offset="1" />
                    </LinearGradientBrush.GradientStops>
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
    </Canvas>
</Window>

 

728x90

 

▶ MainWindow.xaml.cs

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Shapes;

namespace TestProject
{
    /// <summary>
    /// 메인 윈도우
    /// </summary>
    public partial class MainWindow : Window
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Enumeration
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 히트 타입 - HitType

        /// <summary>
        /// 히트 타입
        /// </summary>
        private enum HitType
        {
            /// <summary>
            /// 해당 무
            /// </summary>
            NONE,

            /// <summary>
            /// 몸통
            /// </summary>
            BODY,

            /// <summary>
            /// 좌상단
            /// </summary>
            UPPER_LEFT,

            /// <summary>
            /// 우상단
            /// </summary>
            UPPER_RIGHT,

            /// <summary>
            /// 좌하단
            /// </summary>
            LOWER_RIGHT,

            /// <summary>
            /// 우하단
            /// </summary>
            LOWER_LEFT,

            /// <summary>
            /// 왼쪽
            /// </summary>
            LEFT,

            /// <summary>
            /// 오른쪽
            /// </summary>
            RIGHT,

            /// <summary>
            /// 위쪽
            /// </summary>
            TOP,

            /// <summary>
            /// 아래쪽
            /// </summary>
            BOTTOM
        };

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 드래그 여부
        /// </summary>
        private bool isDragging = false;

        /// <summary>
        /// 마지막 포인트
        /// </summary>
        private Point lastPoint;

        /// <summary>
        /// 히트 타입
        /// </summary>
        HitType hitType = HitType.NONE;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainWindow()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private
        //////////////////////////////////////////////////////////////////////////////// Event

        #region 캔버스 마우스 DOWN 처리하기 - canvas_MouseDown(sender, e)

        /// <summary>
        /// 캔버스 마우스 DOWN 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void canvas_MouseDown(object sender, MouseButtonEventArgs e)
        {
            this.hitType = GetHitType(this.rectangle, Mouse.GetPosition(this.canvas));

            SetMouseCursor();

            if(this.hitType == HitType.NONE)
            {
                return;
            }

            this.lastPoint = Mouse.GetPosition(this.canvas);

            this.isDragging = true;
        }

        #endregion
        #region 캔버스 마우스 이동시 처리하기 - canvas_MouseMove(sender, e)

        /// <summary>
        /// 캔버스 마우스 이동시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void canvas_MouseMove(object sender, MouseEventArgs e)
        {
            if(!this.isDragging)
            {
                this.hitType = GetHitType(this.rectangle, Mouse.GetPosition(this.canvas));

                SetMouseCursor();
            }
            else
            {
                Point point = Mouse.GetPosition(this.canvas);

                double offsetX = point.X - this.lastPoint.X;
                double offsetY = point.Y - this.lastPoint.Y;

                double newX      = Canvas.GetLeft(this.rectangle);
                double newY      = Canvas.GetTop (this.rectangle);
                double newWidth  = this.rectangle.Width;
                double newHeight = this.rectangle.Height;

                switch(this.hitType)
                {
                    case HitType.BODY :

                        newX += offsetX;
                        newY += offsetY;

                        break;

                    case HitType.UPPER_LEFT :

                        newX += offsetX;
                        newY += offsetY;

                        newWidth  -= offsetX;
                        newHeight -= offsetY;

                        break;

                    case HitType.UPPER_RIGHT :

                        newY += offsetY;

                        newWidth  += offsetX;
                        newHeight -= offsetY;

                        break;

                    case HitType.LOWER_RIGHT :

                        newWidth  += offsetX;
                        newHeight += offsetY;

                        break;

                    case HitType.LOWER_LEFT :

                        newX += offsetX;

                        newWidth  -= offsetX;
                        newHeight += offsetY;

                        break;

                    case HitType.LEFT :

                        newX += offsetX;

                        newWidth -= offsetX;

                        break;

                    case HitType.RIGHT :

                        newWidth += offsetX;

                        break;

                    case HitType.BOTTOM :

                        newHeight += offsetY;

                        break;

                    case HitType.TOP :

                        newY += offsetY;

                        newHeight -= offsetY;

                        break;
                }

                if((newWidth > 0) && (newHeight > 0))
                {
                    Canvas.SetLeft(this.rectangle, newX);
                    Canvas.SetTop (this.rectangle, newY);

                    this.rectangle.Width = newWidth;
                    this.rectangle.Height = newHeight;

                    this.lastPoint = point;
                }
            }
        }

        #endregion
        #region 캔버스 마우스 UP 처리하기 - canvas_MouseUp(sender, e)

        /// <summary>
        /// 캔버스 마우스 UP 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void canvas_MouseUp(object sender, MouseButtonEventArgs e)
        {
            this.isDragging = false;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Function

        #region 히트 타입 구하기 - GetHitType(rectangle, point)

        /// <summary>
        /// 히트 타입 구하기
        /// </summary>
        /// <param name="rectangle">사각형</param>
        /// <param name="point">포인트</param>
        /// <returns>히트 타입</returns>
        private HitType GetHitType(Rectangle rectangle, Point point)
        {
            double left   = Canvas.GetLeft(this.rectangle);
            double top    = Canvas.GetTop(this.rectangle);
            double right  = left + this.rectangle.Width;
            double bottom = top  + this.rectangle.Height;

            if(point.X < left)
            {
                return HitType.NONE;
            }

            if(point.X > right)
            {
                return HitType.NONE;
            }

            if(point.Y < top)
            {
                return HitType.NONE;
            }

            if(point.Y > bottom)
            {
                return HitType.NONE;
            }

            const double GAP = 10;

            if(point.X - left < GAP)
            {
                if(point.Y - top < GAP)
                {
                    return HitType.UPPER_LEFT;
                }

                if(bottom - point.Y < GAP)
                {
                    return HitType.LOWER_LEFT;
                }

                return HitType.LEFT;
            }

            if(right - point.X < GAP)
            {
                if(point.Y - top < GAP)
                {
                    return HitType.UPPER_RIGHT;
                }

                if(bottom - point.Y < GAP)
                {
                    return HitType.LOWER_RIGHT;
                }

                return HitType.RIGHT;
            }

            if(point.Y - top < GAP)
            {
                return HitType.TOP;
            }

            if(bottom - point.Y < GAP)
            {
                return HitType.BOTTOM;
            }

            return HitType.BODY;
        }

        #endregion
        #region 마우스 커서 설정하기 - SetMouseCursor()

        /// <summary>
        /// 마우스 커서 설정하기
        /// </summary>
        private void SetMouseCursor()
        {
            Cursor cursor = Cursors.Arrow;

            switch(this.hitType)
            {
                case HitType.NONE        : cursor = Cursors.Arrow;     break;
                case HitType.BODY        : cursor = Cursors.ScrollAll; break;
                case HitType.UPPER_LEFT  :
                case HitType.LOWER_RIGHT : cursor = Cursors.SizeNWSE;  break;
                case HitType.LOWER_LEFT  :
                case HitType.UPPER_RIGHT : cursor = Cursors.SizeNESW;  break;
                case HitType.TOP         :
                case HitType.BOTTOM      : cursor = Cursors.SizeNS;    break;
                case HitType.LEFT        :
                case HitType.RIGHT       : cursor = Cursors.SizeWE;    break;
            }

            if(Cursor != cursor)
            {
                Cursor = cursor;
            }
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by 사용자 icodebroker
TAG , ,

댓글을 달아 주세요