الدرس الثامن
يعتبر استخدام الأساليب الرسومية الأخرى، أسهل في بعض الأحيان من استخدام عناصر التحكم الرسومية.
يرسم برنامج النقاط نقاطاً في مواقع عشوائية من النموذج، موضحاً كيف تستخدم الطريقة Pset لرسم النقاط.
سنبدأ كعادتنا عند تصميم البرنامج بتمثيل نموذج البرنامج:
q أنشئ الدليل C:\VB5Prg\Ch08، لأننا سنحفظ عملنا في هذا الدليل.
qأنشئ مشروعاً تنفيذياً قياسياً جديداً Standard EXE، واحفظ نموذج المشروع بالاسم Points.frm في الدليل C:\VB5Prg\Ch08، واحفظ المشروع بالاسم Points.vbp في ذات الدليل.
q أنشئ النموذج frmPoints طبقاً للجدول 8-1.
يُفترض أن يبدو النموذج المكتمل كذاك المبين في الشكل 8-1.
|
|
الشكل 8-1 النموذج frmPoints (طور التصميم). |
الجدول 8-1. جدول خواص النموذج frmPoints.
|
الكائن |
الخاصية |
القيمة |
|
Form |
Name |
frmPoints |
|
|
Caption |
برنامج النقاط |
|
|
RightToLeft |
True |
|
Timer |
Name |
tmrTimer |
|
|
Interval |
60 |
|
|
Enabled |
True |
|
Menu |
(انظر الجدول 8-2) |
(انظر الجدول 8-2) |
جدول 8-2. جدول قوائم النموذج frmPoints.
|
العنوان |
الخاصية Name |
|
&ملف |
mnuFile |
|
…&خروج |
mnuExit |
|
&رسوم |
mnuGraphics |
|
…ار&سم النقاط |
mnuDrawPoints |
|
…ا&مسح النقاط |
mnuClear |
سنكتب الآن نص برنامج النقاط:
q أدخل النص التالي ضمن قسم التصاريح العامة للنموذج frmPoints:
'يجب التصريح عن كل المتحولات
Option Explicit
'متحول لمعرفة هل سوف ترسم النقاط أم سوف تمسح
Dim gDrawPoints
q أدخل النص التالي ضمن الإجراء Form_Load() للنموذج frmPoints:
Private Sub Form_Load()
'تعطيل الرسم
gDrawPoints = 0
End Sub
q أدخل النص التالي ضمن الإجراء mnuClear_Click():
Private Sub mnuClear_Click()
'تعطيل الرسم
gDrawPoints = 0
'تنظيف سطح النموذج
frmPoints.Cls
End Sub
q أدخل النص التالي ضمن الإجراء mnuDrawPoints_Click() للنموذج frmPoints:
Private Sub mnuDrawPoints_Click()
'تفعيل الرسم
gDrawPoints = 1
End Sub
q أدخل النص التالي ضمن الإجراء mnuExit_Click للنموذج frmPoints:
Private sub mnuExit_Click()
End
End sub
q أدخل النص التالي ضمن الإجراء tmrTimer1_Timer() للنموذج frmPoints:
Private Sub tmrTimer_Timer()
Dim R, G, B
Dim X, Y
Dim Counter
'إذا كان الرسم مفعلا نفّذ ما يلي
If gDrawPoints = 1 Then
'ارسم 100 نقطة عشوائية
For Counter = 1 To 100 Step 1
'الحصول على لون عشوائي
R = Rnd * 255
G = Rnd * 255
B = Rnd * 255
'الحصول على موقع احداثيات عشوائي
X = Rnd * frmPoints.ScaleWidth
Y = Rnd * frmPoints.ScaleHeight
'ارسم النقطة
frmPoints.PSet (X, Y), RGB(R, G, B)
Next
End If
End Sub
q احفظ المشروع باختيار Save Project من القائمة File لفيجول بيسك.
دعنا نشاهد برنامج النقاط قيد التنفيذ:
qنفّذ برنامج النقاط.
qاختر ارسم النقاط من القائمة رسوم.
يستجيب البرنامج بإظهار نقاط ذات ألوان عشوائية في مواقع عشوائية من النموذج (انظر الشكل 8-2).
|
|
الشكل 8-2 رسم نقاط عشوائية على سطح برنامج النقاط. |
qاختر امسح النقاط من القائمة رسوم.
يستجيب البرنامج بمسح سطح برنامج النقاط.
qاختر خروج من القائمة ملف لإنهاء البرنامج.
يستعمل برنامج النقاط، الطريقة الرسومية Pset لرسم نقطة ما في النموذج، كما يستخدم الطريقة Cls لمحو النموذج.
يُصرَح عن المتحول gDrawPoints في قسم التصاريح العامة، ويخدم هذا المتحول كراية Flag. فإذا كان مساوياً إلى الواحد (أي الراية مرفوعة)، فهذا يعني تمكين عملية الرسم، وإذا ساوى الصفر، فهذا يعني عدم تمكين الرسم (الراية غير مرفوعة).
يُنفّذ هذا الإجراء آلياً عند بدء تشغيل البرنامج:
Private Sub Form_Load()
'تعطيل الرسم
gDrawPoints = 0
End Sub
يسند هذا الإجراء القيمة الابتدائية صفر إلى المتحول gDrawPoints لمنع أو لعدم تمكين رسم النقاط.
ينفذ هذا الإجراء عند اختيار امسح النقاط من القائمة رسوم:
Private Sub mnuClear_Click()
'تعطيل الرسم
gDrawPoints = 0
'تنظيف سطح النموذج
frmPoints.Cls
End Sub
يمنع هذا الإجراء عملية الرسم بإسناد القيمة صفر، إلى المتحول gDrawPoints ثم يستخدم الطريقة Cls لتنظيف سطح البرنامج من الرسوم التي عليه.
ملاحظة
استخدم الطريقة Cls (Clean Screen) لتنظيف محتويات سطح كائن ما، تمسح هذه الطريقة الرسوم المتولدة أثناء مرحلة التنفيذ بواسطة طرق الرسم المختلفة.
لاحظ مثلاً أن استخدام العبارة frmMyForm.Cls يؤدي إلى تنظيف سطح النموذج frmMyForm من أي رسوم متولدة عليه.
ينفذ الإجراء mnuDrawPoints_Click() عند اختيار ارسم النقاط من القائمة رسوم:
Private Sub mnuDrawPoints_Click()
'تفعيل الرسم
gDrawPoints = 1
End Sub
يسند هذا الإجراء القيمة واحد إلى الراية (المتحول) gDrawPoints لتمكين الرسم.
ينفذ الإجراء tmrTimer_Timer() تلقائياً كل 60 ميلي ثانية، وذلك بسبب إسناد القيمة 60 إلى الخاصية Interval:
Private Sub tmrTimer_Timer()
Dim R, G, B
Dim X, Y
Dim Counter
'إذا كان الرسم مفعلا نفّذ ما يلي
If gDrawPoints = 1 Then
'ارسم 100 نقطة عشوائية
For Counter = 1 To 100 Step 1
'الحصول على لون عشوائي
R = Rnd * 255
G = Rnd * 255
B = Rnd * 255
'الحصول على موقع احداثيات عشوائي
X = Rnd * frmPoints.ScaleWidth
Y = Rnd * frmPoints.ScaleHeight
'ارسم النقطة
frmPoints.PSet (X, Y), RGB(R, G, B)
Next
End If
End Sub
تفحص العبارة if قيمة الراية gDrawPoints، فإذا كانت مساوية إلى "الواحد"، فهذا يعني أنك اخترت ارسم النقاط من القائمة رسوم، ولذلك تنفذ كتلة العبارة If.
ترسم الحلقة For مائة نقطة، وكل نقطة ترسم بلون عشوائي في موقع عشوائي. تستخدم الطريقة الرسومية PSet لرسم كل نقطة من هذه النقاط:
frmPoints.PSet (X, Y), RGB(R, G, B)
حسب ما أوضحنا، ترسم الطريقة PSet نقطة عند الإحداثيين X و Y المحددين ضمنها
(بواسطة وسائطها).
تمتلك الطريقة PSet وسيطاً إضافياً يدعى Step، وعند استخدام الوسيط Step، تُرسم النقطة نسبة إلى الإحداثيين CurrentX (الإحداثي X الحالي) وCurrentY (الإحداثي Y الحالي).
فمثلاً، لنفترض أن الإحداثي X الحالي CurrentX يساوي 100، والإحداثي Y الحالي CurrentY يساوي 50.
وهكذا يؤدي استخدام العبارة التالية:
frmPoints.PSet Step (10,20)، RGB(R,G,B)
إلى رسم نقطة عند الموقع (X=110 و Y=70)، تحُدَّث قيمة المتحولين CurrentX وCurrentY مباشرة (أي تلقائياً) بعد تنفيذ هذه العبارة، وتصبح قيمة CurrentX = 110 و CurrentY = 70.
تذكر أننا اصطلحنا منذ الفصل الرابع بأن فيجول بيسك، يحدّث قيمة الإحداثيين CurrentX و CurrentY تلقائياً، بإسناد إحداثيي نقطة النهاية لآخر رسم إليهما).
qاستبدل نص الإجراء tmrTimer_Timer() بالنص التالي:
Private Sub tmrTimer1_Timer()
Dim R, G, B
Dim X, Y
Dim Counter
If gDrawPoints = 1 Then
For Counter = 1 To 100 Step 1
R = Rnd * 255
G = Rnd * 255
B = Rnd * 255
frmPoints.PSet Step(1, 1), RGB(R, G, B)
If CurrentX >= frmPoints.ScaleWidth Then
CurrentX = Rnd * frmPoints.ScaleWidth
If CurrentY >= frmPoints.ScaleHieght Then
CurrentY = Rnd * frmPoints.ScaleHieght
End If
Next
End If
End Sub
qاحفظ المشروع بالطريقة المعتادة.
qنفّذ البرنامج، واختر ارسم النقاط من القائمة رسوم، واترك البرنامج يعمل لفترة.
يرسم البرنامج الآن خطوطاً، حسب ما يبينه الشكل 8-3.
|
|
الشكل 8-3 استخدام الإمكانية Step لطريقة الرسم PSet. |
يستخدم نص الإجراء tmrTimer1_Timer() الطريقة PSet مع الإمكانية Step:
frmPoints.PSet Step (1,1)، RGB(R,G,B)
تبعد كل نقطة مرسومة عن سابقتها بمقدار وحدة إلى اليمين ووحدة إلى الأسفل. وهذا يشرح سبب رسم النقاط وكأنها خطوط مستقيمة حسب ما يوضحه الشكل 8-3.
تتحقق عبارتي If في هذا الإجراء، من أن النقاط المرسومة لا تتجاوز حدود النموذج.
ملاحظة
استخدم الطريقة PSet (Point Set) لرسم نقطة في كائن ما، وذلك كالتالي:
ObjectName.Pset (X,Y),Color
تضع العبارة السابقة نقطة على الكائن عند الموقع (X,Y) وبلون معين.
لوضع نقطة معينة على الكائن نسبة إلى آخر نقطة تم رسمها، استخدم العبارة التالية:
ObjectName.Pset Step (X,Y),Color
وهي مكافئة للعبارة التالية:
ObjectName.Pset (oldX + X,oldY + Y),Color
حيث oldX و oldY، إحداثيات آخر نقطة تم رسمها على الكائن.
تعود هذه الطريقة بقيمة لون نقطة ضوئية Pixel محددة. فمثلاً، لمعرفة لون النقطة الضوئية المحددة بالموقع 40 و 30، استخدم العبارة التالية:
PixelColor = Point (30,40)
ورغم أن برنامج النقاط لم يستخدم الطريقة Point، إلا أنك قد تجد استخداماً لها في مشاريعك المستقبلية.
تسمح الطريقة Line للمستخدم برسم خطوط، وتمتلك الصيغة التالية:
Line(X1,Y1)-(X2,Y2), Color
علماً أن (X1,Y1)يمثل إحداثي نقطة بداية الخط، ويمثل (X2,Y2)إحداثي نقطة نهاية الخط، كما أن Color يمثل لون الخط. ويؤدي تجاهل كتابة النقطة الأولى (X1,Y1) إلى رسم الخط بدءاً من الإحداثيين CurrentX وCurrentY. وذلك كالتالي:
Line -(X2,Y2), Color
سنضيف عنصر قائمة جديد يدعى رسم خطوط إلى نظام قوائم برنامج النقاط، بغية توضيح عمل طريقة Line، يعطي الجدول 8-3 جدول القوائم الجديد لبرنامج النقاط.
الجدول 8-3. جدول القوائم الجديد للنموذج frmPoints.
|
العنوان |
الاسم |
|
&ملف |
mnuFile |
|
…&خروج |
mnuExit |
|
&رسوم |
mnuGraphics |
|
…ار&سم النقاط |
mnuDrawPoints |
|
…ا&مسح النقاط |
mnuClear |
|
…رسم &خطوط |
mnuLines |
qأضف النص التالي إلى الإجراء mnuLines_Click() للنموذج frmPoints:
Private sub mnuLines_Click()
Line -(Rnd * frmPoints.ScaleWidth, _
Rnd * frmPoints.ScaleHeight),RGB(0,0,0)
End sub
يرسم هذا الإجراء خطاً واحداً من آخر نقطة رسم وصل إليها، إلى نقطة عشوائية.
q احفظ المشروع بالطريقة المعتادة.
q نفّذ البرنامج النقاط.
q اختر رسم خطوط من القائمة رسوم.
يُرسم خط في النموذج، ويتشابه مع ذاك المبين في الشكل 8-4.
|
|
الشكل 8-4 رسم خط ما بواسطة الطريقة Line. |
بسبب تجاهل الإحداثيين (X1,Y1)، ترسم عبارة Line في هذا الإجراء خطاً ما، ابتداءً من الإحداثيين CurrentX وCurrentY، تكون القيمة الابتدائية للإحداثيين CurrentX وCurrentY مساوية إلى الصفر عند بدء تشغيل البرنامج. وهذا يشرح سبب بداية الخط في الشكل 8-4 من الإحداثيين 0,0.
qاختر رسم خطوط من القائمة رسوم عدة مرات.
يُرسم خط جديد في كل مرة، ويبدأ من نهاية الخط السابق (انظر الشكل 8-5).
q اختر خروج من القائمة ملف لإنهاء البرنامج.
|
|
الشكل 8-5 رسم خطوط متصلة. |
دعنا الآن نكتب برنامجاً يرسم عدة خطوط عند اختيار رسم خطوط من القائمة رسوم:
Private Sub mnuLines_Click()
Dim Counter
For Counter = 1 To 100 Step 1
Line -(Rnd * frmPoints.ScaleWidth, _
Rnd * frmPoints.ScaleHeight), RGB(0, 0, 0)
Next
End Sub
q نفّذ البرنامج.
q اختر رسم خطوط من القائمة رسوم.
يرسم البرنامج مائة خط متصل، حسب ما يبينه الشكل8-6.
|
|
الشكل 8-6 رسم مائة خط متصل. |
يمكنك استخدام الوسيط Step الاختياري في الطريقة Line، كما يلي:
Line (X1,Y1) - Step (dx,dy),Color
علماً أن (X1,Y1) تمثل إحداثيات نقطة البداية، أما Step (dx,dy) فهي دلالة لفيجول بيسك، بأن نقطة نهاية الخط تقع عند الإحداثيين X1 + dx و Y1 + dy. فمثلاً ترسم العبارة التالية:
Line (20,30) - Step (50,100), RGB(0,0,0)
خطاً يبدأ من الإحداثيين 20 , 30 وينتهي بالإحداثيين 70 , 130.
يمكن استخدام الإمكانية Step أيضاً لرسم مربع. ترسم العبارات التالية المربع المبين في الشكل 8-7:
Line (10,20) - (400,20)
Line -Step(0,400)
Line -Step(-300,0)
Line -Step(0,-400)
|
|
الشكل 8-7 رسم مربع بطريقة رسم الخط Line. |
كما تشاهد تعتبر عبارات Line الأربعة لازمة لرسم مربع واحد، الطريقة الأسهل لرسم مربع، بواسطة الطريقة Line تكون باستخدام Line مع الخيار B، أي:
Line (100,20)-(400,420),RGB(0,0,0),B
الإحداثيان الأولين هما إحداثيا الزاوية اليسرى العليا للمربع، أما الإحداثيان اللذان يليهما فيمثلان إحداثيي الزاوية السفلى اليمنى للمربع. يطلب الوسيط B من فيجول بيسك، رسم مربع له هاتين الزاويتين.
إذا أردت ملء المربع (طمسه)، استخدم الوسيط F:
Line(100,20)-(400,420),RGB(0,255,0),BF
ترسم هذه العبارة مربعاً وتملؤه باللون الأخضر، لا توجد فاصلة بين B و F لأنك لا تستطيع استخدام F بدون B.
ملاحظة
يقصد برسم المربع هنا، رسم شكل رباعي الأضلاع، وهو ليس بالضرورة مربعاً متساوي الأضلاع.
تُقدم الخاصية FillStyle طريقة ثانية لملء المربع المرسوم، فباستخدام الخاصيتين FillColor وFillStyle للنموذج، واستخدام طريقة Line مع الوسيط B دون الوسيط F نستطيع ملء المربع:
frmMyForm.FillStyle = 2
frmMyForm.FillColor = RGB(255,0,0)
frmMyForm.Line (100,20)-(400,420),RGB(0,0,0),B
تسند العبارة الأولى القيمة 2 إلى الخاصية FillStyle. يبين الجدول 8-4 معاني القيم النهائية المحتملة لهذه الخاصية، وعندما تكون قيمة FillStyle مساوية إلى 2، يمُلأ الكائن بخطوط أفقية.
تسند العبارة الثانية اللون الأحمر RGB(255,0,0) إلى الخاصية FillColor، (بمعنى أن المربع سيلون بالأحمر)، وهكذا تتسبب العبارات الثلاث برسم مربع وملؤه بخطوط شاقولية حمراء.
الجدول 8-4. القيم الثمانية المحتملة للخاصية FillStyle.
|
القيمة |
الشرح |
|
0 |
لون خالص مصمت Solid. |
|
1 |
لون شفاف غير مرئي Transparent (القيمة الافتراضية). |
|
2 |
خطوط أفقية Horizontal Lines. |
|
3 |
خطوط عمودية Vertical Lines. |
|
4 |
خطوط مائلة للأعلى Upward diagonal Lines. |
|
5 |
خطوط مائلة للأسفل Downward diagonal Lines. |
|
6 |
خطوط متقاطعة Cross hatch |
|
7 |
خطوط متقاطعة مائلة Diagonal Cross hatch. |
للتعرف على معاني كل قيمة من قيم الخاصية FillStyle في الجدول 8-4 قم بما يلي:
q أضف القائمة رسم مربع إلى نظام قوائم النموذج frmPoints.
يعطي الجدول 8-5 جدول القائمة الجديد.
الجدول 8-5. إضافة القائمة رسم مربع إلى النموذج frmPoints.
|
العنوان |
الخاصية Name |
|
&ملف |
mnuFile |
|
…&خروج |
mnuExit |
|
&رسوم |
mnuGraphics |
|
…ار&سم النقاط |
mnuDrawPoints |
|
…ا&مسح النقاط |
mnuClear |
|
…رسم &خطوط |
mnuLines |
|
رسم مربع |
mnuDrawBox |
|
…أحمر |
mnuRed |
|
…أخضر |
mnuGreen |
|
…أزرق |
mnuBlue |
|
…- |
mnuSep1 |
|
…تغيير نمط الرسم |
mnuSetStyle |
q أضف النص التالي ضمن الإجراء mnuRed_Click() للنموذج frmPoints:
Private Sub mnuRed_Click()
'تغيير الخاصية FillColor إلى الأحمر
frmPoints.FillColor = RGB(255, 0, 0)
'رسم المربع
frmPoints.Line (100, 80)-Step(5000, 3000), _
RGB(255, 0, 0), B
End Sub
q أضف النص التالي ضمن الإجراء mnuBlue_Click() للنموذج frmPoints:
Private Sub mnuBlue_Click()
'تغيير الخاصية FillColor إلى الأحمر
frmPoints.FillColor = RGB(255, 0, 0)
'رسم المربع
frmPoints.Line (100, 80)-Step(5000, 3000), _
RGB(0, 0, 255), B
End Sub
q أضف النص التالي ضمن الإجراء mnuGreen_Click() للنموذج frmPoints:
Private Sub mnuGreen_Click()
'تغيير الخاصية FillColor إلى الأحمر
frmPoints.FillColor = RGB(255, 0, 0)
'رسم المربع
frmPoints.Line (100, 80)-Step(5000, 3000), _
RGB(0, 255, 0), B
End Sub
qأضف النص التالي ضمن الإجراء mnuSetStyle_Click() للنموذج frmPoints:
Private Sub mnuSetStyle_Click()
Dim FromUser
Dim Instruction
Instruction = "FillStyle أدخل رقماً(0-7) لتعيينه للخاصية"
'الحصول على قيمة من المستخدم
FromUser = InputBox$(Instruction, _
"FillStyle تعيين قيمة ")
'تنظيف النموذج
frmPoints.Cls
'التأكد من القيمة المدخلة
If Val(FromUser) >= 0 And Val(FromUser) <= 7 Then
frmPoints.FillStyle = Val(FromUser)
Else
Beep
MsgBox ("قيمة غير صحيحة")
End If
'رسم المربع
frmPoints.Line (100, 80)-Step(5000, 3000), _
RGB(0, 0, 0), B
End Sub
q احفظ المشروع، باختيار Save Project من القائمة File لفيجول بيسك.
لنشاهد ما كتبناه قيد العمل:
qنفّذ برنامج النقاط.
qاختر تغيير نمط الرسم من القائمة رسم مربع.
يستجيب البرنامج بإظهار مربع إدخال (Input Box) حسب ما يظهر من الشكل 8-8.
|
|
الشكل 8-8 إدخال قيمة للخاصية FillStyle. |
qأدخل رقماً بين صفر و سبعة، وانقر الزر OK. يمثل هذا الرقم قيمة الخاصية FillStyle.
يُظهر البرنامج المربع ويملؤه حسب قيمة FillStyle المدخلة في الخطوة السابقة. يظهر في الشكل 8-9 المربع عندما تكون قيمة FillStyle مساوية إلى 4 (خطوط مائلة). قد تضطر إلى سحب الحافة اليسارية للإطار لتوسيعه.
|
|
الشكل 8-9 التمرن على الخاصية FillStyle. |
q اختر أحمر أو أزرق أو أخضر من القائمة رسم مربع.
يستجيب البرنامج برسم المربع باللون المنتقى.
q تمرن على برنامج النقاط، واختر خروج من القائمة ملف لإنهائه.
ينفذ الإجراء mnuRed_Click عند اختيار أحمر من القائمة رسم مربع:
Private Sub mnuRed_Click()
'تغيير الخاصية FillColor إلى الأحمر
frmPoints.FillColor = RGB(255, 0, 0)
'رسم المربع
frmPoints.Line (100, 80)-Step(5000, 3000), _
RGB(255, 0, 0), B
End Sub
يحدد هذا الإجراء قيمة الخاصية FillColor باللون الأحمر، ثم يستخدم الطريقة Line مع الوسيط B لرسم مربع. يملأ المربع تبعاً للقيمة الراهنة للخاصية FillStyle للنموذج.
يعمل الإجراءان mnuBlue_Click() و mnuGreen_Click() بطريقة مشابهة، محددين قيمة الخاصية FillColor باللون الأزرق Blue أو الأخضر Green.
ينفذ هذا الإجراء عند اختيار تغيير نمط الرسم من القائمة رسم مربع:
Private Sub mnuSetStyle_Click()
Dim FromUser
Dim Instruction
Instruction = "FillStyle أدخل رقماً(0-7) لتعيينه للخاصية"
'الحصول من المستخدم على القيمة
FromUser = InputBox$(Instruction, _
"FillStyle تعيين قيمة ")
'تنظيف النموذج
frmPoints.Cls
'التأكد من القيمة المدخلة
If Val(FromUser) >= 0 And Val(FromUser) <= 7 Then
frmPoints.FillStyle = Val(FromUser)
Else
Beep
MsgBox ("قيمة غير صحيحة")
End If
'رسم المربع
frmPoints.Line (100, 80)-Step(5000, 3000), _
RGB(0, 0, 0), B
End Sub
يستخدم هذا الإجراء التابع الوظيفي InputBox() للحصول على رقم بين صفر وسبعة، ثم ينظف النموذج بواسطة الطريقة Cls، يلي ذلك التحقق من القيمة التي أدخلها المستخدم وذلك باستخدام العبارة If بغية التحقق من أن القيمة تقع ضمن المجال الصحيح (المسموح به).
فإذا كانت القيمة المدخلة واقعة بين صفر وسبعة،تُحَدَّث عند ذلك الخاصية FillStyle بإسناد تلك القيمة إليها.
ترسم آخر عبارة في الإجراء مربعاً باستخدام الطريقة Line مع الإمكانية B. يُرسم المربع اعتماداً على القيمتين الحاليتين للخاصتين FillColor وFillStyle للنموذج.
نُقدم الآن طريقة رسم هامة أخرى وهي الطريقة Circle، تُستخدم هذه الطريقة لرسم الدوائر والقطوع الناقصة، ويوضح برنامج الدائرة كيفية رسم الدوائر.
يمكنك استخدام الطريقة Circle لرسم الدوائر سواء في النموذج، أوفي عنصر تحكم الصورة.
نبدأ كعادتنا بطور التمثيل المرئي (طور التصميم) لنموذج برنامج الدائرة:
qأنشئ مشروعاً تنفيذياً قياسياً جديداً Standard EXE، واحفظ نموذج المشروع بالاسم Circles.frm في الدليل C:\VB5Prg\Ch08، واحفظ المشروع بالاسم Circles.vbp في الدليل C:\VB5Prg\Ch08.
qأنشئ النموذج frmCircles وفقاً للجدول 8-6.
يفترض أن يبدو النموذج المكتمل كما في الشكل 8-10.
|
|
الشكل 8-10 النموذج frmCircles في طور التصميم. |
الجدول 8-6 جدول خصائص النموذج frmCircles.
|
الكائن |
الخاصية |
القيمة |
|
Form |
Name |
frmCircles |
|
|
Caption |
برنامج الدائرة |
|
|
RightToLeft |
True |
|
CommandButton |
Name |
cmdExit |
|
|
Caption |
&خروج |
|
|
RightToLeft |
True |
|
Picture Box |
Name |
picCircles |
|
|
BorderStyle |
1-Fixed Single |
|
Vertical Scroll Bar |
Name |
vsbRadius |
|
|
Max |
100 |
|
|
Min |
1 |
|
|
Value |
1 |
|
Horizontal Scroll Bar |
Name |
hsbCircleWidth |
|
|
Max |
10 |
|
|
Min |
1 |
|
|
Value |
1 |
|
Label |
Name |
lblWidth |
|
|
Caption |
العرض: |
|
|
RightToLeft |
True |
|
Label |
Name |
lblRadius |
|
|
Caption |
نصف القطر: |
|
|
RightToLeft |
True |
سندخل الآن نص برنامج الدائرة:
qتحقق من احتواء قسم التصاريح العامة على العبارة Option Explicit، أي:
' يجب التصريح عن كل المتحولات
Option Explicit
q أدخل النص التالي ضمن الإجراء cmdExit_Click() للنموذج frmCircles:
Private Sub cmdExit_Click()
End
End Sub
q أدخل النص التالي ضمن الإجراء hsbCircleWidth_Change():
Private Sub hsbCircleWidth_Change()
Dim X, Y, Radius
picCircles.DrawWidth = hsbCircleWidth.Value
X = picCircles.ScaleWidth / 2
Y = picCircles.ScaleHeight / 2
picCircles.Cls
picCircles.Circle (X, Y), vsbRadius.Value * 10, _
RGB(255, 0, 0)
End Sub
q أدخل النص التالي ضمن الإجراء hsbCircleWidth_Scroll():
Private Sub hsbCircleWidth_Scroll()
hsbCircleWidth_Change
End Sub
q أدخل النص التالي ضمن الإجراء vsbRadius_Change():
Private Sub vsbRadius_Change()
Dim X, Y, Radius
X = picCircles.ScaleWidth / 2
Y = picCircles.ScaleHeight / 2
picCircles.Cls
picCircles.Circle (X, Y), vsbRadius.Value * 10, _
RGB(255, 0, 0)
End Sub
q أدخل النص التالي ضمن الإجراء vsbRadius_Scroll():
Private Sub vsbRadius_Scroll()
vsbRadius_Change
End Sub
q احفظ المشروع بالطريقة المعتادة.
لنشاهد ما كتبناه قيد التنفيذ:
q نفّذ برنامج الدائرة.
q غَيِّر موقع مؤشر شريط التمرير العمودي.
يتغير نصف قطر الدائرة الظاهرة، وفقاً لوضعية مؤشر شريط التمرير العمودي (انظر الشكل 8-11).
qغَيِّر موقع مؤشر شريط التمرير الأفقي لتحديد قيمة جديدة لعرض حدود الدائرة. وترسم الدائرة بخط مختلف العرض.
|
|
الشكل 8-11 تغيير نصف قطر الدائرة بواسطة شريط التمرير العمودي. |
يستخدم برنامج الدائرة الطريقة Circle لرسم الدائرة. يتغير نصف قطر الدائرة تبعاً لموقع مؤشر شريط التمرير العمودي، ويتغير عرض حدود الدائرة تبعاً لموقع مؤشر شريط التمرير الأفقي.
ينفذ الإجراء vsbRadius_Change() عند تغيير موقع مؤشر شريط التمرير الأفقي:
Private Sub vsbRadius_Change()
Dim X, Y, Radius
X = picCircles.ScaleWidth / 2
Y = picCircles.ScaleHeight / 2
picCircles.Cls
picCircles.Circle (X, Y), vsbRadius.Value * 10, _
RGB(255, 0, 0)
End Sub
يحسب هذا الإجراء، إحداثيي نقطة مركز الدائرة (x,y) بحساب إحداثيات مركز عنصر تحكم الصورة، بحيث يكون مركز الدائرة هو نفسه مركز عنصر تحكم الصورة.
يلي ذلك تنظيف المحتويات الرسومية السابقة الموجودة على عنصر تحكم الصورة، وذلك باستخدام الطريقة Cls (أي تنظيف العنصر من الدائرة السابقة في حال وجودها)، وأخيراً ترسم الدائرة باستخدام الطريقة Circle:
picCircles.Circle (X, Y), vsbRadius.Value * 10, _
RGB(255, 0, 0)
يكون نصف قطر الدائرة المرسومة بلون أحمر، أكبر عشر مرات من القيمة (الحالية) الراهنة لموقع مؤشر شريط التمرير العمودي.
ملاحظه
استخدم الطريقة Circle لرسم دائرة ما على الكائن:
ObjectName.Circle(X , Y) , Radius , color
فمثلاً، لرسم دائرة زرقاء على النموذج المدعو frmMyForm باحداثيي مركز 1000,500 ونصف قطر 75، استخدم العبارة التالية:
frmMyForm.Circle (1000 , 500), 75 , RGB(0,0,255)
بطريقة مشابهة، يرسم الإجراء vsbRadius_Scroll() دائرة جديدة عند تغيير موقع مؤشر شريط التمرير العمودي، وذلك باستدعاء الإجراء vsbRadius_Change.
ينفذ الإجراء hsbCircleWidth_Change() عند تغيير موقع مؤشر شريط التمرير الأفقي:
Private Sub hsbCircleWidth_Change()
Dim X, Y, Radius
picCircles.DrawWidth = hsbCircleWidth.Value
X = picCircles.ScaleWidth / 2
Y = picCircles.ScaleHeight / 2
picCircles.Cls
picCircles.Circle (X, Y), vsbRadius.Value * 10, _
RGB(255, 0, 0)
End Sub
يغيّر هذا الإجراء الخاصية DrawWidth لعنصر تحكم الصورة المدعو picCircles، تبعاً لموقع مؤشر شريط التمرير الأفقي. تحدِد قيمة الخاصية DrawWidth عرض الدائرة المرسومة في عنصر تحكم الصورة. وكما تشاهد هناك تشابه كبير بين هذا الإجراء والإجراء vsbRadius_Change(). ولكن بدلاً من تغيير نصف القطر، يتم هنا تحديث الخاصية DrawWidth لعنصر تحكم الصورة:
picCircles.DrawWidth = hsbCircleWidth.Value
وبطريقة مشابهة، يرسم الإجراء hsbCircleWidth_Scroll() دائرة جديدة، عند تغيير عرض حدود الدائرة، عند تحريك مؤشر شريط التمرير الأفقي، وذلك باستدعاء الإجراء hsbCircleWidth_Change().
نستطيع بإضافة بعض الأسطر إلى برنامج الدائرة، الحصول على مؤثرات رسومية جذابة:
q أضف الزر نمط الرسم إلى النموذج frmCircles، حسب مايبينه الشكل 8-12.
q أسند لهذا الزر الخصائص التالية:
Name: cmdDrawStyle
Caption: نمط الرسم
RightToLeft: True
|
|
الشكل 8-12 إضافة الزر نمط الرسم إلى برنامج الدائرة. |
qأضف النص التالي ضمن الإجراء cmdDrawStyle_Click() للنموذج frmCircles:
Private Sub cmdDrawStyle_Click()
Dim TheStyle
TheStyle = InputBox$("أدخل رقماً(0-6):")
If Val(TheStyle) < 0 Or Val(TheStyle) > 6 Then
Beep
MsgBox ("إدخال غير صحيح")
Else
picCircles.DrawStyle = Val(TheStyle)
End If
End Sub
qاحذف شريط التمرير الأفقي. (تأكد من اختيار شريط التمرير الأفقي ثم اضغط المفتاح Delete لحذفه).
كتبنا في النسخة السابقة لبرنامج الدائرة، نص الإجراء hsbWidth_Change()، أما الآن، فقد حذفنا عنصر التحكم هذا، لهذا يضع فيجول بيسك نص هذا الإجراء في المنطقة General للنموذج frmCircles، لهذا تستطيع بعد حذفك عنصر التحكم، إزالة إجراءاته (Procedures) أيضاً من المنطقة General.
qاحذف الإجراء hsbWidth_Change() من المنطقة General، وذلك بإضاءته كاملاً بما في ذلك أول وآخر سطرين فيه، ثم اضغط الزر Delete من لوحة المفاتيح.
qاحذف الإجراء hsbWidth_Scroll() من المنطقة General بنفس الطريقة المتبعة في الخطوة السابقة.
q احذف اللافتة lblWidth باختيارها، ثم ضغط المفتاح Delete من لوحة المفاتيح.
qحدد اللون الأبيض White في الخاصية BackColor لعنصر التحكم picCircles، مما يعني أن الدائرة سترسم على خلفية بيضاء، الأمر الذي يمكِّنك من مشاهدة تأثيرات نماذج الرسم بشكل أفضل.
دعنا نشاهد النص الذي كتبناه قيد التنفيذ:
q نفّذ برنامج الدائرة.
q انقر الزر نمط الرسم.
يستجيب البرنامج بإظهار مربع رسالة، يطلب منك إدخال رقم بين الصفر والستة.
qأدخل رقماً بين الصفر والستة (هذا الرقم يمثل نمط الرسم)، ثم انقر على الزر OK.
qحرك مؤشر شريط التمرير العمودي جيئة وذهاباً، وشاهد التأثيرات التي تتسبب بها قيم مختلفة لأنصاف الأقطار والأنماط المختلفة، على الدائرة.
qأنهِ البرنامج بالنقر على الزر خروج.
يُنفذ الإجراء cmdDrawStyle_Click() عند نقر الزر نمط الرسم.
يُطلب منك إدخال رقم بين الصفر والستة، ويُستخدم هذا الرقم كقيمة للخاصية DrawStyle لعنصر تحكم الصورة. يعرض الجدول 8-7 قائمة بالقيم السبعة المحتملة للخاصية DrawStyle ومعانيها.
الجدول 8-7. القيم السبعة المحتملة للخاصية DrawStyle.
|
القيمة |
الشرح |
|
0 |
مصمت Solid (القيمة الافتراضية). |
|
1 |
شَرطة Dash ( - - - ). |
|
2 |
نقطة Dot ( . . . ). |
|
3 |
شَرطة نقطة Dash Dot ( - . - . ). |
|
4 |
شَرطة نقطة نقطة Dash Dot Dot ( - . . - . . ). |
|
5 |
غير مرئي Invisible. |
|
6 |
مصمت داخلي Inside Solid. |
ملاحظة
تغير الخاصية DrawStyle، طريقة رسم الخطوط على الكائن، كما رأينا في الجدول السابق.
لكن هناك شرط واحد لكي تظهر هذه التأثيرات وهو: أن يكون عرض حدود الخطوط مساو للواحد (DrawWidth = 1)، ولا يمكن ظهور هذه التأثيرات، في حال ما إذا كانت قيمة الخاصية DrawWidth أكبر من الواحد.
سنجري الآن تعديلاً إضافياً على برنامج الدائرة:
qاستبدل نص الإجراء vsbRadius_Change() بالنص التالي:
Private Sub vsbRadius_Change()
Dim X, Y, Radius
Static LastValue
Dim R, G, B
R = Rnd * 255
G = Rnd * 255
B = Rnd * 255
X = picCircles.ScaleWidth / 2
Y = picCircles.ScaleHeight / 2
If LastValue > vsbRadius.Value Then
picCircles.Cls
End If
picCircles.Circle (X, Y), vsbRadius.Value * 10, _
RGB(R, G, B)
LastValue = vsbRadius.Value
End Sub
qاحفظ المشروع باختيار Save Project من القائمة File.
سنشاهد الآن بعض المؤثرات الرسومية الجميلة:
qنفّذ برنامج الدائرة.
qانقر على الزر نمط الرسم.
يستجيب البرنامج بإظهار مربع الدخول Input Box الذي يطالبك بإدخال رقم بين الصفر والستة.
qأدخل الرقم 2 ثم انقر على الزر OK.
qزد موقع مؤشر شريط التمرير العمودي نصف القطر بالنقر عدة مرات، فوق رأس السهم النازل الواقع أسفل شريط التمرير هذا.
يستجيب البرنامج برسم دوائر كما في الشكل 8-13.
qأنقص موقع مؤشر شريط التمرير العمودي نصف القطر بالنقر عدة مرات، فوق رأس السهم الصاعد المتوضع أعلى شريط التمرير.
يستجيب البرنامج برسم دوائر متعاقبة أصغر.
qتمرن على برنامج الدائرة، ثم أنهِ البرنامج بنقر الزر خروج.
|
|
الشكل 8-13 رسم دوائر بواسطة النسخة المحسنة من برنامج الدائرة. |
ينفذ الإجراء vsbRadius_Change() آلياً عند تغيير موقع مؤشر شريط التمرير.
يبدأ الإجراء بالتصريح عن بضعة متحولات، ويعرّف المتحول الثاني كمتحول ساكن Static:
Static LastValue
مما يعني أن المتحول LastValue لا تسند له القيمة الابتدائية صفر، كلما نُفذ هذا الإجراء، وبمعنى آخر، يحافظ المتحول على قيمته ضمن هذا الإجراء.
يجهز الإجراء بعد ذلك المتحولات الثلاثة R,G,B ويسند إليها أرقاماً تمثل ألواناً عشوائية:
'توليد لون عشوائي
R = Rnd * 255
G = Rnd * 255
B = Rnd * 255
يحسب الإجراء بعد ذلك إحداثيات مركز عنصر تحكم الصورة:
X = picCircles.ScaleWidth / 2
Y = picCircles.ScaleHeight / 2
تستخدم الإحداثيات بعد ذلك ضمن هذا الإجراء كإحداثيات لمركز الدوائر.
يحتفظ المتحول LastValue بقيمة الخاصية Value لشريط التمرير العمودي، قبل تغيير موقع مؤشر شريط التمرير.
تتحقق العبارة If إذا كان الموقع الحالي لمؤشر شريط التمرير (المحدد بالخاصية Value)، أصغر من آخر موقع لشريط التمرير:
If LastValue > vsbRadius.Value Then
picCircles.Cls
End If
إذا كانت القيمة الراهنة للخاصية Value لشريط التمرير العمودي، أصغر من قيمة المتحول LastValue، فهذا يعني أنك أنقصت قيمة شريط التمرير. وفي هذه الحالة تنفذ الطريقة Cls التي تنظف عنصر تحكم لصورة.
يرسم الإجراء بعد ذلك دائرة باستخدام الطريقة Circle:
picCircles.Circle (X, Y), vsbRadius.Value * 10, RGB(R, G, B)
وآخر شيء يفعله هذا الإجراء، هو تحديث قيمة المتحول LastValue. وعند التنفيذ التالي لهذا الإجراء، تمثل قيمة المتحول LastValue الخاصية Value لشريط التمرير قبل التغيير:
LastValue = vsbRadius.Value
فإذا زاد المستخدم شريط التمرير، لا تنفذ الطريقة Cls، وهكذا تبقى الدوائر التي رسمت مسبقاً على الشاشة عند زيادة شريط التمرير، وينظف عنصر تحكم الصورة عند إنقاص شريط التمرير.
لعل المتحول LastValue هو الشيء الهام الواجب الانتباه إليه، من المناقشة السابقة.
يصرح عن هذا المتحول بأنه Static:
Static LastValue
تُسند القيمة صفر إلى المتحول LastValue عند تنفيذ الإجراء vsbRadius_Change() لأول مرة من قبل فيجول بيسك. تتغير هذه القيمة أثناء تنفيذ الإجراء، وعند التنفيذ التالي لهذا الإجراء، يُعاد إسناد القيمة الابتدائية صفر إلى المتحولات الغير ساكنة non static (مثل المتحول X و Y و Radius) من جديد.
أما المتحول LastValue فلا تتبدل قيمته منذ آخر تنفيذ للإجراء، وذلك بسبب التصريح عنه بأنه من النوع الساكن Static (بمعنى أنه يحتفظ بقيمته التي أسندت إليه من التنفيذ السابق للإجراء).
قد تلاحظ تشابهاً بين المتحول المصرح عنه في قسم التصاريح العامة General Declarations، وبين المتحول المصرح عنه كمتحول ساكن Static. ففي كلتا الحالتين، يحتفظ المتحول بقيمته طالما أن البرنامج يعمل. لكن هنالك اختلاف هام بين نوعي المتحولين هذين:
qالمتحول المصرح عنه في قسم التصاريح العامة لنموذج يمكن الولوج إليه من ضمن أي إجراء في النموذج.
qالمتحول المصرح عنه في إجراء كمتحول ساكن Static، يقبل الولوج إليه من ضمن الإجراء الذي صرّح عن هذا المتحول.
فإذا حاولت مثلاً الولوج إلى المتحول LastValue من ضمن الإجراء Form_Load() مثلاً، فسوف ينتج لديك خطأ، لأنك لا تستطيع الوصول إلى هذا المتحول من خارج الإجراء vsbRadius_Change()، يمكنك أيضاً التصريح عن متحول آخر يدعى LastValue ضمن الإجراء Form_Load(). وهذه القيمة يمكن التصريح عنها كمتحول ساكن أو متحول غير ساكن نظامي، لكن لا يوجد أي صلة بين المتحول LastValue المنتمي للإجراء Form_Load()، وبين المتحول LastValue الخاص بالإجراء vsbRadius_Change().
وكما ترى، يعتبر التصريح عن متحول ساكن، حيلة جيدة للاستخدام، عندما لا ترغب بفقدان قيمة المتحول بعد الانتهاء من تنفيذ الإجراء.
تُخزن المتحولات غير الساكنة النظامية، والمتحولات الساكنة في الحاسب الشخصي PC بطرق مختلفة. فمثلاً قارن بين كيفية تخزين المتحول Radius، (والذي يمثل متحولاً نظامياً غير ساكن ومحلي ضمن الإجراء vsbRadius_Change()، وتخزين المتحول LastValue الساكن.
تضيع قيمة المتحول Radius بعد الخروج من الإجراء vsbRadius_Change() إلى الأبد، وهكذا فإن خلايا الذاكرة التي كانت مخصصة لحفظ المتحول Radius تصبح حرة (أي خالية). أما خلايا الذاكرة المستخدمة لحفظ المتحول الساكن LastValue، تبقى محجوزة طالما أن برنامج الدائرة قيد التنفيذ. كذلك الأمر، يبقى المتحول المصرح عنه في قسم التصاريح العامة في الذاكرة طالما أن البرنامج يعمل.
تُستخدم الطريقة Circle لرسم القطوع الناقصة والأقواس.
وتعطى الصيغة العامة الكاملة لهذه الطريقة بما يلي:
[object.]Circle [Step] ( X , Y ), _
radius , _
[color], _
[start], _
[ end ], _
[aspect]
يُؤدي استخدام الكلمة Step ضمن صيغة العبارة Circle، إلى الدلالة على أن الإحداثيين (X,Y) منسوبين للإحداثيين CurrentY CurrentX ,. فمثلاً، إذا كانت قيمة CurrentX تساوي 1000، وقيمة CurrentY تساوي 3000، ترسم العبارة التالية دائرة بنصف قطر يساوي 80، ومركز الإحداثيات (X = 1010 , Y = 3010):
frmMyform.Circle Step (10,20),80
الوسيط Aspect عبارة عن رقم موجب يتسبب برسم قطوع ناقصة. فمثلاً، تُولد الطريقة Circle دائرة مكتملة إذا كانت قيمة Aspect تساوي الواحد، أما عندما تكون قيمة Aspect أكبر من الواحد، فتولد الطريقة Circle عند ذلك، قَطعاً ناقصاً، يتطاول على محوره العمودي. وعندما تكون قيمة Aspect أقل من الواحد، تولد الطريقة Circle قَطعاً ناقصاً يمتد على محوره الأفقي. تُبين الأشكال 8-14و 8-15و 8-16 ثلاثة قطوع ناقصة بثلاثة قيم مختلفة للوسيط Aspect (نسبة القطرين).
|
|
الشكل 8-14 رسم دائرة مكتملة Aspect = 1. |
|
|
الشكل 8-15 رسم قطع ناقص متطاول أفقياً Aspect = 0.5. |
|
|
الشكل 8-16 رسم قطع ناقص متطاول عمودياً Aspect = 2.7. |
يوضح برنامج القطوع الناقصة، كيفية رسم القطوع الناقصة، بأنصاف أقطار وقيم مختلفة للوسيط Aspect.
نبدأ كعادتنا بالتمثيل المرئي لنموذج البرنامج:
qأنشئ مشروعاً جديداً قياسياً من النوع Standard EXE، ثم احفظ نموذج المشروع بالاسم Ellipses.frm في الدليل C:\VB5Prg\Ch08، واحفظ ملف المشروع في ذات الدليل بالاسم Ellipses.vbp.
q أنشئ النموذج frmEllipses طبقاً للجدول 8-8.
يُفترض أن يبدو النموذج كما هو مبين في الشكل 8-17.
|
|
الشكل 8-17 النموذج frmEllipses (طور التصميم). |
الجدول 8-8. جدول خصائص النموذج frmEllipses.
|
الكائن |
الخاصية |
القيمة |
|
Form |
Name |
frmEllipses |
|
|
Caption |
برنامج القطوع الناقصة |
|
|
RightToLeft |
True |
|
CommandButton |
Name |
cmdExit |
|
|
Caption |
&خروج |
|
|
RightToLeft |
True |
|
Horizontal Scroll Bar |
Name |
hsbAspect |
|
|
Max |
100 |
|
|
Min |
1 |
|
|
Value |
1 |
|
Horizontal Scroll Bar |
Name |
hsbRadius |
|
الكائن |
الخاصية |
القيمة |
|
|
Max |
100 |
|
|
Min |
1 |
|
|
Value |
1 |
|
Label |
Name |
lblInfo |
|
|
Caption |
نسبة القطرين: |
|
|
RightToLeft |
True |
|
Label |
Name |
lblAspect |
|
|
Caption |
نسبة القطرين: |
|
|
RightToLeft |
True |
|
Label |
Name |
lblRadius |
|
|
Caption |
نصف القطر: |
|
|
RightToLeft |
True |
ستدخل الآن نص برنامج القطوع الناقصة:
qتحقق بأن العبارة Option Explicit تقع ضمن قسم التصاريح العامة للنموذج frmEllipses:
' يجب التصريح عن كل المتحولات
Option Explicit
q أدخل النص التالي ضمن الإجراء cmdExit_Click():
Private sub cmdExit_Click()
End
End sub
q أدخل النص التالي ضمن الإجراء Form_Load():
Private Sub Form_Load()
hsbAspect.Value = 10
hsbRadius.Value = 10
lblInfo.Caption = "نسبة القطرين: 1"
frmEllipses.DrawWidth = 2
End Sub
q أدخل النص التالي ضمن الإجراء hsbAspect_Change():
Private Sub hsbAspect_Change()
Dim X, Y
Dim Info
X = frmEllipses.ScaleWidth / 2
Y = frmEllipses.ScaleHeight / 2
frmEllipses.Cls
frmEllipses.Circle (X, Y), hsbRadius.Value * 10, _
RGB(255, 0, 0), , , hsbAspect.Value / 10
Info = "نسبة القطرين: " + Str(hsbAspect.Value / 10)
frmEllipses.lblInfo.Caption = Info
End Sub
q أدخل النص التالي ضمن الإجراء hsbAspect_Scroll():
Private Sub hsbAspect_Scroll()
hsbAspect_Change
End Sub
qأدخل النص التالي ضمن الإجراء hsbRadius_Change() للنموذج frmEllipses:
Private Sub hsbRadius_Change()
Dim X, Y
Dim Info
X = frmEllipses.ScaleWidth / 2
Y = frmEllipses.ScaleHeight / 2
frmEllipses.Cls
frmEllipses.Circle (X, Y), hsbRadius.Value * 10, _
RGB(255, 0, 0), , , hsbAspect.Value / 10
Info = "نسبة القطرين: " + Str(hsbAspect.Value / 10)
frmEllipses.lblInfo.Caption = Info
End Sub
q أدخل النص التالي ضمن الإجراء hsbRadius_Scroll():
private sub hsbRadius_Scroll()
hsbRadius_Change()
End sub
لنشاهد ما كتبناه على أرض الواقع:
qنفّذ برنامج القطوع الناقصة.
qبدّل موقع مؤشر شريط التمرير نصف القطر لرسم دوائر وقطوع، بواسطة قيم مختلفة لنصف القطر.
qبدّل موقع مؤشر شريط التمرير نسبة القطرين لرسم قطوع ناقصة ذات قيم مختلفة للوسيط Aspect.
لاحظ أن قيمة الوسيط Aspect الراهنة تظهر على يمين شريط التمرير نسبة القطرين. يرسم البرنامج دائرة مكتملة عندما تكون قيمة نسبة القطرين تساوي الواحد، أما عندما تكون قيمة نسبة القطرين أقل من الواحد، يرسم البرنامج عندها قَطعاً ناقصاً ممتداً على محوره الأفقي، كما يظهر من الشكل 8-15، أما عندما تكون قيمة نسبة القطرين أكبر من الواحد، يرسم البرنامج قطعاً ممتداً على محوره العمودي، حسب ما يوضحه الشكل 8-16.
يرسم البرنامج قطوعاً ناقصة باستخدام الطريقة Circle. وتستخدم الخاصية Value لشريطي التمرير كوسائط تمرر للطريقة Circle.
ينفذ الإجراء Form_Load() عند تحميل النموذج frmEllipses (أي في بداية التنفيذ):
Private Sub Form_Load()
hsbAspect.Value = 10
hsbRadius.Value = 10
lblInfo.Caption = "نسبة القطرين: 1"
frmEllipses.DrawWidth = 2
End Sub
يسند هذا الإجراء القيمة 10 إلى الخاصية Value لشريط التمرير ثم يظهر اللافتة lblInfo وهي تحمل العنوان (نسبة القطرين: 1)، على يمين شريط التمرير نسبة القطرين. ستلاحظ قريباً أن البرنامج يستخدم عُشْر قيمة الخاصية Value لشريط التمرير نسبة القطرين، كقيمة للوسيط Aspect في الطريقة Circle.
فمثلاً، عندما تكون قيمة الخاصية Value لشريط التمرير نسبة القطرين مساوية إلى 20، فهذا يعني أن الطريقة Circle تستخدم القيمة 2 كقيمة للوسيط Aspect، وهذا هو السبب وراء قيام الإجراء Form_Load() بتسمية اللافتة lblInfo بالعنوان (نسبة القطرين: 1) بعد إسناد القيمة 10 إلى شريط التمرير نسبة القطرين.
تسند آخر عبارة في هذا الإجراء القيمة 2 إلى الخاصية DrawWidth للنموذج.
frmEllipses.DrawWidth = 2
يتسبب هذا الأمر، برسم الأشكال بعرض يساوي إلى وحدتي قياس (أي 2 Units)، وحدة القياس قد تكون نقطة ضوئية Pixel، (حسبما هو محدد في الخاصية ScaleMode)، وهكذا فعند استخدام الطريقة Circle ترسم القطوع بخط عرضه وحدتين.
لاحظ أن الإجراء عمد إلى إسناد قيمة معينة للخاصية DrawWidth، وإسناد عنوان للافتة lblInfo، وإسناد قيمة أيضاً لشريطي التمرير، وهي عمليات كان يمكن إنجازها أثناء طور التصميم (أي في مرحلة التمثيل المرئي).
ينفذ الإجراء hsbAspect_Change() عند تبديل موقع شريط التمرير نسبة القطرين:
Private Sub hsbAspect_Change()
Dim X, Y
Dim Info
X = frmEllipses.ScaleWidth / 2
Y = frmEllipses.ScaleHeight / 2
frmEllipses.Cls
frmEllipses.Circle (X, Y), hsbRadius.Value * 10, _
RGB(255, 0, 0), , , hsbAspect.Value / 10
Info = "نسبة القطرين: " + Str(hsbAspect.Value / 10)
frmEllipses.lblInfo.Caption = Info
End Sub
يحسب هذا الإجراء إحداثي مركز النموذج ويسندهما للمتحولين X,Y.
ينظف الإجراء سطح النموذج من أي قطوع مرسومة مسبقاً، مستخدماً الطريقة Cls، ثم يرسم القطع الناقص:
frmEllipses.Circle (X, Y), hsbRadius.Value * 10, _
RGB(255, 0, 0), , , hsbAspect.Value / 10
يُسند إلى الوسيط Radius (نصف القطر) القيمة الحالية لشريط التمرير نصف القطر مضروبة بـ 10، كما يُسند إلى الوسيط Aspect، عُشْر قيمة الخاصية Value لشريط التمرير نسبة القطرين.
لاحظ أننا لم نستخدم الوسيطين الاختياريين Start وEnd للطريقة Circle بعد، بل وضعنا مكانهما فاصلتين (أي فاصلتين بين الوسيط Color والوسيط Aspect)، تشير هاتان الفاصلتان لفيجول بيسك بأن الوسيطين الاختياريين غير مذكورين (مهملين).
يُنفذ هذا الإجراء آلياً، عند تبديل موقع مؤشر شريط التمرير نصف القطر (أي تحريك الزالقة)، يعتبر هذا الإجراء مشابهاً للإجراء hsbAspect_Change()، فيظهر القطع الناقص وتعدّل محتويات اللافتة lbllnfo.
لاحظ أن نص الإجراء hsbRadius_Scroll()، يستدعي الإجراء hsbRadius_Change()، كما أن نص الإجراء hsbAspect_Scroll() يستدعي بدوره الإجراء hsbAspect_Change()، (بمعنى أنك تنفذ الإجراءات المرافقة للحادثة تغيير Change عند حصول حادثة التمرير Scroll).
سنكتب الآن برنامج الأقواس Arcs، يوضح هذا البرنامج كيفية استخدام الطريقة Circle لرسم أقواس ذات نقاط بدء وانتهاء مختلفة. نذكرك الآن بالصيغة العامة الكاملة للطريقة Circle:
[object.]Circle [Step] ( X , Y ), _
radius , _
[color], _
[start], _
[ end ], _
[aspect]
يُحدد الوسيطان End, Start نقطتي البداية والنهاية لقوس الدائرة. فإذا كانت نقطة البداية تُساوي مثلاً الدرجة صفرْ، ونقطة النهاية تساوي الدرجة 45ْ، فهذا يعني أن هذا الجزء فقط من الدائرة هو الذي سيرسم. يوضح الشكل 8-18 جزء من دائرة (قوس) مرسوم بالطريقة Circle، نقطة بدايته الزاوية صفرْ ونقطة نهايته الزاوية 45ْ. كما يوضح الشكل 8-19 قوساً ذو نقطة بداية عند الدرجة 23ْ ونقطة نهاية عند الدرجة 180ْ.
|
|
الشكل 8-18 رسم قوس (0ْ-45ْ). |
|
|
الشكل 8-19 رسم قوس (23ْ-180ْ). |
سنصمم الآن نموذج برنامج الأقواس:
qأنشئ مشروعاً تنفيذياً قياسياً Standard EXE، ثم احفظ نموذج المشروع بالاسم Arcs.frm في الدليل C:\VB5Prg\Ch08، واحفظ ملف المشروع في ذات الدليل بالاسم Arc.Vbp.
qأنشئ النموذج frmArcs حسب الجدول 8-9.
يفترض أن يبدو النموذج المكتمل كما في الشكل 8-20.
|
|
الشكل 8-20 النموذج frmArcs. في مرحلة التصميم. |
الجدول 8-9. جدول خصائص النموذج frmArcs.
|
الكائن |
الخاصية |
القيمة |
|
Form |
Name |
frmArcs |
|
|
Caption |
برنامج الأقواس |
|
|
RightToLeft |
True |
|
CommandButton |
Name |
cmdExit |
|
|
Caption |
&خروج |
|
|
RightToLeft |
True |
|
Horizontal Scroll Bar |
Name |
hsbFrom |
|
|
Max |
360 |
|
|
Min |
0 |
|
|
Value |
0 |
|
Horizontal Scroll Bar |
Name |
hsbTo |
|
|
Max |
360 |
|
|
Min |
0 |
|
|
Value |
0 |
|
Vertical Scroll Bar |
Name |
vsbRadius |
|
|
Max |
100 |
|
|
Min |
1 |
|
|
Value |
1 |
|
Label |
Name |
lblFrom |
|
الكائن |
الخاصية |
القيمة |
|
|
Caption |
من الزاوية: |
|
|
RightToLeft |
True |
|
Label |
Name |
lblTo |
|
|
Caption |
إلى الزاوية: |
|
|
RightToLeft |
True |
|
Label |
Name |
lblRadius |
|
|
Caption |
نصف القطر: |
|
|
RightToLeft |
True |
سنبدأ الآن بكتابة نص برنامج الأقواس:
qتحقق بأن قسم التصاريح العامة للنموذج frmArcs يحوي العبارة Option Explicit.
' يجب التصريح عن كل المتحولات
Option Explicit
qأنشئ إجراءاً جديداً يدعى DrawArcs في قسم التصاريح العامة للنموذج frmArcs. (انقر نقرةً مزدوجة على النموذج لإظهار نافذة نص البرنامج ثم اختر Add Procedure من القائمة Tools، ثم اختر النوع Sub في الحقل Type لمربع الحوار Add Procedure، وعين المجال Public في الحقل Scope، ثم اكتب DrawArc في المربع Name، وأخيراً انقر الزر OK).
q أدخل النص التالي ضمن الإجراء DrawArc() الذي أنشأناه في الخطوة السابقة:
Public Sub DrawArc()
Dim x, y
Const pi = 3.14159265
x = frmArcs.ScaleWidth / 2
y = frmArcs.ScaleHeight / 2
frmArcs.Cls
Circle (x, y), vsbRadius.Value * 20, , _
hsbFrom * 2 * pi / 360, hsbTo * 2 * pi / 360
lblFrom.Caption = "من الزاوية: " + Str(hsbFrom.Value)
lblTo.Caption = "إلى الزاوية: " + Str(hsbTo.Value)
lblRadius.Caption = "نصف القطر:" + Str(vsbRadius.Value * 20)
End Sub
q أدخل النص التالي ضمن الإجراء cmdExit_Click() للنموذج frmArcs:
Privat sub cmdExit_Click()
End
End sub
q أدخل النص التالي ضمن الإجراء hsbFrom_Change() للنموذج frmArcs:
Privat sub hsbFrom_Change()
DrawArc
End sub
q أدخل النص التالي ضمن الإجراء hsbFrom_Scroll() للنموذج frmArcs:
Privat sub hsbFrom_Scroll()
hsbFrom_Change
End sub
q أدخل النص التالي ضمن الإجراء hsbTo_Change():
Privat sub hsbTo_Change()
DrawArc
End sub
q أدخل النص التالي ضمن الإجراءhsbTo_Scroll للنموذج frmArcs:
Private Sub hsbTo_Scroll()
hsbTo_Change
End Sub
q أدخل النص التالي ضمن الإجراء VsbRadius_Change للنموذج frmArcs:
Private Sub vsbRadius_Change()
DrawArc
End Sub
q أدخل النص التالي ضمن الإجراء VsbRadius_Scroll للنموذج frmArcs:
Private Sub vsbRadius_Scroll()
vsbRadius_Change
End Sub
q احفظ المشروع بالطريقة المعتادة.
لنشاهد برنامج الأقواس على أرض الواقع:
q نفّذ برنامج الأقواس.
qزد نصف القطر، بتحريك مؤشر شريط التمرير نصف القطر (شريط التمرير العمودي).
q زد قيمة شريط التمرير من زاوية (شريط التمرير الأفقي اليميني).
q زد قيمة شريط التمرير إلى زاوية (شريط التمرير الأفقي اليساري).
كما تلاحظ، يُرسم قوس يبدأ من النقطة المحددة بواسطة شريط التمرير من زاوية، وينتهي بالنقطة المحددة بشريط التمرير إلى زاوية.
يوضح الشكل 8-21 قوساً يبدأ من الدرجة 180ْ، وينتهي بالدرجة 23ْ.
|
|
الشكل 8-21 رسم قوس (180ْ-23ْ). |
q انقر الزر خروج لإنهاء البرنامج.
يَستخدم برنامج الأقواس الطريقة Circle لرسم الأقواس.
تُستخدم قيم الخاصية Value لكل من شريط التمرير نصف القطر وشريطي التمرير من زاوية و إلى زاوية كوسائط للطريقة Circle.
ينفذ الإجراء DrawArc() عند تغيير موقع مؤشر شريط التمرير نصف القطر، أو موقع مؤشر شريط التمرير من زاوية، أو عند تغيير موقع مؤشر شريط التمرير إلى زاوية.
يُعرّف هذا الإجراء قيمة الثابت pi (p)، ويُسند له القيمة العددية المكافئة:
CONST pi = 3.14159265
ثم يحسب إحداثيات مركز النموذج:
x = frmArcs.ScaleWidth / 2
y = frmArcs.ScaleHeight / 2
وينظف محتويات النموذج بعد ذلك بالطريقة Cls:
frmArcs.Cls
ثم يرسم القوس باستخدام الطريقة Circle:
Circle (x, y), vsbRadius.Value * 20, , _
hsbFrom * 2 * pi / 360, hsbTo * 2 * pi / 360
نكرر الصيغة الكاملة للطريقة Circle:
[Object].Circle [Step] (X,Y),Radius, _
[color],[Start],[End], [Aspect]
يتحدد مركز القوس في هذا الإجراء بالوسيطين X,Y، كما يتحدد نصف قطر القوس بقيمة الخاصية Value لشريط التمرير vsbRadius مضروبة بـ 20.
تُحدد قيمة الخاصية Min لشريط التمرير، أثناء مرحلة التصميم بالقيمة 1، كما حُددت الخاصية Max لهذا الشريط بالقيمة 100. مما يعني أن نقل مؤشر شريط التمرير من الموضع الأدنى Min إلى الموضع الأعلى Max، يستلزم النقر مائة مرة على أسهم الشريط.
تُضرب قيمة Value بالقيمة 20، ثم تُستخدم القيمة الناتجة للوسيط Radius (نصف القطر)، مما يعني أن نصف القطر يمكن أن يتخذ أي قيمة ما بين 20 و2000.
لم نستخدم في مثالنا هذا الوسيط Color، وإنما وضعنا فاصلة مكانه للإشارة إلى عدم استخدامه. يستخدم البرنامج في مثل هذه الحالة اللون المحدد بالخاصية ForeColor للنموذج، والذي يكون اللون الأسود في الحالة الافتراضية.
الوسيطان التاليان في الطريقة Circle هما: Start و End، ويجب تمرير قيمتهما بالراديان.
تم إسناد القيمة 1 للخاصية Min لشريطي التمرير من زاوية و إلى زاوية، وإسناد القيمة 360 للخاصية Max. مما يعني أن كلا الشريطين، مقسم إلى 360 جزء، يمثل كل جزء منها درجة واحدة، وتستخدم الصيغة التالية للتحويل من الدرجات إلى الراديان:
Radians = Degree * 2 * pi / 360
فمثلاً، الدرجة 360 تكافئ:
360 * 2 * pi / 360 = 6.2831853 Radians
وهذا ما يشرح السبب الذي دفع الإجراء DrawArc
إلى جداء قيمة الخاصية Value
للشريطين من زاوية (يمثل الوسيط Start)،
والشريط إلى زاوية (يمثل الوسيط End)
بالقيمة
.
لم يُستخدم الوسيط Aspect الاختياري هنا، وبما أن هذا الوسيط آخر وسيط Circle فلا توجد حاجة لوضع فاصلة بعد الوسيط End.
ملاحظة
يمكن الحصول على القيمة الحقيقة للثابت p، عن طريق العبارة التالية:
Dim pi As Double
pi = 4 * ATN(1)
آخر شيء ينجزه هذا الإجراء، هو إظهار المحتويات الجديدة للافتات: نصف القطر و من زاوية و إلى زاوية:
lblFrom.Caption = "من الزاوية: " + Str(hsbFrom.Value)
lblTo.Caption = "إلى الزاوية: " + Str(hsbTo.Value)
lblRadius.Caption = "نصف القطر:" + Str(vsbRadius.Value * 20)
تمكّنك هذه العبارات الثلاث من مشاهدة القيم الراهنة لأشرطة التمرير.
يُنفَذ هذا الإجراء آلياً، عند تغيير موقع مؤشر شريط التمرير من زاوية:
Private Sub hsbFrom_Change()
DrawArc
End Sub
يُنفذ هذا الإجراء DrawArc() الذي يرسم القوس، تبعاً للقيمة الجديدة لشريط التمرير من زاوية.
يُنفِذ كلا الإجرائين hsbTo_Change() وvsbRadius_Change() الإجراء DrawArc()، عند تغيير موقع مؤشر أحد الشريطين: إلى زاوية أو نصف القطر.
يسمح هذان الوسيطان باستخدام قيم سالبة. وعند تمرير قيم سالبة للوسيط Start، يرسم فيجول بيسك خطاً مستقيماً من مركز القوس إلى نقطة بداية القوس، كما أن تمرير قيم سالبة للوسيط End، تتسبب برسم خط مستقيم من مركز القوس إلى نقطة نهاية القوس. يوضح الشكل 8-22 قوساً يرسم بالعبارة التالية:
Circle (X,Y),1000, -25 * 2 * pi / 360, -45 * 2 * pi / 360
|
|
الشكل 8-22 رسم قوس (-25ْ, -45ْ). |
كما يبين الشكل 8-23 قوساً رسم بواسطة العبارة التالية:
Circle (X,Y),1000, -45 * 2 * pi / 360, -25 * 2 * pi / 360
|
|
الشكل 8-23 رسم قوس (-45ْ , -25ْ). |
ويوضح الشكل قوساً رسم بالعبارة التالية:
Circle (X,Y),1000, -45 * 2 * pi / 360, 25 * 2 * pi / 360
|
|
الشكل 8-24 رسم قوس (-45ْ , 25ْ). |
ويبين الشكل 8-25 قوساً رُسم بواسطة العبارة التالية:
Circle (X,Y),1000, 45 * 2 * pi / 360, -25 * 2 * pi / 360
|
|
الشكل 8-25 رسم قوس (45ْ , -25ْ). |
يُمكنك التمرين على استخدام الوسيطين Start و End للطريقة Circle، المستخدمة ضمن الإجراء DrawArc() كما يلي:
qغيّر الطريقة Circle في الإجراء DrawArc()، إلى العبارة التالية، كي تتمكن من رسم أقواس مشابهة لتلك المبين في الشكلين 8-22 و8-23:
Circle (X, Y),vsbRadius.Value * 20, _
-hsbFrom * 2* pi / 360, -hsbTo * 2 * pi / 360
qغيّر الطريقة Circle إلى العبارة التالية، حتى تتمكن من رسم أقواس مشابهة للمبينة في الشكل 8-24:
Circle (X, Y),vsbRadius.Value * 20, _
-hsbFrom * 2* pi / 360, hsbTo * 2 * pi / 360
q أما لرسم أقواس تشبه القوس المبينة في الشكل 8-25 فاستخدم العبارة التالية:
Circle (X, Y),vsbRadius.Value * 20, _
hsbFrom * 2* pi / 360, -hsbTo * 2 * pi / 360
تسمح هذه الخاصية بإعادة رسم محتويات الكائن الرسومية، في حال تم تغطية هذا الكائن بكائن آخر مثلاً. والقيمة الافتراضية لها تساوي False.
استخدم الخطوات التالية لرؤية تأثير الخاصية AutoRedraw:
q نفّذ برنامج الأقواس.
qارسم قوساً بتغيير مواقع مؤشرات أشرطة التمرير: من زاوية و إلى زاوية و نصف القطر.
qصغّر إطار برنامج الأقواس بنقر رمز إشارة الناقص، الذي يظهر عند الزاوية اليمنى العليا من إطار برنامج الأقواس.
يستجيب البرنامج بتصغير إطار برنامج الأقواس ويظهره كرمز في شريط المهام.
q استرجع إطار برنامج الأقواس إلى حجمه الطبيعي.
ستجد أن القوس المرسومة لم تظهر في الإطار، والسبب أن قيمة الخاصية AutoRedraw تساوي False.
qأنهِ البرنامج، ثم أسند القيمة True إلى الخاصية AutoRedraw، وكرر الخطوات السابقة.
ستلاحظ هذه المرة أن البرنامج أعاد رسم القوس آلياً، والسبب في ذلك، أن قيمة الخاصية AutoRedraw تساوي True هذه المرة.
تستطيع إظهار هذا الإجراء، بالنقر المزدوج على النموذج، والانتقال إلى إطار نص البرنامج، ثم اختيار Form من مربع السرد اليساري، واختيار Paint من مربع السرد اليميني.
استخدم هذا الإجراء لرسم خمسة خطوط أفقية كما يلي:
q أرجع الخاصية AutoRedraw إلى القيمة False مرة أخرى.
q أضف السطور التالية إلى الإجراء Form_Paint():
Private Sub Form_Paint()
frmArcs.Line (2000, 100)-(4000, 100)
frmArcs.Line (2000, 200)-(4000, 200)
frmArcs.Line (2000, 300)-(4000, 300)
frmArcs.Line (2000, 400)-(4000, 400)
frmArcs.Line (2000, 500)-(4000, 500)
End Sub
q احفظ المشروع باختيار Save Project من القائمة File في فيجول بيسك.
qنفّذ برنامج الأقواس، وشاهد الخطوط الأفقية الخمسة، وقد رسمت على سطح برنامج الأقواس.
q غطِ إطار برنامج الأقواس، بإطار تطبيق آخر، (المهم تغطية الخطوط الأفقية الخمس)، ثم ارفع إطار ذلك التطبيق عنه مرة ثانية.
كما تلاحظ، أُعيد رسم الخطوط مرة ثانية.
يُنفذ الإجراء Form_Paint()، كلما احتاج فيجول بيسك إلى إعادة رسم النموذج أو جزء منه، وبما أن فيجول بيسك يرسم النموذج عند بداية تشغيل البرنامج، فهذا يعني أن الإجراء Form_Paint() ينفذ آلياً عند بدء تشغيل البرنامج. كما يُنفذ فيجول بيسك هذا الإجراء كلما احتاج إلى إعادة رسم النموذج أو جزء منه كما ذكرنا سابقاً.
وبشكل عام، يمكنك الاستفادة من الإجراء Form_Paint()، مثل الاستفادة الحاصلة من إسناد True للخاصية AutoRedraw.
تمتاز الخاصية AutoRedraw بسهولة العمل، فلا حاجة عندها لكتابة نصوص برنامج لإعادة الرسم مرة أخرى. إلا أن سلبية الخاصية AutoRedraw في أنها تستهلك قدراً لا بأس به من الذاكرة، وتتسبب بفترات تأخير ملحوظة أثناء تنفيذ البرنامج، وخصوصاً على الأجهزة البطيئة نسبياً.