728x90
반응형
728x170
▶ PolygonEventArgs.cs
using System.Collections.Generic;
using System.Drawing;
namespace TestProject
{
/// <summary>
/// 다각형 이벤트 인자
/// </summary>
public class PolygonEventArgs
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Public
#region Field
/// <summary>
/// 포인트 리스트
/// </summary>
public List<Point> PointList;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - PolygonEventArgs(pointList)
/// <summary>
/// 생성자
/// </summary>
/// <param name="pointList">포인트 리스트</param>
public PolygonEventArgs(List<Point> pointList)
{
PointList = pointList;
}
#endregion
}
}
728x90
▶ PolygonSelector.cs
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace TestProject
{
/// <summary>
/// 다각형 선택자
/// </summary>
public class PolygonSelector
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Delegate
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 다각형 선택 이벤트 핸들러 - PolygonSelectedEventHandler(sender, e)
/// <summary>
/// 다각형 선택 이벤트 핸들러
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
public delegate void PolygonSelectedEventHandler(object sender, PolygonEventArgs e);
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Event
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 다각형 선택시 이벤트 - PolygonSelected
/// <summary>
/// 다각형 선택시 이벤트
/// </summary>
public event PolygonSelectedEventHandler PolygonSelected;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 컨트롤
/// </summary>
private Control control;
/// <summary>
/// 펜
/// </summary>
private Pen pen;
/// <summary>
/// 포인트 리스트
/// </summary>
private List<Point> pointList;
/// <summary>
/// 이용 가능 여부
/// </summary>
private bool enabled = true;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 이용 가능 여부 - Enabled
/// <summary>
/// 이용 가능 여부
/// </summary>
public bool Enabled
{
get
{
return this.enabled;
}
set
{
if(value == this.enabled)
{
return;
}
this.enabled = value;
if(this.enabled)
{
this.control.MouseDown += control_MouseDown;
}
else
{
this.control.MouseDown -= control_MouseDown;
this.control.MouseMove -= control_MouseMove;
this.control.MouseClick -= control_MouseClick;
this.control.Paint -= control_Paint;
}
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - PolygonSelector(control, pen)
/// <summary>
/// 생성자
/// </summary>
/// <param name="control">컨트롤</param>
/// <param name="pen">펜</param>
public PolygonSelector(Control control, Pen pen)
{
this.control = control;
this.pen = pen;
this.control.MouseDown += control_MouseDown;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Protected
#region 다각형 선택시 이벤트 발생시키기 - FirePolygonSelectedEvent()
/// <summary>
/// 다각형 선택시 이벤트 발생시키기
/// </summary>
protected virtual void FirePolygonSelectedEvent()
{
if((PolygonSelected == null) || (this.pointList.Count < 3))
{
this.control.Refresh();
}
else
{
PolygonEventArgs e = new PolygonEventArgs(this.pointList);
PolygonSelected(this, e);
}
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 컨트롤 마우스 DOWN 처리하기 - control_MouseDown(sender, e)
/// <summary>
/// 컨트롤 마우스 DOWN 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void control_MouseDown(object sender, MouseEventArgs e)
{
if(e.Button != MouseButtons.Left)
{
return;
}
this.control.MouseDown -= control_MouseDown;
this.pointList = new List<Point>();
this.pointList.Add(e.Location);
this.pointList.Add(e.Location);
this.control.MouseMove += control_MouseMove;
this.control.MouseClick += control_MouseClick;
this.control.Paint += control_Paint;
}
#endregion
#region 컨트롤 마우스 이동시 처리하기 - control_MouseMove(sender, e)
/// <summary>
/// 컨트롤 마우스 이동시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void control_MouseMove(object sender, MouseEventArgs e)
{
this.pointList[this.pointList.Count - 1] = e.Location;
this.control.Refresh();
}
#endregion
#region 컨트롤 마우스 클릭시 처리하기 - control_MouseClick(sender, e)
/// <summary>
/// 컨트롤 마우스 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void control_MouseClick(object sender, MouseEventArgs e)
{
int pointCount = pointList.Count;
if(e.Button == MouseButtons.Right)
{
this.pointList.RemoveAt(pointCount - 1);
this.control.MouseMove -= control_MouseMove;
this.control.MouseClick -= control_MouseClick;
this.control.Paint -= control_Paint;
FirePolygonSelectedEvent();
this.control.MouseDown += control_MouseDown;
}
else
{
if(this.pointList[pointCount - 1] != this.pointList[pointCount - 2])
{
this.pointList.Add(e.Location);
this.control.Refresh();
}
}
}
#endregion
#region 컨트롤 페인트시 처리하기 - control_Paint(sender, e)
/// <summary>
/// 컨트롤 페인트시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void control_Paint(object sender, PaintEventArgs e)
{
if(this.pointList.Count > 1)
{
e.Graphics.DrawLines(pen, this.pointList.ToArray());
}
}
#endregion
}
}
300x250
▶ MainForm.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Windows.Forms;
namespace TestProject
{
/// <summary>
/// 메인 폼
/// </summary>
public partial class MainForm : Form
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 다각형 셀렉터
/// </summary>
private PolygonSelector polygonSelector;
/// <summary>
/// 포인트 배열
/// </summary>
private PointF[] pointArray = null;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainForm()
/// <summary>
/// 생성자
/// </summary>
public MainForm()
{
InitializeComponent();
Load += Form_Load;
this.pictureBox.Paint += pictureBox_Paint;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region 폼 로드시 처리하기 - Form_Load(sender, e)
/// <summary>
/// 폼 로드시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void Form_Load(object sender, EventArgs e)
{
this.polygonSelector = new PolygonSelector(this.pictureBox, new Pen(Color.Red, 3));
this.polygonSelector.PolygonSelected += polygonSelector_PolygonSelected;
}
#endregion
#region 다각형 셀렉터 다각형 선택시 처리하기 - polygonSelector_PolygonSelected(sender, e)
/// <summary>
/// 다각형 셀렉터 다각형 선택시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void polygonSelector_PolygonSelected(object sender, PolygonEventArgs e)
{
this.pointArray = GetPointArray(e.PointList);
this.pictureBox.Refresh();
}
#endregion
#region 픽처 박스 페인트시 처리하기 - pictureBox_Paint(sender, e)
/// <summary>
/// 픽처 박스 페인트시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void pictureBox_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.Clear(pictureBox.BackColor);
if(this.pointArray != null)
{
DrawImageInPolygon(e.Graphics, this.pointArray, Properties.Resources.sample);
using(Pen pen = new Pen(Color.Green, 3))
{
e.Graphics.DrawPolygon(pen, this.pointArray.ToArray());
}
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region 포인트 배열 구하기 - GetPointArray(pointEnumerable)
/// <summary>
/// 포인트 배열 구하기
/// </summary>
/// <param name="pointEnumerable">포인트 열거 가능형</param>
/// <returns>포인트 배열</returns>
private PointF[] GetPointArray(IEnumerable<Point> pointEnumerable)
{
var resultEnumerable = from Point point in pointEnumerable select (PointF)point;
return resultEnumerable.ToArray();
}
#endregion
#region 다각형 테두리 설정하기 - SetPolygonBound(pointArray, minimumX, maximumX, minimumY, maximumY)
/// <summary>
/// 다각형 테두리 설정하기
/// </summary>
/// <param name="pointArray">포인트 배열</param>
/// <param name="minimumX">최소 X</param>
/// <param name="maximumX">최대 X</param>
/// <param name="minimumY">최소 Y</param>
/// <param name="maximumY">최대 Y</param>
public void SetPolygonBound
(
PointF[] pointArray,
out float minimumX,
out float maximumX,
out float minimumY,
out float maximumY
)
{
minimumX = pointArray[0].X;
maximumX = minimumX;
minimumY = pointArray[0].Y;
maximumY = minimumY;
foreach(PointF point in pointArray)
{
if(minimumX > point.X) minimumX = point.X;
if(maximumX < point.X) maximumX = point.X;
if(minimumY > point.Y) minimumY = point.Y;
if(maximumY < point.Y) maximumY = point.Y;
}
}
#endregion
#region 다각형 내에서 이미지 그리기 - DrawImageInPolygon(graphics, pointArray, image)
/// <summary>
/// 다각형 내에서 이미지 그리기
/// </summary>
/// <param name="graphics">그래픽스</param>
/// <param name="pointArray">포인트 배열</param>
/// <param name="image">이미지</param>
public void DrawImageInPolygon(Graphics graphics, PointF[] pointArray, Image image)
{
float minimumX;
float maximumX;
float minimumY;
float maximumY;
SetPolygonBound(pointArray, out minimumX, out maximumX, out minimumY, out maximumY);
float width = maximumX - minimumX;
float height = maximumY - minimumY;
float centerX = (minimumX + maximumX) / 2f;
float centerY = (minimumY + maximumY) / 2f;
float scaleX = width / image.Width;
float scaleY = height / image.Height;
float scale = Math.Max(scaleX, scaleY);
float imageWidth = image.Width * scale;
float imageHeight = image.Height * scale;
float imageCenterX = imageWidth / 2f;
float imageCenterY = imageHeight / 2f;
RectangleF sourceRectangle = new RectangleF(0, 0, image.Width, image.Height);
PointF[] targetPointArray =
{
new PointF(centerX - imageCenterX, centerY - imageCenterY),
new PointF(centerX + imageCenterX, centerY - imageCenterY),
new PointF(centerX - imageCenterX, centerY + imageCenterY)
};
GraphicsPath path = new GraphicsPath();
path.AddPolygon(pointArray);
GraphicsState state = graphics.Save();
graphics.SetClip(path);
graphics.DrawImage(image, targetPointArray, sourceRectangle, GraphicsUnit.Pixel);
graphics.Restore(state);
}
#endregion
}
}
728x90
반응형
그리드형(광고전용)
'C# > WinForm' 카테고리의 다른 글
[C#/WINFORM] 미로 길 찾기 (0) | 2020.08.05 |
---|---|
[C#/WINFORM] ImageAttributes 클래스 : 이미지 수정하기 (0) | 2020.08.04 |
[C#/WINFORM] 라운드 다각형 그리기 (0) | 2020.08.03 |
[C#/WINFORM] 기준선을 사용해 이미지 회전하기 (0) | 2020.08.03 |
[C#/WINFORM] 마우스 아래 그려진 문자 찾기 (0) | 2020.08.03 |
[C#/WINFORM] RGB 색상에서 HSV 색상 구하기 (0) | 2020.08.02 |
[C#/WINFORM] 다각형 선택자를 사용해 다각형 그리기 (0) | 2020.08.01 |
[C#/WINFORM] X/Y축 기준선에 따라 다각형 그리기 (0) | 2020.07.30 |
[C#/WINFORM] Graphics 클래스 : 점(dot) 그리기 (0) | 2020.07.30 |
[C#/WINFORM] Graphics 클래스 : 대시 라인(파선, 破線) 그리기 (0) | 2020.07.30 |
댓글을 달아 주세요