Saber_Fatholahi
چهارشنبه 18 بهمن 1391, 13:05 عصر
در ادامه مطالب قبل
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 1# (http://www.dotnettips.info/post/1195/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 2# (http://www.dotnettips.info/post/1208/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 3# (http://www.dotnettips.info/post/1209/)
(http://www.dotnettips.info/post/1209/)پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 4# (http://www.dotnettips.info/post/1214/)
قبل از شروع توضیحات متدهای کلاس Shape در ادامه پستهای قبل در ^ (http://www.dotnettips.info/post/1195/) و ^ (http://www.dotnettips.info/post/1208/) ابتدا به تشریح یک تصویر میپردازیم.
http://www.dotnettips.info/file/image?name=001-35263b09d3d8466182d6a99d43bd6833.png
خوب همانگونه که در تصویر بالا مشاده مینمایید، برای رسم یک شی چهار حالت متفاوت ممکن است پیش بیاید. (دقت کنید که ربع اول محور مختصات روی بوم گرافیکی قرار گرفته است، در واقع گوشه بالا و سمت چپ بوم گرافیکی نقطه (0 و 0) محور مختصات است و عرض بوم گرافیکی محور Xها و ارتفاع بوم گرافیکی محور Yها را نشان میدهد)
در این حالت StartPoint.X < EndPoint.X و StartPoint.Y < EndPoint.Y خواهد بود. (StartPoint نقطه ای است که ابتدا ماوس شروع به ترسیم میکند، و EndPoint زمانی است که ماوس رها شده و پایان ترسیم را مشخص میکند.)
در این حالت StartPoint.X > EndPoint.X و StartPoint.Y > EndPoint.Y خواهد بود.
در این حالت StartPoint.X > EndPoint.X و StartPoint.Y > EndPoint.Y خواهد بود.
در این حالت StartPoint.X < EndPoint.X و StartPoint.Y > EndPoint.Y خواهد بود.
در ادامه پستهای قبل ادامه کد کلاس Shape را تشریح میکنیم.
using System;
using System.Drawing;
namespace PWS.ObjectOrientedPaint.Models
{
/// <summary>
/// Shape (Base Class)
/// </summary>
public abstract partial class Shape
{
#region Constructors (2)
/// <summary>
/// Initializes a new instance of the <see cref="Shape" /> class.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="zIndex">Index of the z.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="isFill">if set to <c>true</c> [is fill].</param>
/// <param name="backgroundColor">Color of the background.</param>
protected Shape(PointF startPoint, PointF endPoint, int zIndex, Color foreColor, byte thickness, bool isFill, Color backgroundColor)
{
CalulateLocationAndSize(startPoint, endPoint);
Zindex = zIndex;
ForeColor = foreColor;
Thickness = thickness;
IsFill = isFill;
BackgroundColor = backgroundColor;
}
/// <summary>
/// Initializes a new instance of the <see cref="Shape" /> class.
/// </summary>
protected Shape() { }
#endregion Constructors
#region Methods (9)
// Public Methods (8)
/// <summary>
/// Draws the specified g.
/// </summary>
/// <param name="g">The g.</param>
public virtual void Draw(Graphics g)
{
if (!IsSelected) return;
float diff = Thickness + 4;
Color myColor = Color.DarkSeaGreen;
g.DrawString(String.Format("({0},{1})", StartPoint.X, StartPoint.Y), new Font(new FontFamily("Tahoma"), 10), new SolidBrush(myColor), StartPoint.X - 20, StartPoint.Y - 25);
g.DrawString(String.Format("({0},{1})", EndPoint.X, EndPoint.Y), new Font(new FontFamily("Tahoma"), 10), new SolidBrush(myColor), EndPoint.X - 20, EndPoint.Y + 5);
if (ShapeType != ShapeType.Line)
{
g.DrawRectangle(new Pen(myColor), X, Y, Width, Height);
// 1 2 3
// 8 4
// 7 6 5
var point1 = new PointF(StartPoint.X - diff / 2, StartPoint.Y - diff / 2);
var point2 = new PointF((StartPoint.X - diff / 2 + EndPoint.X) / 2, StartPoint.Y - diff / 2);
var point3 = new PointF(EndPoint.X - diff / 2, StartPoint.Y - diff / 2);
var point4 = new PointF(EndPoint.X - diff / 2, (EndPoint.Y + StartPoint.Y) / 2 - diff / 2);
var point5 = new PointF(EndPoint.X - diff / 2, EndPoint.Y - diff / 2);
var point6 = new PointF((StartPoint.X - diff / 2 + EndPoint.X) / 2, EndPoint.Y - diff / 2);
var point7 = new PointF(StartPoint.X - diff / 2, EndPoint.Y - diff / 2);
var point8 = new PointF(StartPoint.X - diff / 2, (EndPoint.Y + StartPoint.Y) / 2 - diff / 2);
g.FillRectangle(new SolidBrush(myColor), point1.X, point1.Y, diff, diff);
g.FillRectangle(new SolidBrush(myColor), point2.X, point2.Y, diff, diff);
g.FillRectangle(new SolidBrush(myColor), point3.X, point3.Y, diff, diff);
g.FillRectangle(new SolidBrush(myColor), point4.X, point4.Y, diff, diff);
g.FillRectangle(new SolidBrush(myColor), point5.X, point5.Y, diff, diff);
g.FillRectangle(new SolidBrush(myColor), point6.X, point6.Y, diff, diff);
g.FillRectangle(new SolidBrush(myColor), point7.X, point7.Y, diff, diff);
g.FillRectangle(new SolidBrush(myColor), point8.X, point8.Y, diff, diff);
}
else
{
var point1 = new PointF(StartPoint.X - diff / 2, StartPoint.Y - diff / 2);
var point2 = new PointF(EndPoint.X - diff / 2, EndPoint.Y - diff / 2);
g.FillRectangle(new SolidBrush(myColor), point1.X, point1.Y, diff, diff);
g.FillRectangle(new SolidBrush(myColor), point2.X, point2.Y, diff, diff);
}
}
/// <summary>
/// Draws the preview.
/// </summary>
/// <param name="g">The g.</param>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="foreColor">Color of the fore.</param>
public void DrawPreview(Graphics g, PointF startPoint, PointF endPoint, Color foreColor)
{
DrawPreview(g, startPoint, endPoint, foreColor, Thickness, IsFill, BackgroundColor, ShapeType);
}
/// <summary>
/// Draws the preview.
/// </summary>
/// <param name="g">The g.</param>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="isFill">if set to <c>true</c> [is fill].</param>
/// <param name="backgroundColor">Color of the background.</param>
/// <param name="shapeType">Type of the shape.</param>
public static void DrawPreview(Graphics g, PointF startPoint, PointF endPoint, Color foreColor, byte thickness, bool isFill, Color backgroundColor, ShapeType shapeType)
{
float x = 0, y = 0;
float width = Math.Abs(endPoint.X - startPoint.X);
float height = Math.Abs(endPoint.Y - startPoint.Y);
if (startPoint.X <= endPoint.X && startPoint.Y <= endPoint.Y)
{
x = startPoint.X;
y = startPoint.Y;
}
else if (startPoint.X >= endPoint.X && startPoint.Y >= endPoint.Y)
{
x = endPoint.X;
y = endPoint.Y;
}
else if (startPoint.X >= endPoint.X && startPoint.Y <= endPoint.Y)
{
x = endPoint.X;
y = startPoint.Y;
}
else if (startPoint.X <= endPoint.X && startPoint.Y >= endPoint.Y)
{
x = startPoint.X;
y = endPoint.Y;
}
switch (shapeType)
{
case ShapeType.Ellipse:
if (isFill)
g.FillEllipse(new SolidBrush(backgroundColor), x, y, width, height);
//else
g.DrawEllipse(new Pen(foreColor, thickness), x, y, width, height);
break;
case ShapeType.Rectangle:
if (isFill)
g.FillRectangle(new SolidBrush(backgroundColor), x, y, width, height);
//else
g.DrawRectangle(new Pen(foreColor, thickness), x, y, width, height);
break;
case ShapeType.Circle:
float raduis = Math.Max(width, height);
if (isFill)
g.FillEllipse(new SolidBrush(backgroundColor), x, y, raduis, raduis);
//else
g.DrawEllipse(new Pen(foreColor, thickness), x, y, raduis, raduis);
break;
case ShapeType.Square:
float side = Math.Max(width, height);
if (isFill)
g.FillRectangle(new SolidBrush(backgroundColor), x, y, side, side);
//else
g.DrawRectangle(new Pen(foreColor, thickness), x, y, side, side);
break;
case ShapeType.Line:
g.DrawLine(new Pen(foreColor, thickness), startPoint, endPoint);
break;
case ShapeType.Diamond:
var points = new PointF[4];
points[0] = new PointF(x + width / 2, y);
points[1] = new PointF(x + width, y + height / 2);
points[2] = new PointF(x + width / 2, y + height);
points[3] = new PointF(x, y + height / 2);
if (isFill)
g.FillPolygon(new SolidBrush(backgroundColor), points);
//else
g.DrawPolygon(new Pen(foreColor, thickness), points);
break;
case ShapeType.Triangle:
var tPoints = new PointF[3];
tPoints[0] = new PointF(x + width / 2, y);
tPoints[1] = new PointF(x + width, y + height);
tPoints[2] = new PointF(x, y + height);
if (isFill)
g.FillPolygon(new SolidBrush(backgroundColor), tPoints);
//else
g.DrawPolygon(new Pen(foreColor, thickness), tPoints);
break;
}
if (shapeType != ShapeType.Line)
{
g.DrawString(String.Format("({0},{1})", x, y), new Font(new FontFamily("Tahoma"), 10), new SolidBrush(foreColor), x - 20, y - 25);
g.DrawString(String.Format("({0},{1})", x + width, y + height), new Font(new FontFamily("Tahoma"), 10), new SolidBrush(foreColor), x + width - 20, y + height + 5);
}
else
{
g.DrawString(String.Format("({0},{1})", startPoint.X, startPoint.Y), new Font(new FontFamily("Tahoma"), 10), new SolidBrush(foreColor), startPoint.X - 20, startPoint.Y - 25);
g.DrawString(String.Format("({0},{1})", endPoint.X, endPoint.Y), new Font(new FontFamily("Tahoma"), 10), new SolidBrush(foreColor), endPoint.X - 20, endPoint.Y + 5);
}
}
/// <summary>
/// Points the in sahpe.
/// </summary>
/// <param name="point">The point.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns>
/// <c>true</c> if [has point in sahpe] [the specified point]; otherwise, <c>false</c>.
/// </returns>
public virtual bool HasPointInSahpe(PointF point, byte tolerance = 5)
{
return point.X > (StartPoint.X - tolerance) && point.X < (EndPoint.X + tolerance) && point.Y > (StartPoint.Y - tolerance) && point.Y < (EndPoint.Y + tolerance);
}
/// <summary>
/// Moves the specified location.
/// </summary>
/// <param name="location">The location.</param>
/// <returns></returns>
public virtual PointF Move(Point location)
{
StartPoint = new PointF(location.X, location.Y);
EndPoint = new PointF(location.X + Width, location.Y + Height);
return StartPoint;
}
/// <summary>
/// Moves the specified dx.
/// </summary>
/// <param name="dx">The dx.</param>
/// <param name="dy">The dy.</param>
/// <returns></returns>
public virtual PointF Move(int dx, int dy)
{
StartPoint = new PointF(StartPoint.X + dx, StartPoint.Y + dy);
EndPoint = new PointF(EndPoint.X + dx, EndPoint.Y + dy);
return StartPoint;
}
/// <summary>
/// Resizes the specified dx.
/// </summary>
/// <param name="dx">The dx.</param>
/// <param name="dy">The dy.</param>
/// <returns></returns>
public virtual SizeF Resize(int dx, int dy)
{
EndPoint = new PointF(EndPoint.X + dx, EndPoint.Y + dy);
return new SizeF(Width, Height);
}
/// <summary>
/// Resizes the specified start point.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="currentPoint">The current point.</param>
public virtual void Resize(PointF startPoint, PointF currentPoint)
{
var dx = (int)(currentPoint.X - startPoint.X);
var dy = (int)(currentPoint.Y - startPoint.Y);
if (startPoint.X >= X - 5 && startPoint.X <= X + 5)
{
StartPoint = new PointF(currentPoint.X, StartPoint.Y);
if (ShapeType == ShapeType.Circle || ShapeType == ShapeType.Square)
{
Height = Width;
}
}
else if (startPoint.X >= EndPoint.X - 5 && startPoint.X <= EndPoint.X + 5)
{
Width += dx;
if (ShapeType == ShapeType.Circle || ShapeType == ShapeType.Square)
{
Height = Width;
}
}
else if (startPoint.Y >= Y - 5 && startPoint.Y <= Y + 5)
{
Y = currentPoint.Y;
if (ShapeType == ShapeType.Circle || ShapeType == ShapeType.Square)
{
Width = Height;
}
}
else if (startPoint.Y >= EndPoint.Y - 5 && startPoint.Y <= EndPoint.Y + 5)
{
Height += dy;
if (ShapeType == ShapeType.Circle || ShapeType == ShapeType.Square)
{
Width = Height;
}
}
}
// Private Methods (1)
/// <summary>
/// Calulates the size of the location and.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
private void CalulateLocationAndSize(PointF startPoint, PointF endPoint)
{
float x = 0, y = 0;
float width = Math.Abs(endPoint.X - startPoint.X);
float height = Math.Abs(endPoint.Y - startPoint.Y);
if (startPoint.X <= endPoint.X && startPoint.Y <= endPoint.Y)
{
x = startPoint.X;
y = startPoint.Y;
}
else if (startPoint.X >= endPoint.X && startPoint.Y >= endPoint.Y)
{
x = endPoint.X;
y = endPoint.Y;
}
else if (startPoint.X >= endPoint.X && startPoint.Y <= endPoint.Y)
{
x = endPoint.X;
y = startPoint.Y;
}
else if (startPoint.X <= endPoint.X && startPoint.Y >= endPoint.Y)
{
x = startPoint.X;
y = endPoint.Y;
}
StartPoint = new PointF(x, y);
EndPoint = new PointF(X + width, Y + height);
}
#endregion Methods
}
}
حال به تشریح سازنده کلاس میپردازیم:
Shape: پارامترهای این سازنده به ترتیب عبارتند از نقطه شروع، نقطه پایان، عمق شی، رنگ قلم، ضخامت خط، آیا شی توپر باشد؟، و رنگ پر کردن شی، در این سازنده ابتدا توسط متدی به نام CalulateLocationAndSize(startPoint, endPoint); b نقاط ابتدا و انتهای شی مورد نظر تنظیم میشود، در متد مذکور بررسی میشود در صورتی که نقاط شروع و پایان یکی از حالتهای 1 ، 2، 3، 4 از تصویر ابتدا پست باشد همگی تبدیل به حالت 1 خواهد شد.
سپس به تشریح متدهای کلاس Shape میپردازیم:
Draw: این متد دارای یک پارامتر ورودی است که بوم گرافیکی مورد نظر میباشد، در واقع شی مورد نظر خود را بروی این بوم گرافیکی ترسیم میکند. در کلاس پایه کار این متد زیاد پیچیده نیست، در صورتی که شی در حالت انتخاب باشد (IsSelected = true) بروی شی مورد نظر 8 مربع کوچک ترسیم میشود و اگر شی مورد نظر خط باشد دو مربع کوچک در طرفین خط رسم میشود که نشان دهنده انتخاب شدن شی مورد نظر است. این متد به صورت virtual تعریف شده است یعنی کلاس هایی که از Shape ارث میبرند میتوانند این متد را برای خود از نو بازنویسی کرده (override کنند) و تغییر رفتار دهند.
DrawPreview : این متد یک متد عمومی بود و مختص هر شی است، وظیفه این متد ترسیم پیش نمایش شی مورد نظر در زمان جابجایی و ترسیم میباشد، پارامترهای آن عبارتند از : بوم گرافیکی، نقطه شروع، نقطه پایان و رنگ قلم ترسیم پیش نمایش شی، خود این متد در بدنه خود متد static بعدی با همین نام را فراخوانی خواهد کرد.
DrawPreview : کار این متد دقیقا مانند متد قبلی میباشد (در واقع اصل کار را برای پیش نمایش همین متد انجام میدهد)، پارامترهای آن عبارتند از : بوم گرافیکی، نقطه شروع، نقطه پایان و رنگ قلم ترسیم پیش نمایش شی، ضخامت خط، آیا شی توپر باشد؟، رنگ پس زمینه شی ، و نوع شی ترسیمی میباشد. (البته خیلی تلاش کردم این دو متد را با Func و Action پیاده سازی کنم اما نشد اگر دوستان نظری دارن خوشحال میشم پیشنهاد بدن)؛ خوب اما کار این متد به این صورت است ابتدا نقاط شروه و پایان را بررسی کرده و آنها را اصلاح میکند؛ سپس با توجه به نوع شی مورد نظر آنر ترسیم میکند، البته با نمایش مقادیر نقطه شروع و پایان.
HasPointInSahpe : این متد نیز به صورت virtual تعریف شده است دارای خروجی بولین میباشد. پارامترهای این متد عبارتند از یک نقطه و یک عدد که نشان دهنده تلرانش نقطه بر حسب پیکسل میباشد. کار این متد این است که یک نقطه را گرفته و بررسی میکند که آیا نقطه مورد نظر با تلرانس وارد شده آیا در داخل شی واقع شده است یا خیر (مثلا وجود نقطه در مستطیل یا وجود نقطه در دایره فرمولهای متفاوتی دارند که در اینجا پیش فرض برای تمامی اشیا حالت مستطیل در نظر گرفته شده که میتوانید آنها را بازنویسی (override) کنید).
Move: این متد به عنوان پارامتر یک نقطه را گرفته و شی مورد نظر را به آن نقطه منتقل میکند در واقع نقطه شروع و پایان ترسیم شی را تغییر میدهد.
Move: این متد نیز برای جابجایی شی به کار میرود، این متد دارای پارامترهای جابجابی در راستای محور Xها , جابجایی در راستای محور Yها؛ و شی مورد نظر را به آن نقطه منتقل میکند در واقع نقطه شروع و پایان ترسیم شی را با توجه به پارامترهای ورودی تغییر میدهد.
Resize: این متد نیز برای تغییر اندازه شی به کار میرود، این متد دارای پارامترهای تغییر اندازه در راستای محور Xها , تغییر اندازه در راستای محور Yها میباشد و نقطه پایان شی مورد نظر را تغییر میدهد اما نقطه شروع تغییری نمیکند.
Resize: این متد نیز برای تغییر اندازه شی به کار میرود، در زمان تغییر اندازه شی با ماوس ابتدا یک نقطه شروع وجود دارد که ماوس در آن نقطه کلیک شده و شروع به درگ کردن شی جهت تغییر اندازه میکند (پارامتر اول این متد نقطه شروع درگ کردن جهت تغییر اندازه را مشخص میکند startPoint)، سپس در یک نقطه ای درگ کردن تمام میشود در این نقطه باید شی تغییر اندازه پیدا کرده و ترسیم شود ( پارامتر دوم این متد نقطه مذکور میباشد currentLocation). سپس با توجه با این دو نقطه بررسی میشود که تغییر اندازه در کدام جهت صورت گرفته است و اعداد جهت تغییرات نقاط شروع و پایان شی مورد نظر محاسبه میشوند. (مثلا تغییر اندازه در مستطیل از ضلع بالا به طرفین، یا از ضلع سمت راست به طرفین و ....). البته برای مربع و دایره باید کاری کنیم که طول و عرض تغییر اندازه یکسان باشد.
CalulateLocationAndSize: این متد که در سازنده کلاس استفاده شده در واقع دو نقطه شروع و پایان را گرفته و با توجه به تصویر ابتدای پست حالتهای 1 و 2 و3 و 4 را به حالت 1 تبدیل کرده و StartPoint و EndPoint را اصلاح میکند.
تذکر: متدهای Move، Resize و HasPointInShape به صورت virtual تعریف شده تا کلاسهای مشتق شده در صورت نیاز خود کد رفتار مورد نظر خود را override کرده یا از همین رفتار استفاده نمایند.
خوشحال میشم در صورتی که در Refactoring کد نوشته شده با من همکاری کنید.
در پستهای آینده به بررسی و پیاده سازی دیگر کلاسها خواهیم پرداخت.
آدرس پست اصلی (http://www.dotnettips.info/post/1209/)
Saber_Fatholahi
دوشنبه 23 بهمن 1391, 00:06 صبح
در ادامه مطالب قبل:
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 1# (http://www.dotnettips.info/post/1195/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 2# (http://www.dotnettips.info/post/1208/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 3# (http://www.dotnettips.info/post/1209/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 4# (http://www.dotnettips.info/post/1214/)
در این پست به بررسی کلاس Triangle جهت رسم مثلث و کلاس Diamond جهت رسم لوزی میپردازیم.
using System.Drawing;
namespace PWS.ObjectOrientedPaint.Models
{
/// <summary>
/// Triangle
/// </summary>
public class Triangle : Shape
{
#region Constructors (2)
/// <summary>
/// Initializes a new instance of the <see cref="Triangle" /> class.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="zIndex">Index of the z.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="isFill">if set to <c>true</c> [is fill].</param>
/// <param name="backgroundColor">Color of the background.</param>
public Triangle(PointF startPoint, PointF endPoint, int zIndex, Color foreColor, byte thickness, bool isFill, Color backgroundColor)
: base(startPoint, endPoint, zIndex, foreColor, thickness, isFill, backgroundColor)
{
ShapeType = ShapeType.Triangle;
}
/// <summary>
/// Initializes a new instance of the <see cref="Triangle" /> class.
/// </summary>
public Triangle()
{
ShapeType = ShapeType.Triangle;
}
#endregion Constructors
#region Methods (1)
// Public Methods (1)
/// <summary>
/// Draws the specified g.
/// </summary>
/// <param name="g">The g.</param>
public override void Draw(Graphics g)
{
var points = new PointF[3];
points[0] = new PointF(X + Width / 2, Y);
points[1] = new PointF(X + Width, Y + Height);
points[2] = new PointF(X, Y + Height);
if (IsFill)
g.FillPolygon(BackgroundBrush, points);
g.DrawPolygon(new Pen(ForeColor, Thickness), points);
base.Draw(g);
}
#endregion Methods
}
}
همانگونه که مشاهده میکنید کلاس مثلث از کلاس Shape ارث برده و تشکیل شده از یک سازنده و بازنویسی (override) متد Draw میباشد، البته متد HasPointInSahpe در کلاس پایه قاعدتا باید بازنویسی شود، برای تشخیص وجود نقطه در شکل مثلث، (اگر دوستان فرمولش میدونن ممنون میشم در اختیار بذارن). در متد Draw سه نقطه مثلث در نظر گرفته شده که بر طبق آن با استفاده از متدهای رسم منحنی اقدام به رسم مثلث توپر یا تو خالی نمودهایم.
کلاس لوزی نیز دقیقا مانند کلاس مثلث عمل میکند.
using System.Drawing;
namespace PWS.ObjectOrientedPaint.Models
{
/// <summary>
/// Diamond
/// </summary>
public class Diamond : Shape
{
#region Constructors (2)
/// <summary>
/// Initializes a new instance of the <see cref="Diamond" /> class.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="zIndex">Index of the z.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="isFill">if set to <c>true</c> [is fill].</param>
/// <param name="backgroundColor">Color of the background.</param>
public Diamond(PointF startPoint, PointF endPoint, int zIndex, Color foreColor, byte thickness, bool isFill, Color backgroundColor)
: base(startPoint, endPoint, zIndex, foreColor, thickness, isFill, backgroundColor)
{
ShapeType = ShapeType.Diamond;
}
/// <summary>
/// Initializes a new instance of the <see cref="Diamond" /> class.
/// </summary>
public Diamond()
{
ShapeType = ShapeType.Diamond;
}
#endregion Constructors
#region Methods (1)
// Public Methods (1)
/// <summary>
/// Draws the specified g.
/// </summary>
/// <param name="g">The g.</param>
public override void Draw(Graphics g)
{
var points = new PointF[4];
points[0] = new PointF(X + Width / 2, Y);
points[1] = new PointF(X + Width, Y + Height / 2);
points[2] = new PointF(X + Width / 2, Y + Height);
points[3] = new PointF(X, Y + Height / 2);
if (IsFill)
g.FillPolygon(BackgroundBrush, points);
g.DrawPolygon(new Pen(ForeColor, Thickness), points);
base.Draw(g);
}
#endregion Methods
}
}
این کلاس نیز از کلاس Shape ارث برده و دارای یک سازنده بوده و متد Draw را ازنو بازنویسی میکند، این متد نیز با استفاده از چهار نقطه و استفاده از متد رسم منحنی در دات نت اقدام به طراحی لوزی توپر یا تو خالی میکند، متد HasPointInSahpe در کلاس پایه قاعدتا باید بازنویسی شود، برای تشخیص وجود نقطه در شکل لوزی، برای رسم لوزی توپر نیز خصوصیت BackgroundBrush استفاده کرده و شی توپر را رسم میکند.
مباحث رسم مستطیل و مربع، دایره و بیضی در پستهای بعد بررسی خواهند شد.
موفق وموید باشید.
آدرس پست اصلی (http://www.dotnettips.info/post/1214/)
Saber_Fatholahi
پنج شنبه 03 اسفند 1391, 01:17 صبح
در ادامه مطلب پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 4# (http://www.dotnettips.info/post/1214/) به تشریح مابقی کلاسهای برنامه میپردازیم.
در این پست به شرح کلاس Rectangle جهت رسم مستطیل و Square جهت رسم مربع میپردازیم
using System.Drawing;
namespace PWS.ObjectOrientedPaint.Models
{
/// <summary>
/// Rectangle
/// </summary>
public class Rectangle : Shape
{
#region Constructors (2)
/// <summary>
/// Initializes a new instance of the <see cref="Rectangle" /> class.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="zIndex">Index of the z.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="isFill">if set to <c>true</c> [is fill].</param>
/// <param name="backgroundColor">Color of the background.</param>
public Rectangle(PointF startPoint, PointF endPoint, int zIndex, Color foreColor, byte thickness, bool isFill, Color backgroundColor)
: base(startPoint, endPoint, zIndex, foreColor, thickness, isFill, backgroundColor)
{
ShapeType = ShapeType.Rectangle;
}
/// <summary>
/// Initializes a new instance of the <see cref="Rectangle" /> class.
/// </summary>
public Rectangle()
{
ShapeType = ShapeType.Rectangle;
}
#endregion Constructors
#region Methods (1)
// Public Methods (1)
/// <summary>
/// Draws the specified g.
/// </summary>
/// <param name="g">The g.</param>
public override void Draw(Graphics g)
{
if (IsFill)
g.FillRectangle(BackgroundBrush, StartPoint.X, StartPoint.Y, Width, Height);
g.DrawRectangle(Pen, StartPoint.X, StartPoint.Y, Width, Height);
base.Draw(g);
}
#endregion Methods
}
}
کلاس Rectangle از کلاس پایه طراحی شده در ^ (http://www.dotnettips.info/post/1208/) ارث بری دارد. این کلاس ساده بوده و تنها شامل یک سازنده و متد ترسیم شی مستطیل میباشد.
کلاس بعدی کلاس Square میباشد، که از کلاس بالا (Rectangle) ارث بری داشته است، کدهای این کلاس را در زیر مشاهده میکنید.
using System;
using System.Drawing;
namespace PWS.ObjectOrientedPaint.Models
{
/// <summary>
/// Square
/// </summary>
public class Square : Rectangle
{
#region Constructors (2)
/// <summary>
/// Initializes a new instance of the <see cref="Square" /> class.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="zIndex">Index of the z.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="isFill">if set to <c>true</c> [is fill].</param>
/// <param name="backgroundColor">Color of the background.</param>
public Square(PointF startPoint, PointF endPoint, int zIndex, Color foreColor, byte thickness, bool isFill, Color backgroundColor)
{
float x = 0, y = 0;
float width = Math.Abs(endPoint.X - startPoint.X);
float height = Math.Abs(endPoint.Y - startPoint.Y);
if (startPoint.X <= endPoint.X && startPoint.Y <= endPoint.Y)
{
x = startPoint.X;
y = startPoint.Y;
}
else if (startPoint.X >= endPoint.X && startPoint.Y >= endPoint.Y)
{
x = endPoint.X;
y = endPoint.Y;
}
else if (startPoint.X >= endPoint.X && startPoint.Y <= endPoint.Y)
{
x = endPoint.X;
y = startPoint.Y;
}
else if (startPoint.X <= endPoint.X && startPoint.Y >= endPoint.Y)
{
x = startPoint.X;
y = endPoint.Y;
}
StartPoint = new PointF(x, y);
var side = Math.Max(width, height);
EndPoint = new PointF(x+side, y+side);
ShapeType = ShapeType.Square;
Zindex = zIndex;
ForeColor = foreColor;
Thickness = thickness;
BackgroundColor = backgroundColor;
IsFill = isFill;
}
/// <summary>
/// Initializes a new instance of the <see cref="Square" /> class.
/// </summary>
public Square()
{
ShapeType = ShapeType.Square;
}
#endregion Constructors
}
}
این کلاس شامل دو سازنده میباشد که سازنده دوم فقط نوع شی را تعیین میکند و بقیه کارهای آن مانند مستطیل است، در واقع میتوان از یک دیدگاه گفت که مربع یک مستطیل است که اندازه طول و عرض آن یکسان است. در سازنده اول (نحوه ترسیم شکل (http://www.dotnettips.info/post/1209/)) ابتدا نقاط ابتدا و انتهای رسم شکل تعیین شده و سپس با توجه به پارامترهای محاسبه شده نوع شی جهت ترسیم و دیگر خصوصیات کلاس مقدار دهی میشود، با این تفاوت که در نقطه EndPoint طول و عرض مربع برابر با بزرگترین مقدار طول و عرض وارد شده در سازنده کلاس تعیین شده و مربع شکل میگیرد. مابقی متدهای ترسیم و ... طبق کلاس پایه مستطیل و Shape تعیین میشود.
آدرس پست اصلی (http://www.dotnettips.info/post/1232/)
مطالب قبل:
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 1# (http://www.dotnettips.info/post/1195/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 2# (http://www.dotnettips.info/post/1208/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 3# (http://www.dotnettips.info/post/1209/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 4# (http://www.dotnettips.info/post/1214/)
Saber_Fatholahi
یک شنبه 06 اسفند 1391, 15:00 عصر
در ادامه پست پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 5# (http://www.dotnettips.info/post/1232/) ، در این پست به تشریح کلاس دایره و بیضی میپردازیم.
ابتدا به تشریح کلاس ترسیم بیضی (Ellipse) میپردازیم.
using System.Drawing;
namespace PWS.ObjectOrientedPaint.Models
{
/// <summary>
/// Ellipse Draw
/// </summary>
public class Ellipse : Shape
{
#region Constructors (2)
/// <summary>
/// Initializes a new instance of the <see cref="Ellipse" /> class.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="zIndex">Index of the z.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="isFill">if set to <c>true</c> [is fill].</param>
/// <param name="backgroundColor">Color of the background.</param>
public Ellipse(PointF startPoint, PointF endPoint, int zIndex, Color foreColor, byte thickness, bool isFill, Color backgroundColor)
: base(startPoint, endPoint, zIndex, foreColor, thickness, isFill, backgroundColor)
{
ShapeType = ShapeType.Ellipse;
}
/// <summary>
/// Initializes a new instance of the <see cref="Ellipse" /> class.
/// </summary>
public Ellipse()
{
ShapeType = ShapeType.Ellipse;
}
#endregion Constructors
#region Methods (1)
// Public Methods (1)
/// <summary>
/// Draws the specified g.
/// </summary>
/// <param name="g">The g.</param>
public override void Draw(Graphics g)
{
if (IsFill)
g.FillEllipse(BackgroundBrush, StartPoint.X, StartPoint.Y, Width, Height);
g.DrawEllipse(Pen, StartPoint.X, StartPoint.Y, Width, Height);
base.Draw(g);
}
#endregion Methods
}
}
این کلاس از شی Shape ارث برده و دارای دو سازنده ساده میباشد که نوع شی ترسیمی را مشخص میکنند، در متد Draw نیز با توجه به توپر یا توخالی بودن شی ترسیم آن انجام میشود، در این کلاس باید متد HasPointInShape بازنویسی (override) شود، در این متد باید تعیین شود که یک نقطه در داخل بیضی قرار گرفته است یا خیر که متاسفانه فرمول بیضی خاطرم نبود. البته به صورت پیش فرض نقطه با توجه به چهارگوشی که بیضی را احاطه میکند سنجیده میشود.
کلاس دایره (Circle) از کلاس بالا (Ellipse) ارث بری دارد که کد آن را در زیر مشاهده مینمایید.
using System;
using System.Drawing;
namespace PWS.ObjectOrientedPaint.Models
{
/// <summary>
/// Circle
/// </summary>
public class Circle : Ellipse
{
#region Constructors (2)
/// <summary>
/// Initializes a new instance of the <see cref="Circle" /> class.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="zIndex">Index of the z.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="isFill">if set to <c>true</c> [is fill].</param>
/// <param name="backgroundColor">Color of the background.</param>
public Circle(PointF startPoint, PointF endPoint, int zIndex, Color foreColor, byte thickness, bool isFill, Color backgroundColor)
{
float x = 0, y = 0;
float width = Math.Abs(endPoint.X - startPoint.X);
float height = Math.Abs(endPoint.Y - startPoint.Y);
if (startPoint.X <= endPoint.X && startPoint.Y <= endPoint.Y)
{
x = startPoint.X;
y = startPoint.Y;
}
else if (startPoint.X >= endPoint.X && startPoint.Y >= endPoint.Y)
{
x = endPoint.X;
y = endPoint.Y;
}
else if (startPoint.X >= endPoint.X && startPoint.Y <= endPoint.Y)
{
x = endPoint.X;
y = startPoint.Y;
}
else if (startPoint.X <= endPoint.X && startPoint.Y >= endPoint.Y)
{
x = startPoint.X;
y = endPoint.Y;
}
StartPoint = new PointF(x, y);
var side = Math.Max(width, height);
EndPoint = new PointF(x + side, y + side);
ShapeType = ShapeType.Circle;
Zindex = zIndex;
ForeColor = foreColor;
Thickness = thickness;
BackgroundColor = backgroundColor;
IsFill = isFill;
}
/// <summary>
/// Initializes a new instance of the <see cref="Circle" /> class.
/// </summary>
public Circle()
{
ShapeType = ShapeType.Circle;
}
#endregion Constructors
#region Methods (1)
// Public Methods (1)
/// <summary>
/// Points the in sahpe.
/// </summary>
/// <param name="point">The point.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns>
/// <c>true</c> if [has point in sahpe] [the specified point]; otherwise, <c>false</c>.
/// </returns>
public override bool HasPointInSahpe(PointF point, byte tolerance = 5)
{
float width = Math.Abs(EndPoint.X+tolerance - StartPoint.X-tolerance);
float height = Math.Abs(EndPoint.Y+tolerance - StartPoint.Y-tolerance);
float diagonal = Math.Max(height, width);
float raduis = diagonal / 2;
float dx = Math.Abs(point.X - (X + Width / 2));
float dy = Math.Abs(point.Y - (Y + height / 2));
return (dx + dy <= raduis);
}
#endregion Methods
}
}
این کلاس شامل دو سازنده میباشد، که در سازنده اول با توجه به نقاط ایتدا و انتهای ترسیم شکل مقدار طول و عرض مستطیل احاطه کننده دایره محاسبه شده و باتوجه به آنها بزرگترین ضلع به عنوان قطر دایره در نظر گرفته میشود و EndPoint شکل مورد نظر تعیین میشود.
در متد HasPointInShape با استفاده از فرمول دایره تعیین میشود که آیا نقطه پارامتر ورودی متد در داخل دایره واقع شده است یا خیر (جهت انتخاب شکل برای جابجایی یا تغییر اندازه).
در پستهای بعد به پیاده سازی اینترفیس نرم افزار خواهیم پرداخت.
موفق و موید باشید
در ادامه مطالب قبل:
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 1# (http://www.dotnettips.info/post/1195/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 2# (http://www.dotnettips.info/post/1208/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 3# (http://www.dotnettips.info/post/1209/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 4# (http://www.dotnettips.info/post/1214/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 5# (http://www.dotnettips.info/post/1232/)
vBulletin® v4.2.5, Copyright ©2000-1403, Jelsoft Enterprises Ltd.