그림판? 그림 이동? 별그리기...
전에 SBS 자막 프로젝트 할때...
당시 그쪽 인력들은 죄다 그래픽 관련인지라 더군다나 C++을 아주 아주 능숙하게 사용하는 사람들이었는데...
정말 잘 만들던데...
오늘 훈스에 별그리기, 그린 선을 클릭해서 이동하는 방법... 들에 대한 문의가 올라왔다.
그 동안 나도 공부도 했다 싶어서 도전... 별과 함게 딱 3시간 반,,, 별은 그닥 오래 안걸렸는데...
선 이동하는게 쉽지 않군... 그리는것 부터 해서 이동하는데 걸린 작업시간이 3시간. ( 뭐 나름 선방했다 치자.. )
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace makeClass
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// 깜빡거릴것 같은....
DoubleBuffered = true;
}
/// <summary>
/// 자료구조( 점과 영역 저장)
/// </summary>
SortedList<string, PointList> Points = new SortedList<string, PointList>();
protected override void OnPaint(PaintEventArgs e)
{
// 선택시 활성화
if (_Selected)
{
e.Graphics.DrawRectangle(Pens.RoyalBlue, Rectangle.Truncate(Points[SelectKey].Region));
}
// 저장된 점 모두 그림.
foreach (KeyValuePair<string, PointList > p1 in Points)
{
for (int i = 0; i < p1.Value.Points.Count - 1; i++)
{
e.Graphics.DrawLine(Pens.Red, p1.Value.Points[i], p1.Value.Points[i + 1]);
}
}
base.OnPaint(e);
}
//마우스 눌렸을때 ( 그리기 모드 )
bool _MouseDown = false;
//선택되었을때 ( 이동 모드 )
bool _Selected = false;
// 선택키
string SelectKey = "";
#region 그리기 & 이동에 필요한 변수
PointF pt = new PointF();
List<PointF> tmp = null;
RectangleF rct; //= new Rectangle(0,0,0,0);
#endregion
protected override void OnMouseDown(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left) // 그리기
{
rct = new RectangleF(0,0,0,0);
pt = rct.Location = e.Location;
tmp = new List<PointF>();
tmp.Add(e.Location);
_MouseDown = true;
}
else if ( e.Button == MouseButtons.Right ) // 이동하기
{
pt = e.Location;
foreach (KeyValuePair<string, PointList> kv in Points)
{
_Selected = kv.Value.Region.Contains(e.Location);
if (_Selected)
{
SelectKey = kv.Key;
tmp = kv.Value.Points;
rct = kv.Value.Region;
break;
}
}
}
base.OnMouseDown(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
if ( _MouseDown && tmp != null )
{
tmp.Add(e.Location);
using (Graphics g = Graphics.FromHwnd(this.Handle))
{
g.DrawLines(Pens.Red, tmp.ToArray() ); // 그리는걸 보여주기 위해..
}
}
else if (_Selected && tmp != null)
{
tmp = Points[SelectKey].Points;
PointF tm;
// 포인트 스왑
for (int idx = 0; idx < tmp.Count; idx++ )
{
tm = tmp[idx];
tm.X += e.Location.X - pt.X;
tm.Y += e.Location.Y - pt.Y;
tmp[idx] = tm;
}
// 영역 스왑
rct = Points[SelectKey].Region;
rct.X += e.Location.X - pt.X;
rct.Y += e.Location.Y - pt.Y;
Points[SelectKey].Region = rct;
using (Graphics g = Graphics.FromHwnd(this.Handle))
{
// 이동시 잔상 제거 및 다시 그리기.
Invalidate( Rectangle.Truncate( new RectangleF( rct.X - 100f, rct.Y - 100f, rct.Width + 200f, rct.Height + 200f )), true);
}
pt = e.Location;
}
// base.OnMouseMove(e);
}
/// <summary>
/// 자료구조 키값. ( 생성시... Object 구분값으로 씀)
/// </summary>
int PointKey = 0;
protected override void OnMouseUp(MouseEventArgs e)
{
if (tmp != null)
{
if (_MouseDown == true)
{
tmp.Add(e.Location);
float maxX = 0;
float maxY = 0;
foreach (PointF pf in tmp)
{
if (rct.X > pf.X) rct.X = pf.X;
if (rct.Y > pf.Y) rct.Y = pf.Y;
if (maxX < pf.X) maxX = pf.X;
if (maxY < pf.Y) maxY = pf.Y;
}
rct.Width = maxX - rct.X;
rct.Height = maxY - rct.Y;
Points.Add((PointKey++).ToString(), new PointList(rct, tmp));
}
// 해제
_Selected = false;
_MouseDown = false;
Invalidate();
tmp = null;
}
base.OnMouseUp(e);
}
// 별그리기...
private void DrawStar(Graphics g, double r, PointF p)
{
PointF[] ps = new PointF[6];
double RadianTheta = 0d;
int cnt = 0;
for (double i = 0; i <= 720d; i += 144d )
{
RadianTheta = i * Math.PI / 180 ;
ps[ cnt ] = new PointF( p.X + (float)( r * 1d * Math.Cos( RadianTheta )) ,
p.Y + (float)( r * 1d * Math.Sin( RadianTheta ) ) );
cnt ++;
}
g.DrawLines(Pens.Red, ps);
}
// 자료구조.
public class PointList
{
public PointList(RectangleF rt, List<PointF> lp )
{
region = rt; points = lp;
}
RectangleF region = new RectangleF();
public RectangleF Region
{
get { return region; }
set { region = value; }
}
List<PointF> points = new List<PointF>();
public List<PointF> Points
{
get { return points; }
set { points = value; }
}
}
}
}
'# 2) .Net ( Vs 2005 ) > WinForm' 카테고리의 다른 글
3가지중 1개로 선택해서 바꿈] 더블 삼항연산자 (0) | 2013.08.01 |
---|---|
[ C# WinForm ] 음.. 달력!! (0) | 2011.03.24 |
런타임상에서의 컨트롤 사이즈 드래그!!! (0) | 2010.06.10 |
서버 - 클라이언트 ... (0) | 2010.05.08 |
타이머 구현... (0) | 2010.04.08 |