بیایید تفاوت بین
Graphics g = this.CreateGraphics();
و
Graphics g = e.Graphics;
رو بهصورت کامل و با جزئیات بررسی کنیم و ببینیم هر کدوم تو چه شرایطی مناسبترن. این دو روش برای دسترسی به شیء Graphics توی Windows Forms استفاده میشن که ابزاری برای ترسیم اشکال، خطوط، متن و تصاویر روی فرم یا کنترلهاست. اما کاربرد و نحوه کارشون با هم فرق داره.
Graphics g = this.CreateGraphics();
توضیح:
این خط یه شیء Graphics جدید رو مستقیماً از فرم یا هر کنترل دیگهای که this بهش اشاره میکنه ایجاد میکنه.
CreateGraphics()
یه متد از کلاس Control هست که هر بار که فراخوانی میشه، یه نمونه تازه از Graphics میسازه و به شما اجازه میده روی سطح فرم چیزی ترسیم کنید.
این شیء به رویدادهای ترسیم سیستم مثل Paint وابسته نیست ( ما وابسته نیستیم)و شما خودتون کنترلش میکنید.
نحوه کار:
وقتی از
CreateGraphics()
استفاده میکنید، ترسیمهایی که انجام میدید موقتی هستن. یعنی اگه فرم نیاز به بازنقاشی پیدا کنه مثلاً وقتی پنجره رو جابهجا میکنید، کوچکش میکنید، یا یه پنجره دیگه روش رو میپوشونه و بعد کنار میره ، چیزایی که با این روش کشیدید پاک میشن، چون این ترسیمها توی حافظه دائمی رندر فرم ذخیره نمیشن. برای نگه داشتن ترسیمها، باید هر بار که فرم بازنقاشی میشه، خودتون دوباره کد ترسیم رو اجرا کنید.
مثال:
private void button1_Click(object sender, EventArgs e)
{
Graphics g = this.CreateGraphics();
g.DrawRectangle(new Pen(Color.Red), 10, 10, 100, 50);
}
اینجا با کلیک روی دکمه، یه مستطیل قرمز کشیده میشه. ولی اگه فرم رو minimize کنید و دوباره برگردونید، مستطیل غیبش میزنه!
پس این روش مناسب چه شرایطی است ؟
ترسیمهای موقتی و فوری: مثلاً وقتی میخواهید یه پیشنمایش سریع (مثل یه خط یا شکل) نشون بدید که نیازی به دائمی بودنش نیست.
ترسیم در پاسخ به رویدادهای کاربر: مثل وقتی که کاربر با ماوس چیزی میکشه و شما فقط میخواهید همون لحظه نشونش بدید (مثل یه برنامه نقاشی ساده).
کنترل دستی: وقتی نمیخواهید به سیستم بازنقاشی فرم وابسته باشید و خودتون میخواهید زمان و مکان ترسیم رو مدیریت کنید.
معایب:
عدم پایداری: ترسیمها با هر بازنقاشی فرم پاک میشن، مگه اینکه خودتون توی رویداد Paint دوباره بکشیدشون.
مصرف منابع: هر بار که CreateGraphics() رو صدا میزنید، یه شیء جدید ساخته میشه که اگه زیاد استفاده بشه، میتونه عملکرد رو پایین بیاره.
نیاز به مدیریت دستی: باید خودتون حواستون باشه که شیء Graphics رو با Dispose() آزاد کنید( اگه خارج از Paint استفاده میکنید)، وگرنه ممکنه مشکل حافظه پیش بیاد.
Graphics g = e.Graphics;
توضیح:
این خط از شیء Graphicsای استفاده میکنه که توسط سیستم توی رویداد Paint یا رویدادهای مشابه مثل OnPaint به شما داده شده.
e یه آرگومان از نوع PaintEventArgs هست که شامل اطلاعات ترسیم (مثل ناحیهای که باید بازنقاشی بشه) و یه نمونه آماده از Graphics است.
این شیء به سیستم رندرینگ فرم وصله و بخشی از فرآیند بازنقاشی ویندوزه.
نحوه کار:
وقتی از e.Graphics استفاده میکنید، ترسیمهاتون بهصورت خودکار با چرخه بازنقاشی فرم هماهنگ میشن. یعنی هر وقت فرم نیاز به ترسیم دوباره داشته باشه (مثلاً بعد از تغییر اندازه یا باز شدن)، کد توی Paint دوباره اجرا میشه و اشکال شما حفظ میشن.
سیستم خودش مدیریت منابع رو انجام میده و نیازی نیست شما Dispose() کنید، چون e.Graphics توسط رویداد کنترل میشه.
مثال:
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawRectangle(new Pen(Color.Red), 10, 10, 100, 50);
}
اینجا مستطیل قرمز هر بار که فرم بازنقاشی میشه کشیده میشه و پاک نمیشه، چون به رویداد Paint وصل شده.
این روش مناسب چه شرایطی است ؟
ترسیمهای دائمی: وقتی میخواهید چیزی رو روی فرم بکشید که همیشه دیده بشه، مثل کادرها، نمودارها یا آیکنها.
طراحی رابط کاربری: برای عناصر گرافیکی که بخشی از ظاهر فرم هستن و باید با تغییرات فرم مثل resize هماهنگ بمونن.
بهینهسازی: چون از سیستم بازنقاشی ویندوز استفاده میکنه، بهینهتره و نیازی به مدیریت دستی منابع نداره.
معایب:
وابستگی به رویداد: فقط توی رویداد Paint یا OnPaint میتونید ازش استفاده کنید و نمیتونید خارج از این رویداد بهش دسترسی داشته باشید.
عدم انعطاف برای ترسیم لحظهای: برای ترسیمهای سریع و موقتی (مثل واکنش به کلیک ماوس) باید یه راه دیگه پیدا کنید یا با Invalidate() رویداد Paint رو دستی فراخوانی کنید.
تفاوتهای کلیدی
ویژگی this.CreateGraphics() e.Graphics
منبع مستقیماً از فرم یا کنترل ساخته میشه از رویداد Paint تأمین میشه
پایداری ترسیم موقتی (با بازنقاشی پاک میشه) دائمی (با هر بازنقاشی تکرار میشه)
محل استفاده هر جایی (مثل رویدادهای کلیک) فقط توی رویداد Paint
مدیریت منابع نیاز به Dispose() داره اگه دستی باشه خودکار توسط سیستم مدیریت میشه
بهینهسازی کمتر بهینه (ایجاد شیء جدید هر بار) بهینهتر (استفاده از سیستم رندر)
ارتباط بین فرم و کلاس با استفاده از Property
فرض کنید برنامهای دارید که در آن، وضعیت یک چکباکس (CheckBox) تعیین میکند که کدام بخش از کد در کلاس شما اجرا شود. به طور مستقیم نمیتوانید از داخل کلاس به کنترلهای موجود در فرم دسترسی داشته باشید.
در این آموزش، یاد میگیریم چگونه وضعیت یک چکباکس را از فرم به یک کلاس منتقل کنیم و بر اساس آن، منطق برنامه را در کلاس تغییر دهیم.
برای این کار، در کلاس خود یک Property ایجاد میکنیم. این Property به عنوان یک رابط بین فرم و کلاس عمل میکند. فرم میتواند مقدار این Property را true یا false تعیین کند و کلاس میتواند بر اساس این مقدار، تصمیمگیری کند.
در کلاس، یک فیلد از نوع `bool` برای ذخیره وضعیت چکباکس و یک متد برای برگرداندن وضعیت به صورت رشتهای خواهیم داشت.
در ادامه، ابتدا کد کلاس و سپس نحوه استفاده از آن را مشاهده میکنید.
کد کلاس:
public bool IsChecked // Property برای دریافت و تنظیم وضعیت چکباکس
{
get { return _isChecked; }
set { _isChecked = value; }
}
public string GetStatusText() // متد برای برگرداندن وضعیت به صورت متن
{
if (_isChecked)
{
return "تیک خورده";
}
else
{
return "تیک نخورده";
}
}
}
نحوه استفاده از کلاس در رویداد کلیک یک دکمه (Button) با فرض وجود یک چکباکس (CheckBox) روی فرم:
// تنظیم مقدار Property با استفاده از وضعیت چکباکس
testClass.IsChecked = checkBox1.Checked;
// استفاده از متد برای نمایش وضعیت چکباکس
label1.Text = testClass.GetStatusText();
}
توضیحات :
ابتدا نمونه ای از کلاس MyClass ایجاد میکنیم. سپس، با استفاده از پراپرتی IsChecked، وضعیت چکباکس را به کلاس منتقل میکنیم. از این به بعد، کلاس میتواند با استفاده از فیلد _isChecked به وضعیت چکباکس دسترسی داشته باشد.
برای بررسی صحت عملکرد کد، میتوانیم از متد GetStatusText استفاده کرده و وضعیت چکباکس را در یک Label نمایش دهیم.
برنامه نویسی شی گرا (OOP) Object-Oriented Programming
مفهوم کلاس (Class)
کلاس یک مفهوم پایهای بسیار مهم در برنامهنویسی شی گراست. کلاس یک بسته (blueprint) است که شامل تعدادی از ویژگیها (fields) و صفاتی است که یک شی میتواند داشته باشد و همچنین شامل تواناییها (methods)یی است که یک شی قادر به انجام آنهاست.
کلاس همچون یک قالب، نقشه و یا الگو عمل میکند و ویژگیهای عمومی اشیاء را تعیین میکند. کلاس به صورت مستقیم قابل استفاده نیست و باید از آن یک شیء (object) یا همان نمونه (instance) ساخت تا با کمک شیء بتوان از ویژگیها و قابلیتهای درون کلاس استفاده کرد.
در تعریف بالا اسم شی را بردیم؛ شیء چیست؟ شیء (Object) یک نمونه (instance) از کلاس است که هنگام استفاده از یک کلاس باید ابتدا یک شیء از آن کلاس را نمونهسازی (instantiate) کنیم.
( البته بعضی از کلاسها را نمیتوان نمونهسازی کرد که بعدا توضیح خواهیم داد )
حالا برویم سراغ ساخت یک کلاس. فرض کنید ما کلاسی میخواهیم داشته باشیم که تمام اعضای این کلاس باید یک نام و یک سن داشته باشند و بتوانند خودشان را معرفی کنند. همانطور که میبینید کلاس زیر این دو ویژگی و یک توانایی را دارد:
class Student
{
// (Fields) ویژگی ها و دادههایی که شیء نگهداری میکند
public string Name; // نام دانشجو
public int Age; // سن دانشجو
// متد سازنده (Constructor) - متدی خاص که هنگام ایجاد شیء اجرا میشود و ویژگیها را مقداردهی اولیه میکند
public Student(string name, int age)
{
Name = name;
Age = age;
}
// متد (Method) - رفتارهایی که شیء میتواند انجام دهد
public void Introduce()
{
Console.WriteLine($"سلام، من {Name} هستم و {Age} سال دارم.");
}
}
خب در کلاس Student میبینید که دو ویژگی به نامهای Name و Age وجود دارد. Name از نوع string است و برای ذخیره نام دانشجو استفاده میشود. Age از نوع int است و برای ذخیره سن دانشجو استفاده میشود. همچنین یک متد سازنده (Constructor) وجود دارد که این ویژگیها را مقداردهی اولیه میکند (این متد هنگام ایجاد شیء اجرا میشود). این کلاس همچنین دارای یک متد به نام Introduce میباشد که قادر است یک متن را در کنسول چاپ کند.
در بالا گفتیم که هنگام استفاده از یک کلاس، لازم است تا یک نمونه از آن را بسازیم (نمونهسازی کنیم). در دو خط زیر، ما دو نمونه از کلاس Student را با نامهای student1 و student2 ساخته و مقداردهی اولیه کردهایم:
// ساخت شیء از کلاس Student (نمونهسازی)
Student student1 = new Student("رضا", 20);
Student student2 = new Student("الهام", 22);
در واقع با ایجاد نمونه از کلاس، یک فضای حافظه برای شیء اختصاص داده میشود و ویژگیهای آن با مقادیر اولیه مقداردهی میشوند. با ایجاد نمونه از کلاس به تنهایی کار خاصی انجام نمیشود و این نمونه درون حافظه بصورت بلااستفاده میماند. ما باید کاری کنیم تا هدف اصلی از موجودیت کلاس تامین شود و آن هم اجرای قابلیت های درون کلاس است و آن هم با کمک گرفتن از نام نمونه میسر می باشد
در دو خط زیر، با کمک نام نمونههای ساخته شده از کلاس بالا، به تنها تابع موجود در آن دسترسی پیدا کرده و آن را به اجرا درمیآوریم:
// فراخوانی متد برای هر شیء
student1.Introduce(); // خروجی: سلام، من رضا هستم و 20 سال دارم.
student2.Introduce(); // خروجی: سلام، من الهام هستم و 22 سال دارم.
در این درس آموختید چگونه یک کلاس را تعریف کنید، ویژگیها و رفتارهای مورد نیاز را در آن قرار دهید، و با نمونهسازی از آن ، کلاس را به خدمت بگیرید. تا درس بعدی، خدا نگهدار
معرفی کتابخانه AdibanDefDateAndTime: راهحلی ساده برای محاسبه اختلاف بین دو تاریخ!
آیا تا حالا توی پروژههاتون نیاز داشتید اختلاف بین یه تاریخ خاص و تاریخ فعلی سیستم رو محاسبه کنید؟ یا دنبال راهی هستید که این کار رو بدون درگیر شدن با پیچیدگیهای تاریخ و زمان انجام بدید؟ ما براتون یه راهحل ساده و کاربردی داریم: کتابخانه AdibanDefDateAndTime.
این کتابخانه یه کلاس قدرتمند به اسم DateTimeComparer داره که بهتون کمک میکنه بهراحتی اختلاف بین یه تاریخ مشخص (بهصورت رشته) و تاریخ فعلی سیستم رو محاسبه کنید. خروجی هم بهصورت یه رشته خوانا و قابلفهم برگردونده میشه.
استفاده ازش خیلی راحته! فقط کافیه این مراحل رو دنبال کنید:
مرحله 1: اضافه کردن کتابخانه به پروژه
اول فایل DLL کتابخانه AdibanDefDateAndTime رو دانلود کنید و به پروژهتون اضافه کنید:
مرحله 2: اضافه کردن فضای نام (Namespace)
توی کدتون، این خط رو بالای فایل بنویسید:
مرحله 3: استفاده از تابع CompareDateTime
حالا میتونید از کلاس DateTimeComparer و تابع CompareDateTime اینجوری استفاده کنید:
{ label1.Text = DateTimeComparer.CompareDateTime("2025-02-07/16:00:00");}
یا اگه بخواید اختلاف رو هر ثانیه بهروز کنید (مثلاً وقتی کمتر از 24 ساعت مونده)، میتونید از تایمر استفاده کنید:
{ label1.Text = DateTimeComparer.CompareDateTime("2025-02-07/02:21:00");}
ما این کتابخانه رو بهصورت رایگان در اختیارتون گذاشتیم تا توی پروژههاتون ازش استفاده کنید. برای دانلود فایل DLL، روی تصویر زیر کلیک کنید: