안녕하세요? 맨날맑음 입니다.
이번 포스팅은 WPF에서 마우스 드래그를 이용한 간단한 사각형 그리기입니다. 이 예제를 응용하면 원이나 선도 그릴 수 있고, 자료구조를 이용하면 윈도우 그림판과 같은 기능도 쉽게 만들 수 있습니다.
-Fig1. 사각형을 그리는 WPF 어플리케이션-
Fig1에서 보는 바와 같이 마우스의 현재 좌표를 왼쪽 상단에 표시해 주며, 드래그를 이용하여 사각형을 그리는 기능을 합니다. WPF에서 제공하는 InkCanvas객체를 이용하면 더 간단하게 구현도 가능 하겠네요^^; 하지만 이번에는 Grid에 사각형을 그리는 방법으로 구현해 보겠습니다.
#1. 마우스 이벤트 |
-Fig2. WPF Window의 마우스 이벤트-
WPF의 컨트롤은 마우스 이벤트를 가지고 있습니다. 마우스 다운이나 업, 마우스 무브, 마우스 휠 등 이벤트를 지원하는데요. 우리 예제에서는 MouseLeftButtonDown과 MouseMove, MouseLeftButtonUp 세 가지 이벤트를 사용합니다. 마우스 이벤트 핸들러에서는 MouseEventArgs 객체가 인자로 넘어오고 이 이벤트객체를 이용하면 현재 마우스의 상태정보를 알 수 있습니다.
이름 |
설명 | |
|
이 이벤트를 시작한 입력 장치를 가져옵니다. (InputEventArgs에서 상속됨) | |
|
라우트된 이벤트가 경로를 따라 이동할 때의 현재 이벤트 처리 상태를 나타내는 값을 가져오거나 설정합니다. | |
|
마우스 왼쪽 단추의 현재 상태를 가져옵니다. | |
|
마우스 가운데 단추의 현재 상태를 가져옵니다. | |
|
이 이벤트와 연결된 마우스 장치를 가져옵니다. | |
|
부모 클래스에서 Source를 조정하기 전에 순수 적중 테스트에 의해 결정되는 원본 보고 소스를 가져옵니다. | |
|
마우스 오른쪽 단추의 현재 상태를 가져옵니다. | |
|
이 RoutedEventArgs 인스턴스와 연결된 RoutedEvent를 가져오거나 설정합니다. (RoutedEventArgs에서 상속됨) | |
|
이벤트를 발생시킨 개체에 대한 참조를 가져오거나 설정합니다. (RoutedEventArgs에서 상속됨) | |
|
이 이벤트와 연결된 스타일러스 장치를 가져옵니다. | |
|
이 이벤트가 발생한 시간을 가져옵니다. (InputEventArgs에서 상속됨) | |
|
첫 번째로 확장된 마우스 단추의 현재 상태를 가져옵니다. | |
|
두 번째로 확장된 마우스 단추의 현재 상태를 가져옵니다. |
- MouseEventArgs 의 속성 (출처 : MSDN)-
이벤트 객체의 속성을 통해 마우스의 현재 상태정보를 알 수 있으며, GetPosition() 메서드를 이용하면 마우스 포인트의 좌표를 얻어 올 수도 있습니다.
#2. Shape객체 |
WPF에서 Rectangle, Ellipse, Polygon과 같은 모든 도형의 기본 클래스는 Shape입니다. Shape는 UI 요소이므로 패널이나 대부분의 컨트롤에서 사용 할 수 있습니다. Stroke 속성을 사용하면 도형의 테두리(윤곽선)의 색상을 지정 할 수 있고, StrokeThickness 속성을 이용하면 도형의 테두리 두께를 설정 할 수 있습니다. 또한 Fill 속성을 이용하면 도형의 표면 색상을 설정 할 수 있습니다.
-Fig3. 여러 속성을 적용하여 랜더링 된 원의 모습-
#3. 코드 구현 |
코드가 간단하여, 대부분의 설명은 주석으로 코드설명을 대신합니다. WPF 프로젝트를 생성하고, 다음과 같은 코드를 넣어 줍니다.
-Code1. MainWindow.xaml-
public partial class MainWindow : Window { ////// 드레그를 시작한 마우스 좌표; /// Point prePosition; ////// 현재 그려지는 사각형 /// Rectangle currentRect; public MainWindow() { InitializeComponent(); //이벤트 핸들러 생성 this.root.MouseLeftButtonDown += new MouseButtonEventHandler(root_MouseLeftButtonDown); this.root.MouseMove += new MouseEventHandler(root_MouseMove); this.root.MouseLeftButtonUp += new MouseButtonEventHandler(root_MouseLeftButtonUp); // 좌표를 나타내는 TextBlock을 최상위로 ... Grid.SetZIndex(this.tbPosition, 99999); } ////// 마우스 클릭 해제 이벤트 핸들러 /// /// /// void root_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { //마우스 캡춰를 제거한다. this.root.ReleaseMouseCapture(); SetRectangleProperty(); currentRect = null; } private void SetRectangleProperty() { //사각형의 투명도를 100% 로 설정 currentRect.Opacity = 1; //사각형의 색상을 지정 currentRect.Fill = new SolidColorBrush(Colors.LightYellow); //사각형의 테두리를 선으로 지정 currentRect.StrokeDashArray = new DoubleCollection(); ; } ////// 마우스 이동 이벤트 핸들러 /// /// /// void root_MouseMove(object sender, MouseEventArgs e) { //현재 이동한 마우스의 좌표를 얻어온다 Point currnetPosition = e.GetPosition(this.root); //좌표를 표시한다. this.tbPosition.Text = string.Format("마우스 좌표 : [{0},{1}]", currnetPosition.X, currnetPosition.Y); //마우스 왼쪽 버튼이 눌려있으면 if (e.MouseDevice.LeftButton == MouseButtonState.Pressed) { if (currentRect != null) { //사각형이 나타날 기준점을 설정한다. double left = prePosition.X; double top = prePosition.Y; //마우스의 위치에 따라 적절히 기준점을 변경한다. if (prePosition.X > currnetPosition.X) { left = currnetPosition.X; } if (prePosition.Y > currnetPosition.Y) { top = currnetPosition.Y; } //사각형의 위치 기준점(Margin)을 설정한다 currentRect.Margin = new Thickness(left, top, 0, 0); //사각형의 크기를 설정한다. 음수가 나올 수 없으므로 절대값을 취해준다. currentRect.Width = Math.Abs(prePosition.X - currnetPosition.X); currentRect.Height = Math.Abs(prePosition.Y - currnetPosition.Y); } } } ////// 마우스 왼쪽 버튼 클릭 이벤트 핸들러 /// /// /// void root_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { //마우스의 좌표를 저장한다. prePosition = e.GetPosition(this.root); //마우스가 Grid밖으로 나가도 위치를 알 수 있도록 마우스 이벤트를 캡처한다. this.root.CaptureMouse(); if (currentRect == null) { //사각형을 생성한다. CreteRectangle(); } } private void CreteRectangle() { currentRect = new Rectangle(); currentRect.Stroke = new SolidColorBrush(Colors.DarkGreen); currentRect.StrokeThickness = 2; currentRect.Opacity = 0.7; //사각형을 그리는 동안은 테두리를 Dash 스타일로 설정한다. DoubleCollection dashSize = new DoubleCollection(); dashSize.Add(1); dashSize.Add(1); currentRect.StrokeDashArray = dashSize; currentRect.StrokeDashOffset = 0; //사각형의 정렬 기준을 설정한다. currentRect.HorizontalAlignment = System.Windows.HorizontalAlignment.Left; currentRect.VerticalAlignment = System.Windows.VerticalAlignment.Top; //그리드에 추가한다. this.root.Children.Add(currentRect); } }
-Code2. MainWindow.xaml.cs-
마우스를 드래그하는 동안은 그림판이나 포토샵에서와 같이 점선으로 사각형의 모양을 표시 해 줄 필요가 있기 때문에 테두리의 속성을 변경 할 필요가 있습니다. 테두리를 점선으로 표시하는 속성은 Rectangle객체의 StrokeDashArray를 사용하여 설정 할 수 있으며, XAML에서는 다음과 같이 표현 할 수 있습니다.
-Fig4. StrokeDashArray 속성이 적용 된 Ellipse-
|
소스 빌드 환경 : VisualStudio2010, .NET Framework4.0
'.NET > WPF' 카테고리의 다른 글
Windows Form에서 WPF Window Application 호출하기 (3) | 2010.06.28 |
---|---|
Microsoft Office Object를 이용한 PPT Viewer 만들기 (14) | 2010.01.18 |
[WPF] Widget 만들기! (0) | 2008.12.26 |