الخاصية :DrawMode
تعتبر الخاصي ة DrawMode من اقوى خصائص نافذة النموذج الرسومية، فعن طريقها
تحدد طريقة التفاعل بين الرسوم التي ترسمها بطرق الرسم –آ Line - مع النقاط
الموجودة على نافذة النموذج. القيمة الافتراضية لهذه الخاصية هي 13-Copy Pen
وتعني ان اللون سيظهر آما هو مطلوب، فالمربع الابيض سيكون ابيض ولو رسم
على مربع اسود، والدائرة الحمراء سترسم حمراء ولو على سطح ارجواني . الا انك
في بعض الحالات الفنية تود ان ترسم رسوم تتأثر بالالوان الموجودة على لوحة
الرسم وهذا مثال واقعي تجده آثيرا في برامج الترآيب شكل 2- 1:
تلاحظ في الشكل 2- 1 (ا) ان المستطيل الازرق الذي رسمناه على المنطقة
البيضاء قد رسم بشكل جيد جدا، ويظهر الفرق في الفن التصميمي واضحا بين
الشكلين (ب) و (ج)، ففي الشكل (ب) قمنا برسم المستطيل الازرق آما نريده
ازرق مما اثر وغطى على النص المكتوب "% 50 " ولن يتمكن المستخدم من رؤيته،
اما في الشكل (ج) فقد استخدمنا القيمة المناسبة للخاصية DrawMode بحيث
تقلب اللون الازرق الى ابيض في حالة الرسم فوق اللون الاسود . لمعرفة آيف تتم
عملية تغيير الالوان، عليك ان تعلم ان الالوان في حقيقتها م ا هي الا اعداد تتحول
بالنظام الثنائي الى ارقام شبيه ب 10011101010 ، اللون الذي تستخدمه يسمى
42
لون القلم Pen Color ، واللون الموجود على لوح او سطح الرسم يسمى Screen
Color ، فالقيمة 15-MergePen للخاصية DrawMode تقوم بتطبيق المعادلة التالية:
S = S Or P
فلو آان ا للون المستخدم هو 10101010 = 170 واللون الموجود على الشاشة هو
01010101 = 85 ، فان اللون الناتج –من تأثير القيمة 15-MergePen سيكون:
S = 01010101
P = 10101010
S = S Or P
S = 10101010 Or 01010101
S = 11111111
11111111 وهو 255 . اذا اردت معرفة جميع المعادلات الت ابعة للقيم الاخرى،
فمكتبة MSDN بها جدول جميل جدا تصل اليه بكتابة الجملة " DrawMode
Property " في الفهرس .Index
الخاصية :ScaleMode
في بداية الفصل وبالتحديد عند فقرة "خصائص الموقع والحجم " ذآرت ان الوحدة
المستخدمة لقياس احداثيات مواقع وطول وعرض الادوات هي الوح دة الموجودة
في الخاصية ScaleMode . توفر لك هذه الخاصية 8 قيم تمثل وحدات Units
تستخدم للقياس هي: 1-Twip والتي تعادل 0.567 سم، 2-Point تعادل 0.72
انش، 3-Pixel تعادل نقطة واحدة على الشاشة، 4-Character تعادل Twips 120
افقيا و Twips 240 عاموديا، 5-Inch تعادل انش واحد، 6-Milimeter تعادل ملم
واحد، 7-Centimeter تعادل واحد سم و 0-User وحدة قياس خاصة يتم تعريفها من
قبل المبرمج.
الخاصيتان Width و Height تعودان بعرض وارتفاع النافذة دائما بالوحدة ،Twip
فالقيمة التابعة للخاصية ScaleMode تؤثر على الوحدة المستخدمة في الادو ات
المحضونة فقط وليس الحاضنة، اما لمعرفة عرض وارتفاع نافذة النموذج بوحدة غير
ال Twip ، قم بتحديد الوحدة في الخاصية ScaleMode واستعلم عن العرض عن
طريق الخاصية ScaleWidth والارتفاع عن طريق الخاصية :ScaleHeight
Private Sub Form_Paint()
Cls
بالبكسل ‘ ScaleMode = vbPixels
Print ScaleHeight
43
Print ScaleWidth
End Sub
في الحقيقة، الخاصيتان ScaleWidth و ScaleHeight تعودان بعرض وارتفاع
المساحة الداخلية لنافذة النموذج، بينما تشمل الخاصيتان Width و Height
المساحة الداخلية والخارجية المتمثلة في سمك حدوده ا وارتفاع شريط عنوانه ا.
مع ذلك، لن تفرق آثيرا معك فنادرا ما تحتاج المساحة الخارجية للنافذة، على
العموم هذا الكود يطبع الفرق:
Private Sub Form_Paint()
Cls
ScaleMode = vbTwips
Print Height - ScaleHeight
Print Width - ScaleWidth
End Sub
اخيرا، القيمة 0-User هي وحدة تعرف من قبل المبرمج، تستطيع تعريف وحدة
خاصة بك عن طريق اسناد قيم الى الخصائص ،ScaleHeight ،ScaleWidth
ScaleLeft و ScaleTop . قد تحتاج تعريف وحدة قياس رسم خاصة بك في حالات
نادرة تعتمد على عرض المخططات الرسومية بشكل استثنائي.
طرق النموذج
بما ان الفقرة السابقة تحدثت عن وحدات القياس التابعة للخاصية ،ScaleMode
فسأبدأ بالتحدث عن الطرق ScaleX و ScaleY . هذه الطرق تمكنك من اجراء عملية
تحويل القياسات بين الوحدات السابقة افقيا وعامودي ا. ارسل القيمة ثم وحدتها
الاصلية ثم الوحدة المطلوبة:
التحويل من Pixels الى ‘ Twips
Print ScaleX(100, vbPixels, vbTwips)
الطريقة Show تؤدي الى اظهار النموذج والطريقة Hide تخفيه، نستطيع ان نقول
بكل ثقة انهما يمثلان الخاصية Visible ولكن على شكل طرق:
Form1.Show ‘ Form1.Visible = True
Form1.Hide ‘ Form1.Visible = False
44
طرق الرسم
الطريقة Cls تمسح جميع الرسوم الموجودة على النافذة وتصفر الاحداثيات
CurrentX و CurrentY الى الاحداثي ( 0 , 0)، والطريقة Point تعود بالقيمة العددية
للون الموجود في الاحداثي ( x, y ) على النافذة:
Private Sub Form_Load()
تحميل صورة وجهي الوسيم! '
Form1.Picture = LoadPicture (“C:\Turki.BMP”)
End Sub
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
Label1.BackColor = Point(X, Y)
Label1.Caption = Hex$(Point(X, Y))
End Sub
الطريقة PSet تمكنك من رسم نقطة على النافذة بارسال الاحداثي ( X, Y ) للنقطة،
سيكون لون النقطة هو نفس اللون الموجود في الخاصية ForeColor او بامكانك
ارسال اللون:
Me.ForeColor = vbBlack
نقطة سوداء ‘ ( 0 , PSet (0
نقطة حمراء ‘ PSet (500, 500), vbRed
الطريقة PSet –وطرق الرسم الاخرى - تدعم الكلمة المحجوزة Step والتي تضيف
الاحداثيات المرسلة ( X, Y ) الى الاحداثيات الحالية –الموجودة في الخاصيتان
CurrentX و :CurrentY
Private Sub Form_Paint()
Dim X As Integer
Cls
Me.CurrentX = 0
Me.CurrentY = 0
For X = 0 To 100
45
PSet Step(5, 5)
Next
End Sub
الطريقة Line تمكنك من رسم الخطوط بارسال احداثيات البداية ( X1, Y1 ) والنهاية
:(X2, Y2)
ForeColor = vbGreen
خط اخضر ‘ ( Me.Line (0, 0) - (Me.ScaleWidth, Me.ScaleHeight
خط احمر ‘ Me.Line (0, Me.ScaleHeight) - (Me.ScaleWidth, 0), vbRed
في حالة تجاهلك للاحداثي ( X1, Y1 ) فان القيم الحالية للخصائص CurrentX و
CurrentY هي نقطة البداية:
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
Me.Line - (X, Y)
End Sub
الطريقة Line تمكنك من رسم المستطيلات عوضا عن الخطوط بارسال الحرف B
مع العلم ان النقش سيكون النقش المحدد في الخاصية FillStyle واللون :FillColor
ForeColor = vbWhite
مربع ابيض ‘ Line (0, 0) - (200, 200), , B
مربع ازرق ‘ Line – Step (200, 200), vbBlue, B
ولتلوين المربع مباشرة –دون استخدام الخصائص، ارسل الحرفين :BF
ForeColor = vbWhite
مربع ابيض ‘ Line (0, 0) - (200, 200), , BF
مربع ازرق ‘ Line – Step (200, 200), vbBlue, BF
واختم فقرة طرق الرسم بالطريقة Cirlce التي من الواضح انها لا ترسم نجوم ! وانما
دوائر بارسال احداثي نقطة مرآز الدائرة ومن ثم طول قطرها:
46
ForeColor = vbWhite
دائرة بيضاء ‘ 500 ,( Circle (Me.ScaleWidth / 2, Me.ScaleHeight / 2
دائرة خضراء ‘ Circle (Me.ScaleWidth / 2, Me.ScaleHeight / 2), 200, vbGreen
عملية تلوين الدائرة لا تتم باستخدام BF آما في الطريقة BF ، وانما بالقيمة
الموجودة في الخاصية FillColor مع النقش .FillStyle
من الاشياء التي تعجبني في الطريقة Cirlce هي امكانية رسم الاقواس بتحديد
زاوية النهاية والبداية بوحدة الراديان :Radian
Const PI = 3.14
نصف دائرة فتحهتها الى الاعلى ‘
Circle (Me.ScaleWidth / 2, Me.ScaleHeight / 2), 1000, , 0, PI
نصف دائرة فتحهتها الى الاسفل ‘
Circle (Me.ScaleWidth / 2, Me.ScaleHeight / 2), 800, , PI, 0
ربع دائرة ‘
Circle (Me.ScaleWidth / 2, Me.ScaleHeight / 2), 500, , 0, PI / 2
من الاشياء التي تزيد من قوة الطريقة Circle هي امكا نية ايصال اطراف الاقواس
بمرآز الدائرة وتلوين جزء معين آما يحدث مع المخططات Charts ، ولعمل ذلك
يشترط استخدام القيم السالبة:
Const PI = 3.14
FillStyle = 0
FillColor = vbBlue
Circle (Me.ScaleWidth / 2, Me.ScaleHeight / 2), 1000, , - (PI), - (PI / 2)
ولرسم الق طع المكافئ Ellipse ، استخدم المتغير لوضع النسبة Ratio بين القطر
العمودي والافقي:
القطر العمودي يعادل ضعف القطر الافقي ‘
Circle (Me.ScaleWidth / 2, Me.ScaleHeight / 2), 1000, , , , 2
اما الطريقة PaintPicture فهي اقوى طرق الرسم والتي ظهرت منذ الاصدار ،VB5
الغرض من هذه الطريقة هو رسم صور تابعة للكائن او الخاصية Picture وتطلب منك
10 متغيرات ! لا تخف وتتجنب استخدامها لكثرة المتغيرات، فالمطلوبة هي الثلاث
الاولى اما الباقية فهي اختيارية، بالنسبة للمتغيرات فالأول هو آائن الصورة، والاربع
47
التالية تحدد بها المنطقة التي سترسم الصورة عليها، والاربعة التالية تحدد
المنطقة التي تريد رسمها فعلا من الصورة الاصلية، والمتغير الاخير يحدد اسلوب
رسم الصورة على الهدف، وهو يتطابق تماماً مع ما اوضحته سابقاً حول خاصية
.DrawMode
تمكنك الطريقة PaintPicture من فعل اشياء آثيرة على الصور، آ قلبها، عكس
الوانها، تمديدها، تحريكها .... الخ، تجد في ملف الكتاب Codes.ZIP مثال يعرض لك
تطبيقات عملية على الطريقة PaintPicture وهذا الجزء الاساسي منه:
Private Sub Form_Paint()
Cls
PaintPicture Picture1.Picture, 0, 0, lWidth1, _
lHeight1, lX2, lY2, lWidth2, lHeight2, iDrawMode
End Sub
ومازال Print موجود
مازال Visual Basic محتفظا بسمات لغة BASIC القديمة، فالامر Print لا يزال
موجود منذ منتصف الستينات حتى الاصدار VB6 . ليس هذا فقط، بل مازالت الصيغ
القديمة آالفواصل المنقوطة ";" والعادية مدعومة في :Visual Basic
"عادية" ,"فاصلة" Print
"منقوطة" ;"فاصلة" Print
ملاحظة: رغم ان Print مصنف ضمن طرق الكائنات، الا انه –تقني ا- لا يعتبر
طريقة. فهو حالة خاصة تعمدها مطوروا Visual Basic حتى تتزامن
التوافيقية مع لغة .BASIC
نوع وحجم الخط الناتج من الامر Print ، هو نفس القيم الموجودة في الخاصية
Font . الدوال TextHeight و TextWidth تفيدان لمعرفة ارتفاع وعرض النص وتختلف
باختلاف نوع وحجم الخط لتتمكن من اختيار الاحداثي المناسب لبدء الكتابة آما
في الكود التالي الذي يكتب النص في وسط النافذة:
Dim sText As String
Font.Size = 20
"ترآي العسيري" = sText
CurrentX = (ScaleWidth - TextWidth(sText)) / 2
CurrentY = (ScaleHeight - TextHeight(sText)) / 2
48
Print sText
اخيرا، جميع المخرجات النصية عبارة عن نقاط تتشكل في صورة حالها آحال طرق
الرسم، والخاصية Image هي المسئولة عن حفظ المعلومات ا لكاملة لهذه
المخرجات.
احداث النموذج
نافذة النموذج هي اآثر آائن من آائنات Visual Basic يحتوي على احداث، معظم
احداثها تم شرحها في فقرة "الاحداث المشترآة ". اما الاحداث الخاصة بها فتفجر
من بداية تحميل النافذة حتى اغلاقها بهذا الترتيب:
<- (Deactivate) <- Paint <- Activate <- Resize <- Load <- Initialize
.Terminate <- Unload <- QueryUnload
ملاحظة: بالنسبة للحدث Deactivate فلا يتم تفجيره بعد الحدث Paint الا
في حالة قيام المستخدم بتحديد نافذة اخرى في نفس البرنامج،
واذا عاد المستخدم الى النافذة الاولى، فان السلسة السابقة تبدأ
من الحدث ... <- Paint <- Activate
الحدث :Initialize
يتم تفجير هذا الحدث بمجرد استخدام آائن النموذج في اآوادك او انشاء نسخة
جديدة من آائن النموذج، يقوم Visual Basic بتفجير هذا الحدث مبكرا جدا أي قبل
انشاء نافذة النموذج ووضع الادوات عليها:
يتم تفجير الحدث Initialize التابع لنموذج ‘ Form2
Dim X As Form2
Set X = New Form2
قد تستفيد من هذا الحدث لتعيين قيم ابتدائية للمتغيرات التابعة لنافذة النموذج
قبل انشاء النافذة:
Dim sUserName As String
Private Sub Form_Initialize()
"مستخدم جديد" = sUserName
49
End Sub
الحدث :Load
يتم تفجير الحدث Load بمجرد البدء في عملية تحميل النافذة باستخدام الدالة
:Load
Load Form2
او حتى عند قيامك باستخدام احد خصائصها او استدعاء طرقها:
يتم تفجير الحدث Load التابع لنموذج ‘ Form2
قبل تعديل قيمة الخاصية ‘ Caption
”النافذة الثانية“ = Form2.Caption
من الضروري معرفة ان الحدث Load لا يتسبب في ظهور النافذة فهو يقع عند
تحميل وانشاء النافذة فقط، فلا تحاول استخدام الاوامر التابعة للواجهة آ
SetFocus او طرق الرسم .... الخ. قد تستفيد من هذا الحدث بوضع قيم ابتدائية
آ:
Private Sub Form_Load()
Text1.Text = sUserName
End Sub
الحدث :Resize
بمجرد ان تظهر نافذة النموذج، فان الحدث Resize يتم تفجيره او آلما قام
المستخديم بتحجيم النافذة وتغيير حجمها، قد تستخدم هذا الحدث بكثرة عند
رغبتك في محاذاة الادوات او تغيير حجمها آلما قام المتسخدم بتغيير حجم النافذة:
Private Sub Form_Resize()
توسيط الاداة على النافذة '
Command1.Move (Me.ScaleWidth - Command1.Width) / 2, _
(Me.ScaleHeight - Command1.Height) / 2
End Sub
50
الحدث :Activate
يتم تفجير الحدث بمجرد ظهور النافذة –بعد الحدث Resize - او بمجرد آون النافذة
هي النافذة النشطة Active Window . مع ذلك، لن يتم تفجير الحدث اذا انتقل
المستخدم من برنامج آخر الى برنامجك، أي أن هذا الحدث لا يتم تفجيره إلا عند
التنقل بين نوافذ برنامجك فقط . قد يفيدك هذا الحدث في تغيير محتويات النافذة –
آتجديث البيان ات- بمجرد قيام المستخدم بتغيير محتويات نافذة اخرى في نفس
البرنامج:
Private Sub Form_Activate()
Label1.Caption = Form2.Text1.Text
End Sub
الحدث :Paint
يتم تفجير هذا الحدث آلما دعت الحاجة الى اعادة رسم النافذة، فلو قمت بوضع
النافذة س فوق النافذة ص ومن ث م تعود الى النافذة س، فان الحدث Paint له
نصيب من الوقوع، آذلك عندما تخفي اجزاء من النافذة ومن ثم تظهرها سيتم
تفجير الحدث . من الضروري جدا جدا اخبارك بانه في حالة آون قيمة الخاصية
AutoRedraw تساوي True فان الحدث Paint لن يتم تفجيره حتى تحج البقرة
على قرونه ا! افضل اآواد يمكنك وضعها بين سطور هذا الحدث هي اآواد الرسم،
الكود التالي يرسم دائرة تغطي معظم اجزاء النافذة:
Private Sub Form_Paint()
Cls
FillStyle = 0
Circle (ScaleWidth / 2, ScaleHeight / 2), _
IIf(ScaleWidth < ScaleHeight, ScaleWidth, ScaleHeight) / 2, 0
End Sub
من المفيد ان اذآر هنا بان تغيير حجم النافذة يؤدي الى تفجير الحدث Paint في
حالة ان قام المستخدم بتكبير الحجم، اما عند تصغير الحجم فان الحدث Paint لا
يتم تفجيره، وذلك لانه لا توجد حاجة لاعادة رسم اجزاء من النافذة، فقد تلاحظ في
الكود السابق انك اذا قمت بتصغيير حجم النافذة، فان الدائرة لن يتم اعادة رسمها،
والفكرة الذآية التي قد تجبر Visual Basic لاعادة رسم الدائرة هي طريق الحدث
:Resize
51
Private Sub Form_Resize()
Form_Paint
End Sub
رغم ان الكود السابق صحيح، الا انه لا يخرج من اصابع م برمج حريف، والسبب ان
الحدث Paint سيتم تنفيذه مرتين آلما قام المستخدم بتكبيير حجم النافذة،
فالأولى بسبب اعادة الرسم والثانية بسبب الاستدعاء الموجود في الحدث
Resize ، لذلك تجد ان المبرمج الذآي لا يستدعي الحدث Fomr_Paint مباشرة بل
يترك الامر ل Visual Basic ليفعله عند وقت الحاجة باستخدام الطريقة :Refresh
Private Sub Form_Resize()
Me.Refresh
End Sub
بعد الحدث التلقائي الاخير Paint تكون نافذة النموذج جاهزة لاستقبال الاحداث
الخاصة لباقي الادوات او احداثها الاخرى آ Click وغيرها، اما في حالة عدم وجود
أي اداة قابلة لاستقبال الترآيز، فان الحدث GotFocus الخاص بنافذة النموذج سيتم
تفجيره فورا.
الحدث :Deactivate
هو عكس الحدث Activate ويتم تفجيره بمجرد ان ينتقل الترآيز الى نافذة اخرى
تابعة لبرنامجك فقط . قد ينفذ هذا الحدث ايضا في حالة الاخفاء المؤقت للنافذة
باستخدام الطريقة Hide او تعديل قيمة الخاصية Visible الى .False
الحدث :QueryUnload
يتم تنفيذ الحدث QueryUnload عندما تكون النافذة على وشك الازالة النهائية من
الذاآرة –وليس الاخفاء المؤقت . يمكنك هذا الحدث من الاستعلام عن الطريقة التي
تسببت في اغلاق النافذة عن طريق المتغير المرسل UnloadMode . المزيد ايضا،
تستطيع الغاء فكرة اغلاق النافذة عن طريق اسناد القيمة True الى المتغير
المرسل Cancel ، فالكود التالي لن يمكن المستخدم من اغلاق النافذة باستخدام
صندوق التحكم Control Box او الزر اغلاق " X" الموجود في اعلى النافذة:
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
If UnloadMode = vbFormControlMenu Then
Cancel = True
52
End If
End Sub
طرق الاستعلام الاخرى عن قيم المتغير UnloadMode موجودة في تعليمات
.MSDN
الحدث :Unload
ان لم تقم بالغاء عمل ية اغلاق النافذة في الحدث السابق، فان الحدث Unload هو
الحدث التالي، معطيك فرصة اخيرة لالغاء عملية اغلاق النافذة عن طريق نفس
المتغير المرسل Cancel ، اما بالنسبة للمتغير UnloadMode فهو غير موجود.
الحدث :Terminate
يتم تفجير هذا الحدث بمجرد موت آائن النموذج، م وضوع موت الكائنات هو احد
فقرات الفصل الخامس "البرمجة آائنية التوجه ."OOP
القوائم Menus
يمكنك Visual Basic من تصميم قائمة Menu لنوافذ النماذج وقت التصميم عن
طريق صندوق الحوار محرر النماذج Menu Editor ، حدد نافذة النموذج ثم اختر الامر
Menu Editor… من قائمة Tools . واذا آنت تعاني من آثرة اعادة تكرار تعبئة
محتويات القوائم، تستطيع استخدام قوالب القوائب Template Menu عن طريق
الاضافة Add-In مدير القوالب .VB6 Template Manager
مبدئيا، آل وحدة من وحدات القائمة تحتوي على الخاصية Caption التي تمثل
النص الظاهر على القائم ة، استخدم الرمز "&" لوضع خط تحت الحرف الذي يليه
حتى تمكن المستخدم من الوصول الى الامر في القائمة بالضغط على المفتاح Alt
والحرف الذي يلي الرمز، واذا آانت قيمة الخاصية Caption الرمز "-" فقط، فان
القائمة ستكون عبارة عن خط فاصل . اما الخاصية Name تمثل الاسم الب رمجي
للقائمة والذي تنطبق عليه نفس شروط الادوات في التسيمة، فالقائمة ماهي الا
أداة لكن من نوع خاص، فبامكانك آتابة اآواد تعدل في خصائص القائمة وقت
التنفيذ:
”&ملف“ = mnuFile.Caption
mnuEdit.Enabled = False
53
آما ان الخصائص Visible و Enabled موجودة في القوائم وتؤثر حتى في القوائم
الفرعية التابعة له ا. والخاصية Checked تحدد ما اذا آنت تريد وضع علامة اختيار
بجانب عنوان القائمة . اما الخاصية WindowList فهي تمكن القائمة من عرض
جميع النوافذ المحضونة في النافذة من النوع .MDI
القوائم المنبثقة :Pop-Up Menus
اذا نقرت بزر الفأرة الايمن على أي آائن، فان قائمة صغيرة ستظهر لك . هذه
القائمة تسمى Pop-Up Menu . تستطيع تطبيقها في Visual Basic عن طريق
الامر PopupMenu مع تحديد القائمة التي تود عرضها:
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
If Button And vbRightButton Then
PopupMenu mnuView
End If
End Sub
آما يمكنك عرض قائمة تابعة لنافذة نموذج اخرى:
PopupMenu frmMain.mnuHelp
تقبلوا تحياتي