728x90
728x170
■ 소용돌이 프랙탈(Vortex Fractal)을 그리는 방법을 보여준다.
▶ Complex.cs
using System;
namespace TestProject
{
/// <summary>
/// 복소수
/// </summary>
public class Complex
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Public
#region Field
/// <summary>
/// 실수부
/// </summary>
public double Real = 0d;
/// <summary>
/// 허수부
/// </summary>
public double Imaginary = 0d;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 크기 - Magnitude
/// <summary>
/// 크기
/// </summary>
public double Magnitude
{
get
{
return (Math.Sqrt(Real * Real + Imaginary * Imaginary));
}
}
#endregion
#region 제곱 크기 - MagnitudeSquared
/// <summary>
/// 제곱 크기
/// </summary>
public double MagnitudeSquared
{
get
{
return (Real * Real + Imaginary * Imaginary);
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - Complex(real, imaginary)
/// <summary>
/// 생성자
/// </summary>
/// <param name="real">실수부</param>
/// <param name="imaginary">허수부</param>
public Complex(double real, double imaginary)
{
Real = real;
Imaginary = imaginary;
}
#endregion
#region 생성자 - Complex(real)
/// <summary>
/// 생성자
/// </summary>
/// <param name="real">실수부</param>
public Complex(double real)
{
Real = real;
Imaginary = 0d;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 파싱하기 - Parse(source)
/// <summary>
/// 파싱하기
/// </summary>
/// <param name="source">소스 문자열</param>
/// <returns>복소수</returns>
public static Complex Parse(string source)
{
source = source.Replace(" ", "");
source = source.ToLower().Replace("i", "");
char[] characterArray = { '+', '-' };
int position = source.IndexOfAny(characterArray);
if(position == 0)
{
position = source.IndexOfAny(characterArray, 1);
}
double real = double.Parse(source.Substring(0, position));
double imaginary = double.Parse(source.Substring(position));
return new Complex(real, imaginary);
}
#endregion
#region + 연산자 재정의하기 - +(c)
/// <summary>
/// + 연산자 재정의하기
/// </summary>
/// <param name="c">복소수</param>
/// <returns>복소수</returns>
public static Complex operator +(Complex c)
{
return new Complex(c.Real, c.Imaginary);
}
#endregion
#region - 연산자 재정의하기 - -(c)
/// <summary>
/// - 연산자 재정의하기
/// </summary>
/// <param name="c">복소수</param>
/// <returns>복소수</returns>
public static Complex operator -(Complex c)
{
return new Complex(-c.Real, -c.Imaginary);
}
#endregion
#region + 연산자 재정의하기 - +(c1, c2)
/// <summary>
/// + 연산자 재정의하기
/// </summary>
/// <param name="c1">복소수 1</param>
/// <param name="c2">복소수 2</param>
/// <returns>복소수</returns>
public static Complex operator +(Complex c1, Complex c2)
{
return new Complex(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary);
}
#endregion
#region - 연산자 재정의하기 - -(c1, c2)
/// <summary>
/// - 연산자 재정의하기
/// </summary>
/// <param name="c1">복소수 1</param>
/// <param name="c2">복소수 2</param>
/// <returns>복소수</returns>
public static Complex operator -(Complex c1, Complex c2)
{
return new Complex(c1.Real - c2.Real, c1.Imaginary - c2.Imaginary);
}
#endregion
#region * 연산자 재정의하기 - *(c1, c2)
/// <summary>
/// * 연산자 재정의하기
/// </summary>
/// <param name="c1">복소수 1</param>
/// <param name="c2">복소수 2</param>
/// <returns>복소수</returns>
public static Complex operator *(Complex c1, Complex c2)
{
return new Complex
(
c1.Real * c2.Real - c1.Imaginary * c2.Imaginary,
c1.Real * c2.Imaginary + c1.Imaginary * c2.Real
);
}
#endregion
#region / 연산자 재정의하기 - /(c1, c2)
/// <summary>
/// / 연산자 재정의하기
/// </summary>
/// <param name="c1">복소수 1</param>
/// <param name="c2">복소수 2</param>
/// <returns>복소수</returns>
public static Complex operator /(Complex c1, Complex c2)
{
double denominator = c2.Real * c2.Real + c2.Imaginary * c2.Imaginary;
double real = (c1.Real * c2.Real + c1.Imaginary * c2.Imaginary) / denominator;
double imaginary = (c1.Imaginary * c2.Real - c1.Real * c2.Imaginary) / denominator;
return new Complex(real, imaginary);
}
#endregion
#region < 연산자 재정의하기 - <(c1, c2)
/// <summary>
/// < 연산자 재정의하기
/// </summary>
/// <param name="c1">복소수 1</param>
/// <param name="c2">복소수 2</param>
/// <returns>처리 결과</returns>
public static bool operator <(Complex c1, Complex c2)
{
return (c1.Magnitude < c2.Magnitude);
}
#endregion
#region > 연산자 재정의하기 - >(c1, c2)
/// <summary>
/// > 연산자 재정의하기
/// </summary>
/// <param name="c1">복소수 1</param>
/// <param name="c2">복소수 2</param>
/// <returns>처리 결과</returns>
public static bool operator >(Complex c1, Complex c2)
{
return (c1.Magnitude > c2.Magnitude);
}
#endregion
#region <= 연산자 재정의하기 - <=(c1, c2)
/// <summary>
/// <= 연산자 재정의하기
/// </summary>
/// <param name="c1">복소수 1</param>
/// <param name="c2">복소수 2</param>
/// <returns>처리 결과</returns>
public static bool operator <=(Complex c1, Complex c2)
{
return (c1.Magnitude <= c2.Magnitude);
}
#endregion
#region >= 연산자 재정의하기 - >=(c1, c2)
/// <summary>
/// >= 연산자 재정의하기
/// </summary>
/// <param name="c1">복소수 1</param>
/// <param name="c2">복소수 2</param>
/// <returns>처리 결과</returns>
public static bool operator >=(Complex c1, Complex c2)
{
return (c1.Magnitude >= c2.Magnitude);
}
#endregion
#region == 연산자 재정의하기 - ==(c1, c2)
/// <summary>
/// == 연산자 재정의하기
/// </summary>
/// <param name="c1">복소수 1</param>
/// <param name="c2">복소수 2</param>
/// <returns>처리 결과</returns>
public static bool operator ==(Complex c1, Complex c2)
{
return (c1.Real == c2.Real && c1.Imaginary == c2.Imaginary);
}
#endregion
#region != 연산자 재정의하기 - !=(c1, c2)
/// <summary>
/// != 연산자 재정의하기
/// </summary>
/// <param name="c1">복소수 1</param>
/// <param name="c2">복소수 2</param>
/// <returns>처리 결과</returns>
public static bool operator !=(Complex c1, Complex c2)
{
return !(c1 == c2);
}
#endregion
#region 암시적 형변환 하기 - Complex(real)
/// <summary>
/// 암시적 형변환 하기
/// </summary>
/// <param name="real"></param>
public static implicit operator Complex(double real)
{
return new Complex(real, 0);
}
#endregion
#region 명시적 형변환 하기 - double(c)
/// <summary>
/// 명시적 형변환 하기
/// </summary>
/// <param name="c">복소수</param>
public static explicit operator double(Complex c)
{
return c.Magnitude;
}
#endregion
#region 동일 여부 구하기 - Equals(instance)
/// <summary>
/// 동일 여부 구하기
/// </summary>
/// <param name="instance">인스턴스</param>
/// <returns>동일 여부</returns>
public override bool Equals(object instance)
{
Complex c = instance as Complex;
return this == c;
}
#endregion
#region 해시 코드 구하기 - GetHashCode()
/// <summary>
/// 해시 코드 구하기
/// </summary>
/// <returns>해시 코드</returns>
public override int GetHashCode()
{
return Real.GetHashCode() | Imaginary.GetHashCode();
}
#endregion
#region 문자열 구하기 - ToString()
/// <summary>
/// 문자열 구하기
/// </summary>
/// <returns>문자열</returns>
public override string ToString()
{
if(Imaginary == 0)
{
return string.Format("{0}", Real);
}
if(Real == 0)
{
return string.Format("{0}i", Imaginary);
}
if(Imaginary < 0)
{
return string.Format("{0} - {1}i", Real, Math.Abs(Imaginary));
}
return string.Format("{0} + {1}i", Real, Imaginary);
}
#endregion
#region 문자열 구하기 - ToString(format)
/// <summary>
/// 문자열 구하기
/// </summary>
/// <param name="format">포맷</param>
/// <returns>문자열</returns>
public string ToString(string format)
{
if(Imaginary == 0)
{
return string.Format("{0:" + format + "}", Real);
}
if(Real == 0)
{
return string.Format("{0:" + format + "}i", Imaginary);
}
if(Imaginary < 0)
{
return string.Format("{0:" + format + "} - {1:" + format + "}i", Real, Math.Abs(Imaginary));
}
return string.Format("{0:" + format + "} + {1:" + format + "}i", Real, Imaginary);
}
#endregion
}
}
▶ MainForm.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
namespace TestProject
{
/// <summary>
/// 메인 폼
/// </summary>
public partial class MainForm : Form
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Public
#region Field
/// <summary>
/// 최대 반복 카운트
/// </summary>
public int MaximumIterationCount;
/// <summary>
/// 복소수
/// </summary>
public Complex Complex;
/// <summary>
/// 색상 리스트
/// </summary>
public List<Color> ColorList = new List<Color>();
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 최소 X
/// </summary>
private const double MINIMUM_X = -2;
/// <summary>
/// 최대 X
/// </summary>
private const double MAXIMUM_X = 2;
/// <summary>
/// 최소 Y
/// </summary>
private const double MINIMUM_Y = -2;
/// <summary>
/// 최소 Y
/// </summary>
private const double MAXIMUM_Y = 2;
/// <summary>
/// 상자 그리기 여부
/// </summary>
private bool isDrawingBox;
/// <summary>
/// 시작 X
/// </summary>
private double startX;
/// <summary>
/// 시작 Y
/// </summary>
private double startY;
/// <summary>
/// 현재 X
/// </summary>
private double currentX;
/// <summary>
/// 현재 Y
/// </summary>
private double currentY;
/// <summary>
/// 최소 X
/// </summary>
private double minimumX;
/// <summary>
/// 최대 X
/// </summary>
private double maximumX;
/// <summary>
/// 최소 Y
/// </summary>
private double minimumY;
/// <summary>
/// 최대 Y
/// </summary>
private double maximumY;
/// <summary>
/// 비트맵
/// </summary>
private Bitmap bitmap;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainForm()
/// <summary>
/// 생성자
/// </summary>
public MainForm()
{
InitializeComponent();
#region 이벤트를 설정한다.
Load += Form_Load;
this.saveAsMenuItem.Click += saveAsMenuItem_Click;
this.scaleX2MenuItem.Click += scaleMenuItem_Click;
this.scaleX4MenuItem.Click += scaleMenuItem_Click;
this.scaleX8MenuItem.Click += scaleMenuItem_Click;
this.fullScaleMenuItem.Click += fullScaleMenuItem_Click;
this.refreshMenuItem.Click += refreshMenuItem_Click;
this.setOptionMenuItem.Click += setOptionMenuItem_Click;
this.canvasPictureBox.MouseDown += canvasPictureBox_MouseDown;
this.canvasPictureBox.MouseMove += canvasPictureBox_MouseMove;
this.canvasPictureBox.MouseUp += canvasPictureBox_MouseUp;
#endregion
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Event
//////////////////////////////////////////////////////////////////////////////// Private
#region 폼 로드시 처리하기 - Form_Load(sender, e)
/// <summary>
/// 폼 로드시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void Form_Load(object sender, EventArgs e)
{
Show();
Application.DoEvents();
MaximumIterationCount = 64;
Complex = new Complex(0.62, -0.55);
ResetColorList();
SettingForm form = new SettingForm();
ColorList.Add(form.color40PictureBox.BackColor);
ColorList.Add(form.color17PictureBox.BackColor);
ColorList.Add(form.color18PictureBox.BackColor);
ColorList.Add(form.color19PictureBox.BackColor);
ColorList.Add(form.color20PictureBox.BackColor);
ColorList.Add(form.color21PictureBox.BackColor);
ColorList.Add(form.color22PictureBox.BackColor);
ColorList.Add(form.color23PictureBox.BackColor);
form.Close();
this.fullScaleMenuItem.PerformClick();
}
#endregion
#region 다른 이름으로 저장하기 메뉴 항목 클릭시 처리하기 - saveAsMenuItem_Click(sender, e)
/// <summary>
/// 다른 이름으로 저장하기 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void saveAsMenuItem_Click(object sender, EventArgs e)
{
if(this.saveFileDialog.ShowDialog() == DialogResult.OK)
{
this.bitmap.Save(this.saveFileDialog.FileName);
string fileName = this.saveFileDialog.FileName;
string fileExtension = fileName.Substring(fileName.LastIndexOf("."));
switch(fileExtension)
{
case ".bmp" : this.bitmap.Save(fileName, ImageFormat.Bmp ); break;
case ".jpg" :
case ".jpeg" : this.bitmap.Save(fileName, ImageFormat.Jpeg); break;
case ".gif" : this.bitmap.Save(fileName, ImageFormat.Gif ); break;
case ".png" : this.bitmap.Save(fileName, ImageFormat.Png ); break;
case ".tif" :
case ".tiff" : this.bitmap.Save(fileName, ImageFormat.Tiff); break;
}
}
}
#endregion
#region 스케일 메뉴 항목 클릭시 처리하기 - scaleMenuItem_Click(sender, e)
/// <summary>
/// 스케일 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void scaleMenuItem_Click(object sender, EventArgs e)
{
MenuItem menuItem = sender as MenuItem;
ScaleArea(int.Parse(menuItem.Tag.ToString()));
}
#endregion
#region 전체 스케일 메뉴 항목 클릭시 처리하기 - fullScaleMenuItem_Click(sender, e)
/// <summary>
/// 전체 스케일 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void fullScaleMenuItem_Click(object sender, EventArgs e)
{
this.minimumX = MINIMUM_X;
this.maximumX = MAXIMUM_X;
this.minimumY = MINIMUM_Y;
this.maximumY = MAXIMUM_Y;
Cursor = Cursors.WaitCursor;
Application.DoEvents();
DrawVortexFractal();
Cursor = Cursors.Default;
this.canvasPictureBox.Cursor = Cursors.Cross;
}
#endregion
#region 새로 고침 메뉴 항목 클릭시 처리하기 - refreshMenuItem_Click(sender, e)
/// <summary>
/// 새로 고침 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void refreshMenuItem_Click(object sender, EventArgs e)
{
ScaleArea(1);
}
#endregion
#region 옵션 설정하기 메뉴 항목 클릭시 처리하기 - setOptionMenuItem_Click(sender, e)
/// <summary>
/// 옵션 설정하기 메뉴 항목 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void setOptionMenuItem_Click(object sender, EventArgs e)
{
SettingForm form = new SettingForm();
form.StartPosition = FormStartPosition.CenterParent;
form.Initialize(this);
form.ShowDialog(this);
}
#endregion
#region 캔버스 픽처 박스 마우스 DOWN 처리하기 - canvasPictureBox_MouseDown(sender, e)
/// <summary>
/// 캔버스 픽처 박스 마우스 DOWN 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void canvasPictureBox_MouseDown(object sender, MouseEventArgs e)
{
this.isDrawingBox = true;
this.startX = e.X;
this.startY = e.Y;
this.currentX = e.X;
this.currentY = e.Y;
}
#endregion
#region 캔버스 픽처 박스 마우스 이동시 처리하기 - canvasPictureBox_MouseMove(sender, e)
/// <summary>
/// 캔버스 픽처 박스 마우스 이동시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void canvasPictureBox_MouseMove(object sender, MouseEventArgs e)
{
if(!this.isDrawingBox)
{
return;
}
this.currentX = e.X;
this.currentY = e.Y;
Bitmap newBitmap = new Bitmap(this.bitmap);
Graphics newBitmapGraphics = Graphics.FromImage(newBitmap);
newBitmapGraphics.DrawRectangle
(
Pens.Yellow,
(int)(Math.Min(this.startX, this.currentX)),
(int)(Math.Min(this.startY, this.currentY)),
(int)(Math.Abs(this.startX - this.currentX)),
(int)(Math.Abs(this.startY - this.currentY))
);
this.canvasPictureBox.Image = newBitmap;
}
#endregion
#region 캔버스 픽처 박스 마우스 UP 처리하기 - canvasPictureBox_MouseUp(sender, e)
/// <summary>
/// 캔버스 픽처 박스 마우스 UP 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void canvasPictureBox_MouseUp(object sender, MouseEventArgs e)
{
if(!this.isDrawingBox)
{
return;
}
this.isDrawingBox = false;
this.canvasPictureBox.Image = this.bitmap;
this.currentX = e.X;
this.currentY = e.Y;
double x1 = Math.Min(this.startX, this.currentX);
double x2 = Math.Max(this.startX, this.currentX);
if(x1 == x2)
{
x2 = x1 + 1;
}
double y1 = Math.Min(this.startY, this.currentY);
double y2 = Math.Max(this.startY, this.currentY);
if(y1 == y2)
{
y2 = y1 + 1;
}
double factor = (this.maximumX - this.minimumX) / this.canvasPictureBox.ClientSize.Width;
this.maximumX = this.minimumX + x2 * factor;
this.minimumX = this.minimumX + x1 * factor;
factor = (this.maximumY - this.minimumY) / this.canvasPictureBox.ClientSize.Height;
this.maximumY = this.minimumY + y2 * factor;
this.minimumY = this.minimumY + y1 * factor;
Cursor = Cursors.WaitCursor;
Application.DoEvents();
DrawVortexFractal();
Cursor = Cursors.Default;
this.canvasPictureBox.Cursor = Cursors.Cross;
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Function
//////////////////////////////////////////////////////////////////////////////// Public
#region 색상 리스트 리셋하기 - ResetColorList()
/// <summary>
/// 색상 리스트 리셋하기
/// </summary>
public void ResetColorList()
{
ColorList = new List<Color>();
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Private
#region 화면비 조정하기 - AdjustAspect()
/// <summary>
/// 화면비 조정하기
/// </summary>
private void AdjustAspect()
{
double height;
double width;
double middle;
double aspectDesired = (this.maximumY - this.minimumY) / (this.maximumX - this.minimumX);
double canvasAspect = this.canvasPictureBox.ClientSize.Height / (double)this.canvasPictureBox.ClientSize.Width;
if(aspectDesired > canvasAspect)
{
width = (this.maximumY - this.minimumY) / canvasAspect;
middle = (this.minimumX + this.maximumX) / 2;
this.minimumX = middle - width / 2;
this.maximumX = middle + width / 2;
}
else
{
height = (this.maximumX - this.minimumX) * canvasAspect;
middle = (this.minimumY + this.maximumY) / 2;
this.minimumY = middle - height / 2;
this.maximumY = middle + height / 2;
}
}
#endregion
#region 소용돌이 프랙탈 그리기 - DrawVortexFractal()
/// <summary>
/// 소용돌이 프랙탈 그리기
/// </summary>
private void DrawVortexFractal()
{
const int MAXIMUM_MAGNITUDE_SQUARED = 8;
this.bitmap = new Bitmap
(
this.canvasPictureBox.ClientSize.Width,
this.canvasPictureBox.ClientSize.Height
);
Graphics graphics = Graphics.FromImage(this.bitmap);
graphics.Clear(this.canvasPictureBox.BackColor);
this.canvasPictureBox.Image = this.bitmap;
Application.DoEvents();
AdjustAspect();
int width = this.canvasPictureBox.ClientRectangle.Width;
int height = this.canvasPictureBox.ClientRectangle.Height;
double real = (this.maximumX - this.minimumX) / (width - 1);
double imaginary = (this.maximumY - this.minimumY) / (height - 1);
int colorCount = ColorList.Count;
double zReal = this.minimumX;
for(int x = 0; x < width; x++)
{
double zImaginary = this.minimumY;
for(int y = 0; y < height; y++)
{
Complex z = new Complex(zReal, zImaginary);
Complex zMinus1 = new Complex(zReal, zImaginary);
int colorValue = 1;
while((colorValue < MaximumIterationCount) && (z.MagnitudeSquared < MAXIMUM_MAGNITUDE_SQUARED))
{
Complex zPlus1 = z * z + Complex.Real + Complex.Imaginary * zMinus1;
zMinus1 = z;
z = zPlus1;
colorValue++;
}
this.bitmap.SetPixel(x, y, ColorList[colorValue % colorCount]);
zImaginary += imaginary;
}
zReal += real;
if(x % 10 == 0)
{
this.canvasPictureBox.Refresh();
}
}
Text = string.Format
(
"소용돌이 프랙탈(Vortex Fractal) 그리기 : Vortex ({0}, {1}) - ({2}, {3})",
this.minimumX.ToString("0.000000"),
this.minimumY.ToString("0.000000"),
this.maximumX.ToString("0.000000"),
this.maximumY.ToString("0.000000")
);
}
#endregion
#region 영역 스케일 처리하기 - ScaleArea(scaleFactor)
/// <summary>
/// 영역 스케일 처리하기
/// </summary>
/// <param name="scaleFactor">스케일 팩터</param>
private void ScaleArea(int scaleFactor)
{
double size = scaleFactor * (this.maximumX - this.minimumX);
if(size > 3.2)
{
this.fullScaleMenuItem.PerformClick();
return;
}
double middle = (this.minimumX + this.maximumX) / 2;
this.minimumX = middle - size / 2;
this.maximumX = middle + size / 2;
size = scaleFactor * (this.maximumY - this.minimumY);
if(size > 2.4)
{
this.fullScaleMenuItem.PerformClick();
return;
}
middle = (this.minimumY + this.maximumY) / 2;
this.minimumY = middle - size / 2;
this.maximumY = middle + size / 2;
Cursor = Cursors.WaitCursor;
Application.DoEvents();
DrawVortexFractal();
Cursor = Cursors.Default;
this.canvasPictureBox.Cursor = Cursors.Cross;
}
#endregion
}
}
728x90
그리드형(광고전용)
'C# > WinForm' 카테고리의 다른 글
[C#/WINFORM] ToolStripButton 클래스 : 라디오 버튼 사용하기 (0) | 2018.12.09 |
---|---|
[C#/WINFORM] ListView 클래스 : 그룹 사용하기 (0) | 2018.12.08 |
[C#/WINFORM] 임의의 선으로 채워진 텍스트 그리기 (0) | 2018.12.08 |
[C#/WINFORM] 외곽선 텍스트 그리기 (0) | 2018.12.08 |
[C#/WINFORM] 부드러운 소용돌이 프랙탈(Smooth Vortex Fractal) 그리기 (0) | 2018.12.08 |
[C#/WINFORM] 소용돌이 모양 프랙탈(Curlicue Fractal) 그리기 (0) | 2018.12.08 |
[C#/WINFORM] 폰트 메트릭(Font Metrics) 구하기 (0) | 2018.12.08 |
[C#/WINFORM] 문자 크기 측정하기 (0) | 2018.12.08 |
[C#/WINFORM] 마우스 드래그시 고무밴드 상자(Rubber Band Box) 표시하기 (0) | 2018.12.08 |
[C#/WINFORM] 포인트 리스트를 둘러싸는 원 구하기 (0) | 2018.12.05 |