728x90
반응형
728x170
▶ MainForm.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace TestProject
{
/// <summary>
/// 메인 폼
/// </summary>
public partial class MainForm : Form
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Enumeration
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 그리기 모드 - DrawMode
/// <summary>
/// 그리기 모드
/// </summary>
private enum DrawMode
{
/// <summary>
/// 해당 무
/// </summary>
None,
/// <summary>
/// X축 설정하기
/// </summary>
SetAxisX,
/// <summary>
/// Y축 설정하기
/// </summary>
SetAxisY,
/// <summary>
/// 다각형 그리기
/// </summary>
DrawPolygon
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// X축 시작 포인트
/// </summary>
private PointF axisXStartPoint;
/// <summary>
/// X축 종료 포인트
/// </summary>
private PointF axisXEndPoint;
/// <summary>
/// Y축 시작 포인트
/// </summary>
private PointF axisYStartPoint;
/// <summary>
/// Y축 종료 포인트
/// </summary>
private PointF axisYEndPoint;
/// <summary>
/// 다각형 리스트
/// </summary>
private List<List<PointF>> polygonList = new List<List<PointF>>();
/// <summary>
/// 신규 포인트 리스트
/// </summary>
private List<PointF> newPointList = null;
/// <summary>
/// 마지막 포인트
/// </summary>
private PointF lastPoint;
/// <summary>
/// 그리기 모드
/// </summary>
private DrawMode drawMode = DrawMode.None;
/// <summary>
/// X축 그리기 여부
/// </summary>
private bool isDrawingAxisX = false;
/// <summary>
/// Y축 그리기 여부
/// </summary>
private bool isDrawingAxisY = false;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainForm()
/// <summary>
/// 생성자
/// </summary>
public MainForm()
{
InitializeComponent();
Load += Form_Load;
this.openMenuItem.Click += openMenuItem_Click;
this.newMenuItem.Click += newMenuItem_Click ;
this.eixtMenuItem.Click += eixtMenuItem_Click;
this.setXAxisMenuItem.Click += setXAxisMenuItem_Click;
this.setYAxisMenuItem.Click += setYAxisMenuItem_Click;
this.drawPolygonMenuItem.Click += drawPolygonMenuItem_Click;
this.clearPolygonMenuItem.Click += clearPolygonMenuItem_Click;
this.pictureBox.Paint += pictureBox_Paint;
this.pictureBox.MouseDown += pictureBox_MouseDown;
this.pictureBox.MouseMove += pictureBox_MouseMove;
this.pictureBox.MouseUp += pictureBox_MouseUp;
this.pictureBox.MouseClick += pictureBox_MouseClick;
}
#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)
{
int length = 75;
double angle = Math.PI / 6;
this.axisXStartPoint = new PointF(10, 100);
this.axisXEndPoint = new PointF
(
this.axisXStartPoint.X + length * (float)Math.Cos(angle),
this.axisXStartPoint.Y + length * (float)Math.Sin(angle)
);
angle = -Math.PI / 4;
this.axisYStartPoint = new PointF(10, 100);
this.axisYEndPoint = new PointF
(
this.axisYStartPoint.X + length * (float)Math.Cos(angle),
this.axisYStartPoint.Y + length * (float)Math.Sin(angle)
);
}
#endregion
#region 열기 메뉴 항목 클릭시 처리하기 - openMenuItem_Click(sender, e)
/// <summary>
/// 열기 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void openMenuItem_Click(object sender, EventArgs e)
{
if(this.openFileDialog.ShowDialog() == DialogResult.OK)
{
this.pictureBox.Image = LoadBitmapUnlocked(this.openFileDialog.FileName);
}
}
#endregion
#region 새로 그리기 메뉴 항목 클릭시 처리하기 - newMenuItem_Click(sender, e)
/// <summary>
/// 새로 그리기 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void newMenuItem_Click(object sender, EventArgs e)
{
this.pictureBox.Image = null;
this.polygonList.Clear();
this.pictureBox.Refresh();
}
#endregion
#region 종료 메뉴 항목 클릭시 처리하기 - eixtMenuItem_Click(sender, e)
/// <summary>
/// 종료 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void eixtMenuItem_Click(object sender, EventArgs e)
{
Close();
}
#endregion
#region X축 설정하기 메뉴 항목 클릭시 처리하기 - setXAxisMenuItem_Click(sender, e)
/// <summary>
/// X축 설정하기 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void setXAxisMenuItem_Click(object sender, EventArgs e)
{
this.drawMode = DrawMode.SetAxisX;
this.pictureBox.Cursor = Cursors.Cross;
}
#endregion
#region Y축 설정하기 메뉴 항목 클릭시 처리하기 - setYAxisMenuItem_Click(sender, e)
/// <summary>
/// Y축 설정하기 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void setYAxisMenuItem_Click(object sender, EventArgs e)
{
this.drawMode = DrawMode.SetAxisY;
this.pictureBox.Cursor = Cursors.Cross;
}
#endregion
#region 다각형 그리기 메뉴 항목 클릭시 처리하기 - drawPolygonMenuItem_Click(sender, e)
/// <summary>
/// 다각형 그리기 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void drawPolygonMenuItem_Click(object sender, EventArgs e)
{
this.drawMode = DrawMode.DrawPolygon;
this.newPointList = new List<PointF>();
this.pictureBox.Cursor = Cursors.Cross;
}
#endregion
#region 다각형 지우기 메뉴 항목 클릭시 처리하기 - clearPolygonMenuItem_Click(sender, e)
/// <summary>
/// 다각형 지우기 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void clearPolygonMenuItem_Click(object sender, EventArgs e)
{
this.polygonList.Clear();
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.DrawDashedLine(Color.Red , Color.Yellow, 2, new float[]{ 3, 3 }, this.axisXStartPoint, this.axisXEndPoint);
e.Graphics.DrawDashedLine(Color.Green, Color.Yellow, 2, new float[]{ 3, 3 }, this.axisYStartPoint, this.axisYEndPoint);
using(Pen pen = new Pen(Color.Red, 2))
{
pen.Color = Color.Blue;
using(Brush brush = new SolidBrush(Color.FromArgb(128, Color.LightBlue)))
{
foreach(List<PointF> pointList in this.polygonList)
{
e.Graphics.FillPolygon(brush, pointList.ToArray());
e.Graphics.DrawPolygon(pen, pointList.ToArray());
}
}
if(this.newPointList != null)
{
pen.Color = Color.Green;
pen.DashStyle = DashStyle.Solid;
if(this.newPointList.Count > 1)
{
e.Graphics.DrawLines(pen, this.newPointList.ToArray());
}
e.Graphics.DrawLine(pen, this.newPointList[this.newPointList.Count - 1], this.lastPoint);
foreach(PointF point in this.newPointList)
{
e.Graphics.FillEllipse(Brushes.Red, point.X - 3, point.Y - 3, 6, 6);
}
}
}
}
#endregion
#region 픽처 박스 마우스 DOWN 처리하기 - pictureBox_MouseDown(sender, e)
/// <summary>
/// 픽처 박스 마우스 DOWN 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
if(this.drawMode == DrawMode.SetAxisX)
{
this.isDrawingAxisX = true;
this.axisXStartPoint = e.Location;
this.axisXEndPoint = e.Location;
this.pictureBox.Refresh();
}
else if(this.drawMode == DrawMode.SetAxisY)
{
this.isDrawingAxisY = true;
this.axisYStartPoint = e.Location;
this.axisYEndPoint = e.Location;
this.pictureBox.Refresh();
}
}
#endregion
#region 픽처 박스 마우스 이동시 처리하기 - pictureBox_MouseMove(sender, e)
/// <summary>
/// 픽처 박스 마우스 이동시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void pictureBox_MouseMove(object sender, MouseEventArgs e)
{
if(this.drawMode == DrawMode.SetAxisX)
{
if(this.isDrawingAxisX)
{
this.axisXEndPoint = e.Location;
this.pictureBox.Refresh();
}
}
else if(this.drawMode == DrawMode.SetAxisY)
{
if(this.isDrawingAxisY)
{
this.axisYEndPoint = e.Location;
this.pictureBox.Refresh();
}
}
else if(this.drawMode == DrawMode.DrawPolygon)
{
if(this.newPointList.Count == 0)
{
return;
}
PointF adjustedPoint = AdjustPoint(e.Location);
this.lastPoint = adjustedPoint;
this.pictureBox.Refresh();
}
}
#endregion
#region 픽처 박스 마우스 UP 처리하기 - pictureBox_MouseUp(sender, e)
/// <summary>
/// 픽처 박스 마우스 UP 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void pictureBox_MouseUp(object sender, MouseEventArgs e)
{
if(this.drawMode == DrawMode.SetAxisX)
{
if(this.isDrawingAxisX)
{
this.pictureBox.Cursor = Cursors.Default;
this.drawMode = DrawMode.None;
this.isDrawingAxisX = false;
}
}
else if(this.drawMode == DrawMode.SetAxisY)
{
if(this.isDrawingAxisY)
{
this.pictureBox.Cursor = Cursors.Default;
this.drawMode = DrawMode.None;
this.isDrawingAxisY = false;
}
}
}
#endregion
#region 픽처 박스 마우스 클릭시 처리하기 - pictureBox_MouseClick(sender, e)
/// <summary>
/// 픽처 박스 마우스 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void pictureBox_MouseClick(object sender, MouseEventArgs e)
{
if(this.drawMode == DrawMode.DrawPolygon)
{
if(e.Button == MouseButtons.Right)
{
this.pictureBox.Cursor = Cursors.Default;
if(this.newPointList.Count > 3)
{
SaveNewPolygon();
}
this.newPointList = null;
this.drawMode = DrawMode.None;
}
else
{
PointF adjustedPoint = AdjustPoint(e.Location);
this.newPointList.Add(adjustedPoint);
this.lastPoint = adjustedPoint;
}
this.pictureBox.Refresh();
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region 잠금없이 비트맵 로드하기 - LoadBitmapUnlocked(filePath)
/// <summary>
/// 잠금없이 비트맵 로드하기
/// </summary>
/// <param name="filePath">파일 경로</param>
/// <returns>비트맵</returns>
private Bitmap LoadBitmapUnlocked(string filePath)
{
using(Bitmap bitmap = new Bitmap(filePath))
{
return new Bitmap(bitmap);
}
}
#endregion
#region 신규 다각형 저장하기 - SaveNewPolygon()
/// <summary>
/// 신규 다각형 저장하기
/// </summary>
private void SaveNewPolygon()
{
this.newPointList[this.newPointList.Count - 1] = AdjustPoint
(
this.newPointList[this.newPointList.Count - 1],
this.newPointList[0]
);
this.polygonList.Add(this.newPointList);
}
#endregion
#region 변환 매트릭스 구하기 - GetTransformMatrix()
/// <summary>
/// 변환 매트릭스 구하기
/// </summary>
/// <returns>변환 매트릭스</returns>
private Matrix GetTransformMatrix()
{
float xAxisDeltaX = this.axisXEndPoint.X - this.axisXStartPoint.X;
float xAxisDeltaY = this.axisXEndPoint.Y - this.axisXStartPoint.Y;
float xAxisLength = (float)Math.Sqrt(xAxisDeltaX * xAxisDeltaX + xAxisDeltaY * xAxisDeltaY);
float yAxisDeltaX = this.axisYEndPoint.X - this.axisYStartPoint.X;
float yAxisDeltaY = this.axisYEndPoint.Y - this.axisYStartPoint.Y;
float yAxisLength = (float)Math.Sqrt(yAxisDeltaX * yAxisDeltaX + yAxisDeltaY * yAxisDeltaY);
RectangleF rectangle = new RectangleF(0, 0, xAxisLength, yAxisLength);
PointF[] targetPointArray =
{
this.axisXStartPoint,
this.axisXEndPoint,
new PointF(this.axisXStartPoint.X + yAxisDeltaX, this.axisXStartPoint.Y + yAxisDeltaY)
};
Matrix matrix = new Matrix(rectangle, targetPointArray);
matrix.Invert();
return matrix;
}
#endregion
#region 포인트 조정하기 - AdjustPoint(pointToAdjust, referencePoint)
/// <summary>
/// 포인트 조정하기
/// </summary>
/// <param name="pointToAdjust">조정할 포인트</param>
/// <param name="referencePoint">참조 포인트</param>
/// <returns>조정 포인트</returns>
private PointF AdjustPoint(PointF pointToAdjust, PointF referencePoint)
{
if(this.newPointList == null)
{
return pointToAdjust;
}
if(this.newPointList.Count == 0)
{
return pointToAdjust;
}
Matrix matrix = GetTransformMatrix();
PointF[] pointArray =
{
referencePoint,
pointToAdjust,
};
matrix.TransformPoints(pointArray);
float deltaX = Math.Abs(pointArray[1].X - pointArray[0].X);
float deltaY = Math.Abs(pointArray[1].Y - pointArray[0].Y);
if(deltaX <= deltaY)
{
pointArray[1].X = pointArray[0].X;
}
else
{
pointArray[1].Y = pointArray[0].Y;
}
matrix.Invert();
matrix.TransformPoints(pointArray);
return pointArray[1];
}
#endregion
#region 포인트 조정하기 - AdjustPoint(point)
/// <summary>
/// 포인트 조정하기
/// </summary>
/// <param name="point">포인트</param>
/// <returns>조정 포인트</returns>
private PointF AdjustPoint(PointF point)
{
if(this.newPointList == null)
{
return point;
}
if(this.newPointList.Count == 0)
{
return point;
}
return AdjustPoint(point, this.newPointList[this.newPointList.Count - 1]);
}
#endregion
}
}
728x90
반응형
그리드형(광고전용)
'C# > WinForm' 카테고리의 다른 글
[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] Graphics 클래스 : 점(dot) 그리기 (0) | 2020.07.30 |
[C#/WINFORM] Graphics 클래스 : 대시 라인(파선, 破線) 그리기 (0) | 2020.07.30 |
[C#/WINFORM] 기준선에 따라 다각형 그리기 (0) | 2020.07.30 |
[C#/WINFORM] 이미지 스프라이트 사용하기 (0) | 2020.07.30 |
[C#/WINFORM] 연결 원 그리기 (0) | 2020.07.29 |
댓글을 달아 주세요