남윤형

텍스트박스의 글자를 도형에 삽입해서 다시 그리는 기능을 삽입

......@@ -8,23 +8,34 @@ using System.Windows.Forms;
namespace flowchart
{
// 각종 선택 상황을 열거형으로 정의
public enum State
{
NONE, RECTANGLE, RHOMBUS, PARALLELOGRAM, LINKLINE, MOVE
}
// flowchart를 그리는 판넬에 필요한 기능을 삽입. (Panel 객체를 상속해서 사용했음)
// 마우스 클릭을 놓으면 어떤 도형 또는 선을 선택했는지 판단해서, 해당 자료구조를 생성하고, 페인트 함수를 통해 그린다.
class CustomPanel : Panel
{
private String _state; // NONE, DRAW, MOVE
private String _figName; // NONE, RECTANGLE, RHOMBUS, LINKLINE, ETC
public static Control _parentControl = null; // 텍스트박스에서 부모로 정의하기 위한 변수
public CustomPanel() // 생성자
{
_parentControl = this;
}
private State _selectState = State.NONE; // 열거형을 사용하기 위한 변수
private List<FigBase> _shapes = new List<FigBase>(); // 도형을 저장한 리스트 자료구조
private List<FigLinkline> _linkLines = new List<FigLinkline>(); // 링크 선을 저장한 리스트 자료구조
private FigBase _linkStartShape = null; // 처음 선택한 도형을 저장하는 변수
private FigBase _movingShape = null; // 도형을 움직이겠다고 선택된 경우 해당 도형을 저장하는 변수
// private 변수를 클래스 밖에서 읽고 쓰게 하는 함수
public string FigName { get { return _figName; } set { _figName = value; } }
public String State { get { return _state; } set { _state = value; } }
// 외부 클래스에서 호출되는 변수(열거형 값) 정의
public State SelectState { get { return _selectState; } set { _selectState = value; } }
// 마우스를 판넬에서 움질일때 호출되는 이벤트 함수
protected override void OnMouseMove(MouseEventArgs e)
......@@ -38,33 +49,34 @@ namespace flowchart
FigBase shape = FindShapeByLocation(e.Location);
if (shape != null)
Cursor = Cursors.SizeAll; // 도형 안에 마우스가 있을 경우
else
Cursor = Cursors.Default; // 도형 밖에 마우스 포인터가 있을 경우
if (shape != null && _figName == "LINKLINE") // 링크 라인을 그리겠다고 선택하고, 도형 안에 마우스가 있을 경우
Cursor = Cursors.SizeAll; // 도형 안에 마우스가 있을 경우 마우스 모양 변경
else
Cursor = Cursors.Default; // 도형 밖에 마우스 포인터가 있을 경우 마우스 모양 변경
// 도형 안에 마우스가 있고, 링크 라인을 그리겠다고 선택
if (shape != null && _selectState == State.LINKLINE)
Cursor = Cursors.Cross;
}
// 마우스를 클릭한 상태에서 링크 라인을 그리지 않겠다고 선택된 경우
else if (e.Button == MouseButtons.Left && _figName != "LINKLINE")
else if (e.Button == MouseButtons.Left && _selectState != State.LINKLINE)
{
FigBase shape = FindShapeByLocation(e.Location);
FigBase shape = FindShapeByLocation(e.Location); // 마우스가 어떤 도형안에 있는지 검색
if (shape != null)
{
_state = "MOVE"; // 움직이는 상태로 바꿈
_movingShape = shape; // 해당 도형을 레퍼런스
_selectState = State.MOVE; // 움직이는 상태로 바꿈
_movingShape = shape; // 해당 도형을 레퍼런스
}
}
// 마우스를 클릭한 상태에서 링크 라인을 그리겠다고 선택한 경우
else if (e.Button == MouseButtons.Left && _figName == "LINKLINE")
else if (e.Button == MouseButtons.Left && _selectState == State.LINKLINE)
{
if (_linkStartShape == null) // 처음 도형을 선택한것만 저장하기 위함. (다른 영역의 도형으로 넘어가도 실행안함)
// 처음 도형을 선택한것만 저장하기 위함. (다른 영역의 도형으로 넘어가도 실행안함)
if (_linkStartShape == null)
{
_linkStartShape = FindShapeByLocation(e.Location);
_linkStartShape = FindShapeByLocation(e.Location); // 마우스가 어떤 도형안에 있는지 검색
if (_linkStartShape != null)
{
_state = "MOVE";
_selectState = State.LINKLINE;
}
}
}
......@@ -72,40 +84,33 @@ namespace flowchart
base.OnMouseMove(e);
}
// 실제 도형을 그리거나 이동하는 함수, 최종 OnPaint() 함수가 호출되어 실행됨
// 실제 그릴 도형정보를 리스트 자료구조에 삽입하고, OnPaint() 함수를 호출
protected override void OnMouseUp(MouseEventArgs e)
{
//System.Diagnostics.Trace.WriteLine("debug >>>" + _state);
// 그리기 상태
if (_state == "DRAW")
if (_selectState == State.RECTANGLE) // 사각형 그리기 선택
{
if (_figName == "RECTANGLE")
{
// 사각형에 대한 정보를 자료구조에 삽입한다.
FigRectangle rectangle = new FigRectangle(e.Location, new System.Drawing.Size(100, 100));
_shapes.Add(rectangle);
}
else if (_figName == "RHOMBUS")
{
FigRhombus rhombus = new FigRhombus(e.Location, new System.Drawing.Size(100, 100));
_shapes.Add(rhombus);
}
else if (_figName == "PARALLELOGRAM")
{
FigParallelogram parallelogram = new FigParallelogram(e.Location, new System.Drawing.Size(100, 100));
_shapes.Add(parallelogram);
}
// 사각형에 대한 정보를 자료구조에 삽입한다.
FigRectangle rectangle = new FigRectangle(e.Location, new System.Drawing.Size(100, 100));
_shapes.Add(rectangle);
}
else if (_selectState == State.RHOMBUS) // 마름모 그리기 선택
{
FigRhombus rhombus = new FigRhombus(e.Location, new System.Drawing.Size(100, 100));
_shapes.Add(rhombus);
}
else if (_selectState == State.PARALLELOGRAM) // 평행사변형 그리기 선택
{
FigParallelogram parallelogram = new FigParallelogram(e.Location, new System.Drawing.Size(100, 100));
_shapes.Add(parallelogram);
}
// 움직이는 상태이고 링크 라인을 그리지 않는 경우 (단순 도형 이동)
else if (_state == "MOVE" && _figName != "LINKLINE")
else if (_selectState == State.MOVE) // 도형을 움직이는 상태로 선택한 경우
{
if (_movingShape != null)
{
_movingShape.Location = e.Location; // 찾은 도형의 위치값을 옮길위치로 수정
_movingShape.Location = e.Location; // 자료구조에서 찾은 도형의 위치값을 옮길위치로 수정
}
}
// 움직이는 상태이고 링크 라인을 그리는 경우 (링크 라인을 긋는 경우)
else if (_state == "MOVE" && _figName == "LINKLINE")
else if (_selectState == State.LINKLINE) // 선을 그리기로 선택한 경우
{
if (_linkStartShape != null)
{
......@@ -126,10 +131,22 @@ namespace flowchart
}
}
_state = "NONE";
_selectState = State.NONE;
this.Refresh(); // 다시 그리기 요청: OnPaint()
base.OnMouseUp(e);
}
// 도형 안에서 마우스를 더블클릭하면 텍스트 에디터를 삽입한다.
protected override void OnMouseDoubleClick(MouseEventArgs e)
{
FigBase shape = FindShapeByLocation(e.Location);
if (shape != null)
{
shape.EnterEditMode(); // FigBase에 함수 있음
}
base.OnMouseDoubleClick(e);
}
// 실제 그리는 OnPaint를 통해 내가 작성한 Draw함수를 호출한다.
protected override void OnPaint(PaintEventArgs e)
......@@ -147,7 +164,7 @@ namespace flowchart
base.OnPaint(e);
}
// 현재 위치에 해당하는 도형을 자료구조에서 레퍼런스 함
// 현재 위치에 해당하는 도형을 자료구조에서 찾아서 레퍼런스 함
private FigBase FindShapeByLocation(Point location)
{
foreach (FigBase s in _shapes)
......
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace flowchart
{
// flowchart 도형을 그리는 클래스의 공통(부모 클래스)
// 변수: 위치(_location), 크기(_size). 링크선 위치(_linkPoints)
// 함수: 그리기(Draw), 영역내에 있는지 확인(PointInRegion)
class FigBase
{
private Point _location; // 위치 변수
private Size _size; // 크기 변수
private Point[] _linkPoints = new Point[] { Point.Empty, Point.Empty, Point.Empty, Point.Empty }; // Top, Left, Bottom, Right
// 텍스트 박스와 관련된 변수
private TextBox _textBox = null;
private string _text; // 텍스트박스 글자
private Rectangle _textArea; // 위치계산 용
private bool _editMode = false; // 더블클릭여부 판단
protected FigBase(Point location, Size size) // 생성자 (위치와 크기를 저장)
{
_location = location;
_size = size;
CalculateLinkPoint();
CalculateLinkPoint(); // 선을 연결하기 위해 도형 주위의 4개의 위치값을 재계산
CalculateTextArea(); // 텍스트박스의 위치를 재계산
}
// 내부 변수를 외부에서 접근하는 함수
......@@ -30,7 +37,8 @@ namespace flowchart
set
{
_location = value;
CalculateLinkPoint(); // 선을 연결하기 위해 도형 주위의 4개의 위치값을 재계산
CalculateLinkPoint();
CalculateTextArea();
}
}
public Size Size
......@@ -39,7 +47,8 @@ namespace flowchart
set
{
_size = value;
CalculateLinkPoint(); // 선을 연결하기 위해 도형 주위의 4개의 위치값을 재계산
CalculateLinkPoint();
CalculateTextArea();
}
}
public Point[] LinkPoints { get => _linkPoints; set => _linkPoints = value; }
......@@ -47,7 +56,15 @@ namespace flowchart
// 자식 클래스에 필요한 공통 함수
public virtual void Draw(Graphics g)
{
// 에디트 모드 경우만 글자를 삽입한다.
if (!_editMode)
{
using (Font font = new Font("맑은 고딕", 16, FontStyle.Regular, GraphicsUnit.Pixel))
{
PointF pointF1 = new PointF(_textArea.X, _textArea.Y);
g.DrawString(_text, font, Brushes.Black, pointF1);
}
}
}
......@@ -66,5 +83,49 @@ namespace flowchart
_linkPoints[2] = new Point(_location.X + (int)(((float)_size.Width) / 2), _location.Y + _size.Height); // Bottom
_linkPoints[3] = new Point(_location.X + _size.Width, _location.Y + (int)(((float)_size.Height) / 2)); // Right
}
// 텍스트 박스의 위치를 계산한다.
private void CalculateTextArea()
{
_textArea = new Rectangle(_location, _size);
_textArea.Inflate(-20, -20);
}
// 도형에서 마우스를 더블클릭하면 호출된다.
public virtual void EnterEditMode()
{
if (!_editMode)
{
_editMode = true;
if (_textBox == null)
{
_textBox = new TextBox();
_textBox.Font = new Font("맑은 고딕", 16, FontStyle.Regular, GraphicsUnit.Pixel);
_textBox.Parent = CustomPanel._parentControl; // 판넬을 부모로 지정
_textBox.KeyDown += TextBox_KeyDown; // 키다운 이벤트를 호출한다.
}
else
{
_textBox.Show();
}
_textBox.Location = _textArea.Location;
_textBox.Size = _textArea.Size;
}
}
// 에디트 모드를 종료한댜.
private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
TextBox textBox = (TextBox)sender;
_text = textBox.Text;
textBox.Hide();
textBox.Clear();
_editMode = false;
}
}
}
}
......
......@@ -10,6 +10,8 @@ namespace flowchart
{
class FigLinkline
{
// 도형과 도형사이에 선을 연결하는 클래스
private FigBase _startShape; // 링크 라인의 시작 위치
private FigBase _endShape; // 링크 라인의 종료 위치
......
......@@ -9,6 +9,9 @@ namespace flowchart
{
class FigParallelogram : FigBase
{
// 프로세스 평행사변형을 그리는 클래스(FigureBase를 상속)
// Draw 함수에서 평행사변형을 그린다.
// 생성자도 상속해서 사용.
public FigParallelogram(Point location, Size size) : base(location, size)
{
......
......@@ -9,6 +9,9 @@ namespace flowchart
{
class FigRhombus : FigBase
{
// 프로세스 마름모를 그리는 클래스(FigureBase를 상속)
// Draw 함수에서 마름모를 그린다.
// 생성자도 상속해서 사용.
public FigRhombus(Point location, Size size) : base(location, size)
{
......
......@@ -45,7 +45,7 @@ namespace flowchart
this.btn_default.TabIndex = 0;
this.btn_default.Text = "default";
this.btn_default.UseVisualStyleBackColor = true;
this.btn_default.Click += new System.EventHandler(this.btn_default_Click_1);
this.btn_default.Click += new System.EventHandler(this.btn_default_Click);
//
// btn_rectangle
//
......@@ -55,7 +55,7 @@ namespace flowchart
this.btn_rectangle.TabIndex = 1;
this.btn_rectangle.Text = "process";
this.btn_rectangle.UseVisualStyleBackColor = true;
this.btn_rectangle.Click += new System.EventHandler(this.btn_rectangle_Click_1);
this.btn_rectangle.Click += new System.EventHandler(this.btn_rectangle_Click);
//
// btn_rhombus
//
......@@ -65,7 +65,7 @@ namespace flowchart
this.btn_rhombus.TabIndex = 2;
this.btn_rhombus.Text = "if";
this.btn_rhombus.UseVisualStyleBackColor = true;
this.btn_rhombus.Click += new System.EventHandler(this.btn_rhombus_Click_1);
this.btn_rhombus.Click += new System.EventHandler(this.btn_rhombus_Click);
//
// btn_linkline
//
......@@ -80,11 +80,9 @@ namespace flowchart
// CustomPanel
//
this.CustomPanel.BackColor = System.Drawing.SystemColors.ActiveBorder;
this.CustomPanel.FigName = null;
this.CustomPanel.Location = new System.Drawing.Point(174, 10);
this.CustomPanel.Name = "CustomPanel";
this.CustomPanel.Size = new System.Drawing.Size(707, 533);
this.CustomPanel.State = null;
this.CustomPanel.TabIndex = 0;
//
// btn_parallelogram
......
......@@ -17,42 +17,32 @@ namespace flowchart
InitializeComponent();
}
private void btn_default_Click_1(object sender, EventArgs e)
private void btn_default_Click(object sender, EventArgs e)
{
// 초기상태
CustomPanel.State = "NONE";
CustomPanel.FigName = "NONE";
CustomPanel.Cursor = Cursors.Default;
CustomPanel.SelectState = State.NONE; // 선택 없음
CustomPanel.Cursor = Cursors.Default; // 마우스 모양은 기본
}
private void btn_rectangle_Click_1(object sender, EventArgs e)
private void btn_rectangle_Click(object sender, EventArgs e)
{
CustomPanel.State = "DRAW"; // 도형을 그리겠다고 선택
CustomPanel.FigName = "RECTANGLE"; // 사각형을 선택
CustomPanel.Cursor = Cursors.Hand;
CustomPanel.SelectState = State.RECTANGLE; // 사각형을 선택
CustomPanel.Cursor = Cursors.Hand; // 마우스 모양은 손모양
}
private void btn_rhombus_Click_1(object sender, EventArgs e)
private void btn_rhombus_Click(object sender, EventArgs e)
{
CustomPanel.State = "DRAW";
CustomPanel.FigName = "RHOMBUS"; // 마름모를 선택
CustomPanel.Cursor = Cursors.Hand;
CustomPanel.SelectState = State.RHOMBUS; // 마름모를 선택
CustomPanel.Cursor = Cursors.Hand; // 마우스 모양은 손모양
}
private void btn_parallelogram_Click(object sender, EventArgs e)
{
CustomPanel.State = "DRAW";
CustomPanel.FigName = "PARALLELOGRAM"; // 사각형을 선택
CustomPanel.Cursor = Cursors.Hand;
CustomPanel.SelectState = State.PARALLELOGRAM; // 평행사변형을 선택
CustomPanel.Cursor = Cursors.Hand; // 마우스 모양은 손모양
}
private void btn_linkline_Click(object sender, EventArgs e)
{
CustomPanel.State = "DRAW";
CustomPanel.FigName = "LINKLINE"; // 링크 라인을 선택
// CustomPanel.Cursor = Cursors.Hand;
CustomPanel.SelectState = State.LINKLINE; // 링크 라인을 선택
}
}
}
......
No preview for this file type