الجمعة، 8 يوليو 2011


Private Sub Form_Load()
gRecordLen = Len(gPerson)
gFileNum = FreeFile
Open "PHONE.DAT" For Random As gFileNum Len = gRecordLen
gCurrentRecord = 1
gLastRecord = FileLen("PHONE.DAT") / gRecordLen
If gLastRecord = 0 Then
gLastRecord = 1
End If
ShowCurrentRecord
End Sub
أدخل النص التالي ضمن الإجراء cmdNew_Click():
Private Sub cmdNew_Click()
SaveCurrentRecord
gLastRecord = gLastRecord + 1
gPerson.Name = ""
gPerson.Phone = ""
gPerson.comments = ""
Put #gFileNum, gLastRecord, gPerson
gCurrentRecord = gLastRecord
ShowCurrentRecord
txtName.SetFocus
End Sub
أدخل النص التالي ضمن الإجراء cmdNext_Click():

Private Sub cmdNext_Click()
If gCurrentRecord = gLastRecord Then
Beep
MsgBox "end of File!", vbExclamation
Else
SaveCurrentRecord
gCurrentRecord = gCurrentRecord + 1
ShowCurrentRecord
End If
txtName.SetFocus
End Sub
أدخل النص التالي ضمن الإجراء cmdPrevious_Click():
Private Sub cmdPrevious_Click()
If gCurrentRecord = 1 Then
Beep
MsgBox "Beginning of file!", vbExclamation
Else
SaveCurrentRecord
gCurrentRecord = gCurrentRecord - 1
ShowCurrentRecord
End If
txtName.SetFocus
End Sub
أدخل النص التالي ضمن الإجراء cmdExit_Click():
Private Sub cmdExit_Click()
SaveCurrentRecord
Close #gFileNum
End
End Sub
تنفيذ برنامج الهاتف
لنشاهد نتيجة ما كتبناه:
نفّذ برنامج الهاتف.
لاحظ المظاهر التالية أثناء تشغيل برنامج الهاتف.
عند تنفيذ البرنامج للمرة الأولى، لا تكون هناك بيانات، ويظهر سجل فارغ على الشاشة، وهو السجل1/1، حسب ما يشار إليه بواسطة عنوان إطار البرنامج. يمكّنك البرنامج من إدخال اسم الشخص ورقم هاتفه وملاحظات حوله، (انظر الشكل 14-3) تستطع الانتقال من حقل لآخر باستخدام الفأرة أو بواسطة المفتاح Tab.
انقر الزر جديد لإضافة سجل جديد.
يظهر سجل فارغ. ويُظهر عنوان البرنامج، رقم السجل الجديد وعدد السجلات الإجمالي (انظر الشكل14-4).
حالما يصبح لديك عدة سجلات تستطيع الانتقال من سجل لآخر، باستخدام زري الأمر التالي و السابق. فنقر الزر التالي ينقلك إلى السجل التالي، وعلى العكس يؤدي نقر الزر السابق إلى الرجوع بك إلى السجل السابق.
الفصل الخامس عشر




المصفوفات، ربط وإدراج كائن ومواضيع أخرى




سنتعلم في هذا الفصل بعض المواضيع المتنوعة في فيجول يبسك، والتي لم تغطها الفصول السابقة.
الملفات من النوع آسكي ASCII
ربما يحتاج المرء عند تطوير البرامج إلى طباعة نسخة مطابقة عن جدول خصائص النموذج ونص البرنامج، يحفظ فيجول بيسك جدول خصائص النموذج، ونص البرنامج، في ملف النموذج. فمثلاً، يحتوي الملف MYFORM.FRM على جدول خصائص النموذج FrmMyForm، ونصوص برنامجه أيضاً.
لنلقِ نظرة على الملف OPTION.FRM الذي طورناه في الفصل*الثاني "الخصائص وعناصر التحكم والكائنات".
شغّل محرر نصوص ما، له القدرة على تحميل ملفات من نوع ASCII (مثل المفكرة Notepad أو الدفتر Word Pad).
افترضنا عبر المناقشة التالية أننا استخدمنا المفكرة، كمحرر للنصوص (تستطيع استخدام برنامج Word إن شئت، لتحميل الملفات النصية).
اختر فتح من قائمة ملف للمفكرة، وحمل الملف C:\VB5Prg\Ch02\OPTION.FRM.
يُفترض أن يظهر الملف OPTION.FRM بشكل مشابه لما يلي:
VERSION 5.00
Begin VB.Form frmOption
BackColor = &H000000FF&
Caption = برنامج الخيارات""
ClientHeight = 4350
ClientLeft = 2400
ClientTop = 1620
ClientWidth = 4455
LinkTopic = "Form1"
RightToLeft = -1 'True
ScaleHeight = 4350
ScaleWidth = 4455
Begin VB.CommandButton cmdExit
Caption = خروج"&"
Height = 495
Left = 1560
RightToLeft = -1 'True
TabIndex = 6
Top = 3720
Width = 1215
End
Begin VB.OptionButton optLevel3
Alignment = 1 'Right Justify
BackColor = &H000000FF&
Caption = "المستوى &3"
BeginProperty Font
Name = "MS Sans Serif"
Size = 9.75
Charset = 178
Weight = 400
Underline = 0 'False
Italic = 0 'False
Strikethrough = 0 'False
EndProperty
ForeColor = &H00FFFFFF&
Height = 385
Left = 600
RightToLeft = -1 'True
TabIndex = 5
Top = 1680
Width = 1215
End
Begin VB.OptionButton optLevel2
Alignment = 1 'Right Justify
BackColor = &H000000FF&
Caption = "المستوى &2"
BeginProperty Font
Name = "MS Sans Serif"
Size = 9.75
Charset = 178
Weight = 400
Underline = 0 'False
Italic = 0 'False
Strikethrough = 0 'False
EndProperty
ForeColor = &H00FFFFFF&
Height = 385
Left = 600
RightToLeft = -1 'True
TabIndex = 4
Top = 960
Width = 1215
End
Begin VB.OptionButton optLevel1
Alignment = 1 'Right Justify
BackColor = &H000000FF&
Caption = "المستوى &1"
BeginProperty Font
Name = "MS Sans Serif"
Size = 9.75
Charset = 178
Weight = 400
Underline = 0 'False
Italic = 0 'False
Strikethrough = 0 'False
EndProperty
ForeColor = &H00FFFFFF&
Height = 385
Left = 600
RightToLeft = -1 'True
TabIndex = 3
Top = 240
Width = 1215
End
Begin VB.CheckBox chkColors
Alignment = 1 'Right Justify
BackColor = &H000000FF&
Caption = "الأ&لوان"
ForeColor = &H00FFFFFF&
Height = 385
Left = 2640
RightToLeft = -1 'True
TabIndex = 2
Top = 1680
Width = 1215
End
Begin VB.CheckBox chkMouse
Alignment = 1 'Right Justify
BackColor = &H000000FF&
Caption = "ال&فأرة"
BeginProperty Font
Name = "MS Sans Serif"
Size = 9.75
Charset = 178
Weight = 400
Underline = 0 'False
Italic = 0 'False
Strikethrough = 0 'False
EndProperty
ForeColor = &H00FFFFFF&
Height = 385
Left = 2640
RightToLeft = -1 'True
TabIndex = 1
Top = 960
Width = 1215
End
Begin VB.CheckBox chkSound
Alignment = 1 'Right Justify
BackColor = &H000000FF&
Caption = "أ&صوات"
BeginProperty Font
Name = "MS Sans Serif"
Size = 9.75
Charset = 178
Weight = 400
Underline = 0 'False
Italic = 0 'False
Strikethrough = 0 'False
EndProperty
ForeColor = &H00FFFFFF&
Height = 385
Left = 2640
RightToLeft = -1 'True
TabIndex = 0
Top = 240
Width = 1215
End
Begin VB.Label lblChoice
Alignment = 1 'Right Justify
BorderStyle = 1 'Fixed Single
BeginProperty Font
Name = "MS Sans Serif"
Size = 9.75
Charset = 178
Weight = 400
Underline = 0 'False
Italic = 0 'False
Strikethrough = 0 'False
EndProperty
ForeColor = &H00000080&
Height = 1335
Left = 600
RightToLeft = -1 'True
TabIndex = 7
Top = 2160
Width = 3255
End
End
Attribute VB_Name = "frmOption"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_Exposed = False
Option Explicit
Private Sub chkColors_Click()
Updatelabel
End Sub
Private Sub chkMouse_Click()
Updatelabel
End Sub
Private Sub chkSound_Click()
Updatelabel
End Sub
Private Sub cmdExit_Click()
End
End Sub
Private Sub optLevel1_Click()
Updatelabel
End Sub
Private Sub optLevel2_Click()
Updatelabel
End Sub
Private Sub OptLevel3_Click()
Updatelabel
End Sub
Public Sub Updatelabel()
Dim Info
Dim LFCR
LFCR = Chr(13) + Chr(10)
' الصوت
If chkSound.Value = 1 Then
Info = "الصوت: تشغيل"
Else
Info = "الصوت: إيقاف"
End If
' الفأرة
If chkMouse.Value = 1 Then
Info = Info + LFCR + "الفأرة: تشغيل"
Else
Info = Info + LFCR + "الفأرة: إيقاف"
End If
' الألوان
If chkColors.Value = 1 Then
Info = Info + LFCR + "الألوان: تشغيل"
Else
Info = Info + LFCR + "الألوان: إيقاف"
End If
' المستوى 1
If optLevel1.Value = True Then
Info = Info + LFCR + "المستوى: 1"
End If
'level 2
If optLevel2.Value = True Then
Info = Info + LFCR + "المستوى: 2"
End If
If optLevel3.Value = True Then
Info = Info + LFCR + "المستوى: 3"
End If
lblChoice.Caption = Info
End Sub
كما تلاحظ، فإن الملف OPTION.FRM عبارة عن ملف آسكي ASCII نظامي (أي ملف نصي عادي). يبين السطر الأول في الملف النصي OPTION.FRM رقم إصدار فيجول بيسك المستخدم لتوليد الملف: Version 5.00، تصف السطور التي تلي هذا السطر، النموذج وعناصر التحكم الموجودة عليه (أي بمعنى آخر، جدول خصائص النموذج). أما الأسطر التي تلي جدول خصائص النموذج، فتمثل نص البرنامج.
يعتبر فهم صيغة الملفات النصية (ملفات ASCII) هام جداً للمبرمجين الذين يرغبون بكتابة برامج تولد ملفات ASCII آلياً، (كأن تكتب برنامجاً يسأل المستخدم بضعة أسئلة، وبناء على أجوبة المستخدم، يولّد البرنامج الملف ASCII للنموذج). لا يمتلك فيجول بيسك أي طريقة تمكّنه من معرفة من أين جاء الملف ASCII، لهذا يجب أن يكون الملف مسايراً بإحكام للصيغة التي يتوقعها فيجول بيسك.
المصفوفات
يتوجب على البرامج التصريح عن المصفوفات إذا أردت استخدامها. يحدّد التصريح عن المصفوفة، اسم المصفوفة وعدد البنود التي يمكنها الاحتفاظ بها. كما أن التصريح عن مصفوفة ضمن قسم التصاريح العامة يجعلها مرئية لكل إجراءات وتوابع النموذج. بينما تكون المصفوفة مرئية لكل نماذج المشروع إذا تم التصريح عنها في وحدة نمطية مستقلة (Module BAS)، وأسبقنا عبارة التصريح بالكلمة المحجوزة Global.
أنواع البيانات Data Type
يدعم فيجول بيسك أنواعاً عديدة من البيانات، يستعرض الجدول 15-1 شتى أنواع البيانات ومجالات قيم البيانات المتوفرة في فيجول بيسك.
لنأخذ مثلاً العبارة التالية للتصريح عن متحول بأنه من النوع الصحيح:
Dim Counter As Integer
وهي تقابل العبارة التالية (أي تكافئ) العبارة السابقة:
Dim Counter%
يعتبر الرمز % التمثيل المختصر للعبارة As Integer، يأخذ المتحول من النوع الصحيح، قيمة ما من ضمن المجال –32768 وحتى 32768. تشغل كل قيمة صحيحة 2 Byte (بايتين) من الذاكرة.
بشكل مشابه، يمكننا التصريح عن متحول بأنه صحيح طويل كما يلي:
Dim Number As Long
تعطي العبارة التالية شكلاً آخر للتصريح عن المتحول Number بأنه من النوع الطويل:
Dim Number&
الرمز & هو التمثيل المختصر للعبارة As Long. يأخذ المتحول من النوع الصحيح الطويل، أي قيمة من ضمن المجال –2,147,483,648 وحتى 2,147,483,648. يشغل كل متحول طويل 4 Byte (4 يايتات) من الذاكرة.
يصرح عن المتحول المضاعف الدقة بشكل مشابه لما يلي:
Dim MyVariable As Double
أو يمكن اختصار التصريح السابق بالشكل التالي:
Dim MyVariable#
المتحول المضاعف الدقة، قد يكون رقماً موجباً أو سالباً ويشغل 8 Byte من الذاكرة.
يوضح الجدول 15-1 مجالات القيم السالبة والموجبة لكل أنواع البيانات في فيجول*بيسك.
الجدول 15-1. أنواع البيانات التي يدعمها فيجول بيسك.
نوع البيانات البايتات المطلوبة المجال الاختصار
Integer 2 بايت -32.768 إلى 32.767 %
Long 4 بايت -2.147.483.648 إلى 2.147.483.647 &
Single-positive 4 بايت 45-E1.401298 إلى 38E3.402823 !
Single-negative 4 بايت 38E3.402823- إلى 45-E1.401298- !
Double-positive 8 بايت 24-D4.94065645841247 إلى 308D1.79769313486232 #
Double-negative 8 بايت 308D1.79769313486232- إلى 24-D4.94065645841247- #
Currency 8 بايت 922337203685477,5808- إلى 922337203685477,5807 @
String يعتمد على عدد الأحرف من صفر إلى حوالي 2 بليون حرف $
Date 8 بايت 1/جونيه/100 إلى 31/ديسمبر/9999
Variant يعتمد على نوع البيانات التي يخزنها
لاحظ أن آخر عنصر في الجدول 15-1 يصف نوع متحول غريب بعض الشيء، وهو النوع Variant، يمكن أن يشير هذا النوع إلى تاريخ أو وقت أو سلسلة كتابية أو متحول ذي فاصلة عائمة (مثلاً 1234.567. فمثلاً عند التصريح عن متحول I بالشكل:
Dim I As Integer
يُشكّل فيجول بيسك متحولاً يدعى I من نوع صحيح، أما عند التصريح عن متحول I بالشكل:
Dim I
فسوف يشكل فيجول بيسك المتحول I من نوع متغير (Variant)،أي أن فيجول بيسك لا يعلم بماذا سوف يستخدم المتحول I، هل هو سلسلة أم متحول صحيح، أم متحول طويل، أم أي نوع آخر. سيتمكن فيجول بيسك فيما بعد من تحديد نوع المتحول بالنظر إلى العبارة التي تستخدمه. فمثلاً: يدرك فيجول بيسك لدى استخدامه العبارة التالية:
I = "My String"
أن المتحول يجب معالجته كسلسلة كتابية، أما إذا صادف فيجول بيسك العبارة التالية:
I = 2 + 3
فسيدرك عندها أن المتحول يجب معالجته كمتحول من نوع صحيح Integer.
ميزة استخدام متحولات متغيرة (Variant) أنه بإمكان نفس المتحول الخدمة بعدة أنواع معطيات. فمثلاً، لا مانع من ورود العبارات التالية في نفس الإجراء:
Dim I
I = 2 + 3
I = "My String"
يلعب المتحول I هنا دور متحول صحيح، ومتحول من نوع كتابي (سلسلة) في نفس الوقت.
أما عيب استخدام نوع البيانات Variant، فهي التسبب فى بطيء عمل البرنامج، نسبة إلى البرامج التي تحدد بدقة نوع المتحولات التي تستخدمها.
فمثلاً، تُنفّذ حلقة For أسرع، عندما يصرّح عن متحول عداد الحلقة، بأنه من النوع الصحيح. طبعاً قد يكون متحول عداد الحلقة من نوع طويل، إذا كانت الحلقة ستتكرر أكثر من 32767 مرة، وعند ذلك ستدور الحلقة بشكل أبطأ مما هي عليه، عندما يكون عداد الحلقة من نوع صحيح.
يمكنك استخدام متحول من النوع المتغير Variant كعداد لحلقة For. إلا أن الحلقة ستدور بشكل أبطأ، مما لو كان المتحول من النوع الصحيح Integer أو الطويل Long. يمكن استخدام عبارة مشابهة لما يلي للتصريح عن عداد حلقة من نوع متغير:
Dim HisVariant
أو تستطيع استخدام عبارة أكثر وضوحاً:
Dim HisVariant As Variant
برنامج المصفوفات
يوضح برنامج المصفوفات كيفية التصريح عن المصفوفات في فيجول بيسك.
التمثيل المرئي للبرنامج المصفوفات
أنشئ الدليل C:\VB5Prg\Ch15. سنستخدم هذا الدليل لحفظ العمل المنجز.
افتح مشروعاً جديداً واحفظ نموذج المشروع بالاسم ARRAYS.FRM في الدليل C:\VB5Prg\Ch15، واحفظ ملف المشروع بالاسم ARRAYS.VBP في ذات الدليل.
أنشئ النموذج طبقاً للجدول 15-2. النموذج المكتمل سيبدوكما في الشكل15-1.
الشكل 15-1 النموذج frmArrays.


الجدول 15-2. جدول خصائص النموذج FrmArrays
الكائن الخاصية القيمة
Form Name frmArrays
Caption برنامج المصفوفات
RightToLeft True
CommandButton Name cmdArray1
Caption مصفوفة &1
RightToLeft True
CommandButton Name cmdArray2
Caption مصفوفة &2
RightToLeft True
CommandButton Name cmdExit
Caption &خروج
RightToLeft True
إدخال نص برنامج المصفوفات
سنبدأ بكتابة نص برنامج المصفوفات:
أدخل النص التالي في قسم التصاريح العامة للنموذج frmArrays:
يجب التصريح عن كل المتحولات
Option Explicit
أدخل النص التالي ضمن الإجراء cmdArray1_Click() للنموذج frmArrays:
Private Sub cmdArray2_Click()
Dim COUNTER
Static array1(1 To 10) As String
array1(1) = "ABC"
array1(2) = "DEF"
array1(3) = "GHI"
frmARRAYs.Cls
Print "":بنود المصفوفة الأولى هي
For COUNTER = 1 To 3 Step 1
Print "Array1(" + Str(COUNTER) + ")=" + array1(COUNTER)
Next
End Sub
أدخل النص التالي ضمن الإجراء cmdArray2_Click() للنموذج frmArrays:
Private Sub cmdArray2_Click()
Dim COUNTER
gArray2(11) = 234
gArray2(12) = 567
gArray2(13) = 890
frmARRAYs.Cls
Print "":بنود المصفوفة الثانية هي
For COUNTER = 11 To 13 Step 1
Print "gArray2(" + Str(COUNTER) + ")="_ +
Str (gArray2(COUNTER))
Next
End Sub
أدخل النص التالي ضمن الإجراء cmdExit_Click() للنموذج frmArrays:
Private Sub cmdExit_Click()
End
End Sub
تنفيذ برنامج المصفوفات
نفّذ برنامج المصفوفات.
انقر الزر مصفوفة1.
يستجيب برنامج المصفوفات، بإظهار بنود المصفوفة الأولى. (انظر الشكل 15-2).
انقر الزر مصفوفة2.
يستجيب برنامج المصفوفات، بإظهار بنود المصفوفة الثانية.
انقر الزر خروج لإنهاء برنامج المصفوفات.
الشكل 15-2 إظهار بنود Array1().

الشكل 15-3 إظهار بنود Array2().
كيف يعمل برنامج المصفوفات
يُصرّح برنامج المصفوفات عن مصفوفتين أحاديتين Array1() و Array2(). يملأ البرنامج أول ثلاثة بنود من المصفوفة Array1() عند نقر الزر مصفوفة1، ويُظهر هذه البنود الثلاثة.
ويملأ البرنامج أيضاً ثلاث بنود من المصفوفة الأحادية Array2()، ويُظهرها عند نقر الزر مصفوفة2.
نص قسم التصاريح العامة
يصرّح في هذا القسم عن المصفوفة الأحادية gArray2():
Dim gArray2(10 to 20) As Integer
هذه المصفوفة من النوع الصحيح (As Integer)، مما يعني أن بنودها من النوع الصحيح.
الرقمين ضمن القوسين الهلاليين، يدلان أن أول بند في هذه المصفوفة هو gArray2(10)، وبالتالي فالبند الثاني هو gArray2(11)، والثالث هو gArray2(12)…الخ. أما آخر بند فهو gArray2(20).
يعني التصريح عن مصفوفة ضمن قسم التصاريح العامة، أنها مرئية لكافة إجراءات وتوابع النموذج.
نص الإجراء cmdArray1_Click()
يُنفّذ هذا الإجراء آلياً عند نقر الزر مصفوفة1:
Private Sub cmdArray1_Click()
Dim COUNTER
Static array1(1 To 10) As String
array1(1) = "ABC"
array1(2) = "DEF"
array1(3) = "GHI"
frmARRAYs.Cls
Print "":بنود المصفوفة الأولى هي
For COUNTER = 1 To 3 Step 1
Print "Array1(" + Str(COUNTER) + ")=" + array1(COUNTER)
Next
End Sub
يصرّح هذا الإجراء عن المصفوفة Array1() بالشكل التالي:
Static Array1(1 to 10) As String
لاحظ أنه يجب استخدام كلمة Static، قبل اسم المصفوفة عند التصريح عنها في قسم التصاريح العامة، أو يصرّح عنها كمصفوفة ساكنة Static ضمن إجراء.
البند الأول في المصفوفة هو Array1(1)، والبند الثاني هو Array1(2) وهكذا، آخر بند في المصفوفة هو Array1(10).
يملأ الإجراء بعد ذلك ثلاثة بنود في المصفوفة، وينظّف النموذج بواسطة الطريقة Cls:
Array1(1)= "ABC"
Array1(2)= "DEF"
Array1(3)= "GHI"
frmArrays.Cls
وأخيراً يُظهِر الإجراء، أول ثلاثة بنود من المصفوفة باستخدام حلقة For:
Print "":بنود المصفوفة الأولى هي
For COUNTER = 1 To 3 Step 1
Print "Array1(" + Str(COUNTER) + ")=" + array1(COUNTER)
Next
نص الإجراء cmdArray2_Clck()
يُنفّذ هذا الإجراء عند نقر الزر مصفوفة2:
Private Sub cmdArray2_Click()
Dim COUNTER
gArray2(11) = 234
gArray2(12) = 567
gArray2(13) = 890
frmARRAYs.Cls
Print "":بنود المصفوفة الثانية هي
For COUNTER = 11 To 13 Step 1
Print "gArray2(" + Str(COUNTER) + ")="_ +
Str (gArray2(COUNTER))
Next
End Sub
يشبه هذا الإجراء سابقه. لكنه يستعمل المصفوفة Array2() بدون أن يصرّح عنها، لأنها مصفوفة عامة لكل الإجراءات، (وذلك بسبب التصريح عنها في قسم التصاريح العامة).
النهايتان العليا والسفلى للمصفوفة
يتحدد البندان الأول و الأخير في المصفوفة حسب ما أوضحه برنامجنا المصفوفات من التصريح عن المصفوفة. فمثلاً: تصرّح العبارة التالية عن مصفوفة من الأرقام من النوع طويل:
Dim MyArray(0 to 35) As Long
البند الأول (النهاية السفلى) هو MyArray(0)، والبند الأخير هو MyArray(35).
نستطيع اختصار التصريح السابق بالعبارة التالية:
Dim MyArray(35) As Long
تفسر العبارة من قبل فيجول بيسك بالشكل التالي: البند الأول في المصفوفة هو MyArray(0)، والبند الثاني هو MyArray(1)…الخ، وآخر بند في المصفوفة هو MyArray(35). عيب استخدام الشكل المختصر للتصريح، أن القيمة الافتراضية للنهاية السفلى هي "الصفر" دوماً، أي ينبغي عليك أن تتذكر دائماً أن البند الأول، هو البند ذي الترتيب "صفر"، بينما البند ذي الترتيب 1 هو البند الثاني وهكذا.
حجم المصفوفة
يتحدد أقصى حجم يمكن أن تصله المصفوفة (الحجم الأعظم) تبعاً لنظام التشغيل، فحسب ما تعلم، يستخدم ويندوز ما يدعى بالذاكرة الوهمية أو الافتراضية Virtual Memory. فعندما تستخدم كل الذاكرة RAM المتاحة، يبدأ ويندوز باستخدام القرص الصلب، وكأنه امتداد للذاكرة RAM. عند ذلك يدعى هذا الجزء من القرص الصلب والمستخدم كذاكرة RAM بالذاكرة الوهمية Virtual Memory.
لنفترض مثلاً أن الحاسب PC يملك ذاكرة RAM بحجم 16 ميجا بايت، وأنه استهلكها كلها، يشرع ويندوز باستخدام حيّز من القرص الصلب كذاكرة RAM، وطبعاً لاشك أن هناك فارق كبير في سرعة القراءة من الذاكرة RAM الفعلية وبين الذاكرة الوهمية، فقراءة البيانات من القرص الصلب تكون أبطأ كثيراً من قراءة البيانات من الذاكرة RAM.
لهذا يجب أن تعلم أن ويندوز سيلجأ إلى استخدام القرص الصلب لدى استعمالك لمصفوفات كبيرة تستهلك الذاكرة*RAM المتاحة، مما سيتسبب بتدني سرعة عمل البرنامج، وسيعاني برنامجك من مشاكل في الأداء عند استهلاك كامل الذاكرة RAM المتاحة.
المصفوفات متعددة الأبعاد
استخدم برنامج المصفوفات مصفوفة ذات بعد وحيد، تستطيع في فيجول بيسك التصريح عن مصفوفات متعددة الأبعاد، فمثلاً تصرّح العبارة التالية عن مصفوفة ذات بعدين (ثنائية البعد):
Static MyArray(0 to 3, 1 to 4)
يمكن سرد بنود هذه المصفوفة بالشكل التالي:
MyArray(0,1) MyArray(0,2) MyArray(0,3) MyArray(0,4)
MyArray(1,1) MyArray(1,2) MyArray(1,3) MyArray(1,4)
MyArray(2,1) MyArray(2,2) MyArray(2,3) MyArray(2,4)
MyArray(3,1) MyArray(3,2) MyArray(3,3) MyArray(3,4)
تستطيع بشكل مشابه، التصريح عن مصفوفة ثلاثية الأبعاد كما يلي:
Dim MyArray(1 to 3, 1 to 7, 1 to 5)
يستخدم نص التصريح التالي حلقتي For لملء بنود مصفوفة ثنائية البعد بالقيمة 3:
Static MyArray ( 1 To 10, 1 To 10)
Dim COUNTER1, COUNTER2
For COUNTER1 = 1 To 10
For COUNTER2 = 1 To 10
MyArray(Counter1, Counter2) = 3
Next Counter2
Next Counter1
المصفوفات الديناميكية
ينبغي الانتباه إلى موضوع الذاكرة عند التصريح عن المصفوفات. فمثلاً، تصرح العبارة التالية عن مصفوفة ذات 10001 بند:
Static MyArray(10000) As long
كل بند في هذه المصفوفة من النوع Long (طويل)، وبالتالي يشغل 4 Byte، وهذه المصفوفة سوف تشغل 40,004 بايتاً من الذاكرة. لعل هذا القدر ليس بالشيء الكثير، لكن ماذا لو كان لدينا عشر مصفوفات مثل هذه المصفوفة في برنامجنا، ستستهلك المصفوفات العشرة هذه 400,040 بايت من الذاكرة.! لهذا حاول دائماً حجز أقل قدر ممكن للمصفوفة في البرنامج.
لكن هناك ملاحظة أخرى، فبعض المصفوفات يتحدد حجمها فقط أثناء زمن التنفيذ، يمكن في هذه الحالة استخدام العبارة ReDim (إعادة الحجز).
تدعى المصفوفة التي تغير حجمها أثناء زمن التنفيذ بالمصفوفة الديناميكية Dynamic Array.
يوضح جزء البرنامج التالي طريقة إعادة حجز مصفوفة:
Private Sub Command1_Click()
Dim Counter
Dim Array1() As Integer
ReDim Array1(1 To 15) As Integer
For Counter = 1 To 15 Step1
Array1(Counter) = Counter
Next Counter
ReDim Array1(1 To 15) As Integer
يصرّح الإجراء عن Array1() كمصفوفة ديناميكية، لاحظ الاختلاف بين التصريح عن المصفوفة الثابتة وبين المصفوفة الديناميكية.
العبارة التالية والتي استخدمناها في النص السابق تعين حجم المصفوفة باستخدام العبارة ReDim:
ReDim Array1(1 to 15) As Integer
هذه العبارة تحدد حجم المصفوفة بـ 15 بنداً، وكل بند من بنودها ينتمي إلى النوع الصحيح.
تملأ الحلقة For بنود المصفوفة الخمسة عشر، ثم تستخدم عبارة ReDim مجدداً لإعادة حجز المصفوفة:
ReDim Array1(1 to 5) As Integer
بعد تنفيذ العبارة ReDim يكون حجم المصفوفة الثانية فقط خمسة بنود. وهكذا يمكنك استخدام هذه التقنية لتبديل حجم مصفوفاتك أثناء زمن التنفيذ، والحفاظ على أكبر قدر حر من ذاكرة الحاسب. تطلبت Array1() في النص السابق (2×15=30 بايت)، وبعد تنفيذ العبارة ReDim الثانية، يتبدّل حجم Array1() إلى خمسة بنود من النوع الصحيح وبالتالي إلى 10 بايت فقط.
ما يهمنا معرفته، أنه في حال تنفيذ عبارة ReDim، تصبح القيم التي كانت مخزنة في المصفوفة مفقودة إلى الأبد.! فإذا أردت المحافظة على بعض قيم المصفوفة لا بد لك من استخدام الكلمة المحجوزة Preserve، يوضح برنامج المصفوفات2 كيفية إنجاز ذلك.
برنامج المصفوفات2
يوضح هذا البرنامج، كيف تتمكن من إعادة حجز المصفوفات، ضمن برامج فيجول بيسك.
التمثيل المرئي لبرنامج المصفوفات2
سنبدأ بتمثيل برنامج المصفوفات2:
أنشئ مشروعاً جديداً من نوع Standard EXE، واحفظ النموذج الجديد بالاسم ARRAYS2.FRM في الدليل C:\VB5Prg\Ch15، واحفظ ملف المشروع بالاسم ARRAYS2.VBP في الدليل C:\VB5Prg\Ch15.
أنشئ النموذج frmArray طبقاً للمواصفات المبينة في الجدول 15-3. يُفترض أن يبدو النموذج المكتمل كما في الشكل 15-4.
الشكل 15-4 النموذج frmArray لبرنامج المصفوفات2.

الجدول 15-3. جدول خصائص النموذج FrmArray.
الكائن الخاصية القيمة
Form Name frmArray
Caption برنامج المصفوفات2
RightToLeft True
CommandButton Name cmdFill10
Caption ا&ملء 10 بنود
RightToLeft True
CommandButton Name cmdOnly5
Caption اختصر البنود إلى 5
RightToLeft True
CommandButton Name cmdExit
Caption &خروج
RightToLeft True
ComboBox Name cboElements
Text (اجعله فارغاً)
Style 0-Drop Down Combo
إدخال نص برنامج المصفوفات2
أدخل النص التالي في قسم التصاريح العامة للنموذج frmArray:
'يجب التصريح عن كل المتحولات
Option Explicit
Dim gTheArray() As Integer
أدخل النص التالي ضمن الإجراء cmdExit_Click() للنموذج frmArray:
Private Sub cmdExit_Click()
End
End Sub
أدخل النص التالي ضمن الإجراء cmdFill10_Click() للنموذج frmArray:
Private Sub cmdFill10_Click()
ReDim gTheArray(1 To 10) As Integer
Dim Counter
For Counter = 1 To 10
gTheArray(Counter) = Counter
Next

cboElements.Clear
For Counter = 0 To 9
cboElements.AddItem Str(gTheArray(Counter + 1))
Next
End Sub
أدخل النص التالي ضمن الإجراء cmdOnly5_Click() للنموذج frmArray:
Private Sub cmdOnly5_Click()
ReDim Preserve gTheArray(1 To 5) As Integer
Dim Counter
cboElements.Clear
For Counter = 0 To 4
cboElements.AddItem Str(gTheArray(Counter + 1))
Next
End Sub
تنفيذ برنامج المصفوفات2
نفّذ برنامج المصفوفات2.
انقر الزر املأ 10 بنود.
يستجيب برنامج المصفوفات2، بملء مربع التحرير والسرد بعشرة بنود. وتستطيع رؤية هذه البنود بنقر رأس السهم النازل لمربع التحرير والسرد لاستعراض لائحة البنود (انظر الشكل 15-5).
انقر الزر اختصر البنود إلى 5
يستجيب برنامج المصفوفات2، بإزالة خمس بنود من مربع التحرير والسرد. يمكنك مشاهدة البنود الخمسة الباقية بنقر رأس السهم النازل لمربع التحرير والسرد لمشاهدة لائحة البنود. (انظر الشكل 15-6).
الشكل 15-5 ملء مربع التحرير والسرد بعشرة بنود.

الشكل 15-6 الإبقاء على خمسة بنود فقط من المصفوفة.
انقر الزر خروج لإنهاء البرنامج.
كيف يعمل برنامج المصفوفات2
يملأ برنامج المصفوفات2 مصفوفة ما، ويملأ بعدها مربع التحرير والسرد ببنود هذه المصفوفة، يُعاد حجز المصفوفة باستخدام الكلمة المحجوزة Preserve والتي تحافظ على قيم البنود المتبقية في المصفوفة.
نص التصاريح العامة
يصرّح في هذا القسم عن مصفوفة ديناميكية:
Dim gTheArray() As Integer
طبعاً يفهم فيجول بيسك من هذه العبارة، أن المصفوفة ديناميكية وذلك لأن القوسين الهلاليين وراء الاسم فارغان.
نص الإجراء cmdFill10_Click()
يُنفّذ هذا الإجراء آلياً، عند نقر الزر املء 10 بنود:
Private Sub cmdFill10_Click()
ReDim gTheArray(1 To 10) As Integer
Dim Counter
For Counter = 1 To 10
gTheArray(Counter) = Counter
Next

cboElements.Clear
For Counter = 0 To 9
cboElements.AddItem Str(gTheArray(Counter + 1))
Next
End Sub
يستخدم الإجراء العبارة ReDim لتحديد حجم المصفوفة بعشرة بنود:
ReDim gTheArray(1 to 10) As Integer
تُستخدم حلقة For لملء بنود المصفوفة:
For Counter = 1 To 10
gTheArray(Counter) = Counter
Next
تُمحى بنود مربع التحرير والسرد، ثم تُستخدم حلقة For لملئه بعشرة بنود، وهذه البنود تتوافق مع بنود المصفوفة (أي يتقابل كل بند من المصفوفة، مع بند من مربع التحرير والسرد):
cboElements.Clear
For Counter = 0 To 9
cboElements.AddItem Str(gTheArray(Counter + 1))
Next
لاحظ أن أول بند في مربع التحرير والسرد هو البند ذو الرقم "صفر"، أما أول بند في المصفوفة فرقمه "1"، كذلك آخر بند في مربع التحرير والسرد هو البند رقم "4"، أما آخر بند في المصفوفة فرقمه "10".
نص الإجراء cmdOnly5_Click()
يُنفذ هذا الإجراء آلياً، عند نقر الزر اختصر البنود إلى 5:
Private Sub cmdOnly5_Click()
ReDim Preserve gTheArray(1 To 5) As Integer
Dim Counter
cboElements.Clear
For Counter = 0 To 4
cboElements.AddItem Str(gTheArray(Counter + 1))
Next
End Sub
يستخدم الإجراء عبارة ReDim لتغيير حجم المصفوفة إلى خمسة بنود:
ReDim Preserve gTheArray(1 to 5) As Integer
تتسبب الكلمة المحجوزة Preserve بالإبقاء على قيم أول خمسة بنود من المصفوفة على حالها (أي تحتفظ البنود بقيمها الأصلية). يمحو الإجراء بعدها بنود مربع التحرير والسرد ويملؤه بخمسة بنود:
cboElements.Clear
For Counter = 0 To 9
cboElements.AddItem Str(gTheArray(Counter + 1))
Next
اتبع الخطوات التالية لرؤية دور الكلمة المحجوزة Preserve:
احذف الكلمة المحجوزة Preserve من العبارة ReDim لتصبح العبارة بالشكل التالي:
ReDim gTheArray(1 to 5) As Integer
نفّذ برنامج المصفوفات2، ثم انقر الزر املء 10 بنود، وافتح مربع التحرير والسرد، وتأكد من امتلائه بعشر بنود
انقر بعد ذلك الزر اختصر البنود إلى 5 وافتح مربع التحرير والسرد، وتأكد أن اللائحة مملوءة بخمسة بنود، ستجد أن قيم هذه البنود الخمس مساوية كلها إلى الصفر، وذلك بسبب حذف الكلمة المحجوزة Preserve.
انقر الزر خروج لإنهاء برنامج المصفوفات2.
المصفوفات التي يزيد حجمها عن 64KB
يمكن لحجم المصفوفة أن يتجاوز 64KB، والمصفوفة التي تتجاوز 64KB تدعى بالمصفوفة الضخمة Huge Array، ليس هنالك تصريح خاص للمصفوفات الضخمة، فهذه المصفوفات عادية، لكن هناك استثناء وحيد، فإذا كانت المصفوفة الضخمة من نوع String، (أي من نوع نصي)، فيجب أن تكون كل بنودها تحمل نفس العدد من الرموز.
برنامج المغيّر
تستطيع كما تعلم، استخدام الخيار Add Procedure من القائمة Tools لبناء إجراءات أو توابع وظيفية خاصة بك، وتمتلك هذه الإجراءات أو التوابع وسائط (معاملات) Parameters خاصة بها، وتسمى هذه الوسائط في أدبيات البرمجة، بالمتغيرات الوسيطية Arguments.
هناك طريقتان لتمرير الوسائط Parameters إلى تابع وظيفي في فيجول بيسك:
طريقة القيمة الراجعة By Reference. (تمرير عنوان المتحول في الذاكرة).
طريقة القيمة الغير راجعة By Value. (تمرير نسخة عن قيمة المتحول).
يوضح برنامج المغيّر الاختلاف بين الطريقتين.
التمثيل المرئي لبرنامج المغيّر
أنشئ مشروعا جديداً من النوع Standard EXE واحفظ نموذج المشروع بالاسم Vary.FRM في الدليل C:\VB5Prg\Ch15 واحفظ ملف المشروع بالاسم VARY.VBP في ذات الدليل.
أنشئ النموذج frmVary طبقاً للجدول 15-4.
يفترض أن يظهر النموذج المكتمل كما في الشكل 15-7.
الشكل 15-7 النموذج frmVary.
الجدول 15-4. جدول خصائص النموذج frmVary.
الكائن الخاصية القيمة
Form Name frmVary
Caption برنامج المغيّر
RightToLeft True
CommandButton Name cmdDoIt
Caption اضغط هنا
RightToLeft True
CommandButton Name cmdExit
Caption &خروج
RightToLeft True
Label Name lblInfo
Caption (اجعله فارغاً)
Alignment 2-Center
BorderStyle 1-Fixed Single
تأكد من أن قسم التصريحات العامة يحوي العبارة Option Explicit:
'يجب التصريح عن كل المتحولات
Option Explicit
أدخل النص التالي ضمن الإجراء cmdDoIt_Click() للنموذج frmVary:
Private Sub cmdDoIt_Click()
Dim V As Integer
Dim Result As Integer
V = 3
Result = VSquare(V)
lblInfo.Caption = "V = " + Str(V) + " 4*4=" + Str(Result)
End Sub
أدخل النص التالي ضمن الإجراء cmdExit_Click() للنموذج frmVary:
Private Sub cmdExit_Click()
End
End Sub
أنشئ تابعاً وظيفياً جديداً في النموذج frmVary وأطلق عليه التسمية VSquare. وذلك بإظهار نافذة نص البرنامج، واختيار Add Procedure من القائمة Tools، ثم تحديد النوع Type على أنه Function، وتحديد الاسم Name بأنه VSquare ثم نقر OK.
يستجيب فيجول بيسك بإضافة التابع الوظيفي VSquare().
غيّر أول سطر بحيث يصبح كما يلي:
Public Function VSquare(ByVal V As Integer)

End Function
والآن أدخل النص التالي ضمن التابع الوظيفي VSquare():
Public Function VSquare(ByVal V As Integer)
V = 4
VSquare = V * V
End Function
تنفيذ برنامج المغير
نفّذ برنامج المغيّر.
انقر الزر اضغط هنا.
يستجيب البرنامج بإظهار القيمة في اللافتة lblInfo كما هو مبين في الشكل 15-8.
انقر الزر خروج لإنهاء البرنامج.
الشكل 15-8 برنامج المغيّر عند تمرير المتحول V إلى التابع الوظيفي VSquare().
كيف يعمل برنامج المغيّر
يمرّر البرنامج متحولاً إلى التابع الوظيفي VSquare() بطريقة القيمة غير الراجعة ByVal، ولذلك لا تتغير قيمة المتحول V من الرقم 3 إلى الرقم 4، كما سترى لاحقاً.
نص الإجراء cmdDoIt_Click()
يُنفّذ هذا الإجراء آلياً، عند نقر الزر اضغط هنا:
Private Sub cmdDoIt_Click()
Dim V As Integer
Dim Result As Integer
V = 3
Result = VSquare(V)
lblInfo.Caption = "V = " + Str(V) + " 4*4=" + Str(Result)
End Sub
يُسند الإجراء القيمة 3 إلى المتحول V، ثم يُنفذ التابع الوظيفي VSquare()، ويُعيد ناتج ضرب (4×4). يُظهر الإجراء بعد ذلك، قيمة المتحول V والقيمة المعادة من التابع الوظيفي VSquare() في اللافتة lblInfo.
نص التابع الوظيفي VSquare()
يُستدعى التابع الوظيفي VSquare() من قبل الإجراء cmdDoIt_Click():
Public Function VSquare(ByVal V As Integer)
V = 4
VSquare = V * V
End Function
يُسند التابع القيمة 4 إلى المتحول V، ثم يُسند القيمة V×V إلى متحول التابع الوظيفي VSquare، الشيء الذي نحب التنبيه إليه، أن المتحول V قد تم تمريره إلى التابع الوظيفي بطريقة القيمة غير الراجعة ByVal، بمعنى أن الإجراء يُنشئ نسخة جديدة عن المتحول المدعو V، ثم يتعامل معه. ولا توجد صلة بين المتحول V في الإجراء طالب الاستدعاء (أي cmdDoIt_Click() في مثالنا هذا)، وبين المتحول V في التابع الوظيفي VSquare().
وهذا يشرح السبب الذي دفعنا إلى إسناد القيمة 3 إلى المتحول V وليس القيمة 4. (انظر إلى الشكل 15-. فقيمة المتحول الممرر بطريقة القيمة غير الراجعة ByVal. لا تتغير في البرنامج طالب الاستدعاء.
تعديل برنامج المغيّر
سنعدّل الآن برنامج المغيّر، بحيث يبدو كالتالي (لاحظ التعديل في أول سطر من التابع الوظيفي):
Public Function VSquare(V As Integer)
V = 4
VSquare = V * V
End Function
نفّذ برنامج المغيّر، وانقر الزر اضغط هنا.
يستجيب البرنامج بإظهار القيم في اللافتة lblInfo حسب ما يتبين من الشكل 15-9.
الشكل 15-9 برنامج المغيّر لدى تمرير المتحول V بطريقة القيمة الراجعة (ByRef).
لاحظ أن المتحول V الآن، لم يمرر بطريقة القيمة غير الراجعة، إلى التابع الوظيفي VSquare()، بل تم تمريره بطريقة القيمة الراجعة، أي أن المتحول الممرر، هو نفس المتحول في الإجراء طالب الاستدعاء، والتابع الوظيفي المستدعى. وهكذا فعند تمرير المتحول V بطريقة القيمة الراجعة، فهذا يعني أن المتحول V في الإجراء cmdDoIt_Click()، هو نفسه في التابع الوظيفي VSquare()، وهذا يشرح سبب ظهور قيمة V في اللافتة lblInfo يحمل القيمة 4 (انظر إلى الشكل 15-9).
يتمكّن المبرمجون بلغة C، من التمييز بين تمرير الوسائط بطريقة القيمة غير الراجعة، وبطريقة القيمة الراجعة، بشكل أكبر، لأنهم يتمكنون من تمييز أن تمرير وسيط بطريقة القيمة الراجعة، يكافئ تمرير عنوان المتحول في الذاكرة. يكفينا هنا أن تلاحظ الفرق بين الطريقتين:
عندما يتم تمرير الوسيط بطريقة القيمة غير الراجعة (ByVal). لا يتمكن التابع الوظيفي المستدعى، من تغيير قيمة الوسيط الممرر في الإجراء الطالب للاستدعاء، (لأنه لا يعرف عنوانه في الذاكرة)، فمثلاً رغم أن التابع VSquare()، يُسند القيمة 4 إلى V، في برنامج المغيّر، إلا أن الإجراء cmdDoIt_Click() يحافظ على قيمة V تساوي 3.
عندما يتم تمرير الوسيط بطريقة القيمة الراجعة (ByRef). يستخدم كل من الإجراء الطالب للاستدعاء والتابع الوظيفي المستدعى نفس المتحول، (لأن الإجراءين يعرفان عنوان المتحول في الذاكرة)، فمثلاً أدى إسناد القيمة 4 إلى V ضمن التابع الوظيفي VSquare() في النسخة المعدّلة من برنامج المغيّر، إلى تعديل قيمة V في الإجراء cmdDoIt_Click()، فظهرت V تساوي 4 في اللافتة lblInfo.
تعديل برنامج المغيّر مجدداً
لنمضي أكثر في تعديل برنامج المغيّر:
غيّر VSquare() ليصبح كالتالي:
Public Function VSquare(VV As Integer)
VV = 4
VSquare = VV * VV
End Function
نفّذ برنامج المغيّر وانقر الزر اضغط هنا.
يستجيب برنامج المغيّر مجدداً كما في الشكل 15-9.
كما تلاحظ، لم يؤثر التغيير في اسم المتحول ضمن VSquare() من V إلى VV على طريقة عمل البرنامج وذلك بسبب تمرير المتحول بطريقة القيمة الراجعة.! وهكذا فرغم أن المتحول يدعى VV ضمن VSquare()، لكنه يبقى نفس المتحول الممرر من قبل الإجراء طالب الاستدعاء (أي أن V و VV هما نفس المتحول).
ملاحظة
انظر الشكل 15-10 لفهم مضمون طريقة تمرير المتحولات بالقيمة الراجعة بشكل أعمق.
حسب الشكل، توجد خلايا من الذاكرة RAM مستخدمة لحفظ المتحول V الخاص بالإجراء cmdDoIt_Click()، يمرر الإجراء cmdDoIt_Click() المتحول V إلى التابع VSquare() بطريقة القيمة الراجعة، ولهذا يستخدم VSquare() بدوره نفس المتحول باستخدام نفس الخلايا في الذاكرة RAM.
إذاً يستخدم cmdDoIt_Click() منطقة من الذاكرة RAM لحفظ المتحول V، ويستخدم VSquare() بدوره نفس المنطقة من الذاكرة RAM لحفظ المتحول VV، وفي كلتا الحالتين فإن V و VV هما نفس المتحول.

الشكل 15-10 تمرير المتحولات بطريقة القيمة الراجعة.
ربط وإدراج الكائن OLE
يُعتبر موضوع ربط وإدراج الكائن Object Linking and Embedding من مواضيع ويندوز الهامة التي يدعمها فيجول بيسك، وطبعاً تحتاج تغطية هذا الموضوع بشكل مفصل إلى كتاب كامل.
تعتبر خاصية OLE من القوة بحيث يمكن التفكير بها كبرمجة كاملة مستقلة، مدمجة ضمن فيجول بيسك، يعطي ما تبقى من هذا الفصل مقدمة مختصرة عن OLE.
تعريف OLE.؟
هذا المصطلح (OLE) مأخوذ من حروف أولى كلمات الجملة ربط و إدراج كائن (Object Linking and Embedding)، يستطيع البرنامج الذي يحوي هذه الخاصية، الاتصال مع معطيات (نص أو رسوم أو أي معلومات أخرى) من تطبيقات ويندوز الأخرى التي تدعم بدورها هذه الخاصية.
لنفرض مثلاً أن مستخدم برنامجك، يرغب بتعديل ملف ما من نوع BMP، لعل أحد الطرق تتمثل بكتابة برنامج فيجول بيسك يسمح للمستخدم برسم وتعديل الصور النقطية BMP، إلا أن مثل هذا الأمر يلزمه عمل كبير، ويستغرق وقتاً طويلاً حتى تعلّم المستخدم كيف يستخدم برنامج الرسوم الخاص بك لتعديل ملفات الصورة BMP.
لعل الحل الأسهل يتمثل بتحميل الصورة BMP باستخدام برنامج رسوم شهير (مثل الرسامPaint brush)، ثم تعديل الصورة بواسطته، وباعتبار أن المستخدم يعمل حتماً على ويندوز، فلا بد أنه غالباً يعرف كيفية استخدام الرسام Paint؟ كبرنامج رسم مرفق مع ويندوز.
كيف ستخبر المستخدم طريقة استخدام برنامج الرسام Paint؟ تستطيع كتابة برنامج بسيط بلغة فيجول بيسك، يستعرض طريقة تحميل صورة نقطية BMP ثم تعديلها بواسطة الرسام. بشكل خطوات، لكن الطريقة الأفضل والأكثر إحكاماً، تتمثل باستخدام عنصر التحكم OLE (OLE Control) حسب ما يوضحه برنامج الرسام. يوضح الشكل 15-11 رمز عنصر التحكم OLE في إطار أدوات فيجول بيسك.
الشكل 15-11 عنصر التحكم OLE.
برنامج الرسام
يوضح برنامج الرسام كيف يمكن استخدام برنامج يدعم تقنية OLE، مثل برنامج Paint Brush واستخدامه في تطبيقات فيجول بيسك، يمكّنك برنامج الرسام من تحميل صورة نقطية من نوع BMP وتعديلها.
التمثيل المرئي لبرنامج الرسام
أنشئ مشروعاً جديداً من نوع Standard EXE واحفظ نموذج المشروع بالاسم USEPAINT.FRM في الدليل C:\VB5Prg\Ch15 واحفظ ملف المشروع بالاسم USEPAINT.VBP في ذات الدليل.
أسند الخصائص التالية للنموذج:
Name: frmUsePaint
Caption: برنامج الرسام
RightToLeft: True
إضافة عنصر التحكم OLE إلى النموذج frmUsePaint
انقر نقرة مزدوجة على رمز عنصر التحكم OLE في مربع الأدوات.
يستجيب فيجول بيسك بوضع عنصر التحكم OLE في النموذج وإظهار مربع الحوار إدراج كائن (انظر الشكل 15-12).
الشكل 15-12 مربع الحوار إدراج كائن.
يُظهر مربع الحوار إدراج كائن لائحة من الكائنات التي يمكن إدراجها في برنامج الرسام.
اختر صورة نقطية من لائحة الكائنات (Objects) ثم انقر الزر موافق.
احفظ المشروع.
تنفيذ البرنامج الرسام
لننفذ برنامج الرسام ونشاهد تقنية OLE قيد التنفيذ:
نفّذ برنامج الرسام.
يظهر برنامج الرسام كما في الشكل 15-13.
انقر نقراً مزدوجاً على عنصر التحكم OLE ضمن إطار برنامج الرسام.
يستجيب البرنامج بتمكينك من الرسم ضمن عنصر التحكم OLE، بنفس الأسلوب الذي ترسم به ضمن الرسام (انظر الشكل 15-14). لاحظ أنك تستطيع إنجاز مهام الرسام الأخرى باستعمال القوائم التي تظهر في قمة إطار برنامج الرسام.
الشكل 15-13 برنامج الرسام بعد تنفيذه.

الشكل 15-14 الرسم ضمن عنصر التحكم OLE.
ارسم شيئاً ما بواسطة برنامج الرسام
انقر الرمز (×) في أعلى اليمين لإنهاء برنامج الرسام.

الخلاصة
تعلمنا في هذا الفصل كيف نقرأ ونعدل الملفات من نوع FRM التي تحوي وصف النموذج وفق صيغة ASCII. وتعلمنا كيف نصرح عن المصفوفات الساكنة والديناميكية، وكيف نستخدمها. وتعلمنا أيضاً كيفية تمرير الوسائط بطريقة القيمة الراجعة ByRef، أو بطريقة القيمة الغير راجعة ByVal، والفرق بين الطريقتين.
كما أعطانا الفصل مقدمة تمهيدية عن تقنية OLE، وكيفية إستخدامها فى تطبيقات فيجول بيسك المختلفة.
الفصل السادس عشر




أداة التحكم فى البيانات ولغة SQL




يوضح هذا الفصل كيفية استخدام أداة التحكم فى البيانات Data Control، المضمنة مع اللغة الأصلية. تستطيع مع هذه الأداة، كتابة برامج تتيح لك الوصول لقواعد البيانات المختلفة، مثل Microsoft Access، DBase، Btrieve، Paradox، FoxPro. يشرح لك هذا الفصل أيضاً، كيفية استخدام لغة الاستعلامات البنيوية SQL لمعالجة قواعد البيانات ببراعة وسهولة.
برنامج البيانات
يوضح برنامج البيانات، سهولة الوصول للبيانات الموجودة في قواعد البيانات المختلفة، وذلك من خلال فيجول بيسك نفسه، واستخدام أداة التحكم فى البيانات. يوضح الشكل 16-1 رمز أداة التحكم فى البيانات الموجود في نافذة مربع الأدوات، قد يظهر رمز أداة التحكم فى البيانات في موقع مختلف في نافذة الأدوات لديك، عن الشكل 16-1، عند وضع مؤشر الفأرة فوق رمز أداة التحكم فى البيانات في نافذة مربع الأدوات، يظهر مستطيل أصفر اللون يحتوي الكلمة Data. عندها ستتأكد من وجود أداة التحكم فى البيانات لديك.
الشكل 16-1 أداة التحكم فى البيانات.
إنشاء قاعدة بيانات وجداول التحكم فى البيانات
يتصل برنامج البيانات الذي ستصممه لاحقاً، بقاعدة بيانات. وهي ضرورية لعمل البرنامج، لذلك يجب أولاً إنشاء ملف قاعدة البيانات. ستنشئ في هذا الفصل قاعدة بيانات، باستخدام برنامج خدمي يسمى مدير التحكم فى البيانات Data Manager، الموجود في لغة فيجول بيسك.
سنستخدم برنامج مدير التحكم فى البيانات، لتصميم وإنشاء قاعدة بيانات تسمى Test.mdb، وهي عبارة عن مجموعة من الجداول، مثال، يمكن أن تحتوي الشركة على الجداول التالية:
جدول يضم لائحة أقسام الشركة الصناعية.
جدول يضم لائحة أسماء بائعي منتجات الشركة.
جدول يضم لائحة أسماء الزبائن.
سوف تضم قاعدة البيانات Test.MDB، جدولاً واحداً هو Parts.
أنشئ الدليل C:\Vb5Prg\Ch16 لتحفظ عملك فيه.
اختر البند Visual Data Manager، من القائمة Add Ins.
قد يسألك فيجول بيسك إذا كنت تريد إضافةSystem.Md? للملفini، انقرالزرلا.
تظهر نافذة VisData كما في الشكل 16-2.
الشكل 16-2 برنامج مدير التحكم فى البيانات.
اختر البند New، ثم البند Microsoft Access، ثم البند Version 7.0 MDB، من القائمة File، انظر الشكل 16-3.
الشكل 16-3 طلب إنشاء قاعدة بيانات من برنامج مدير التحكم فى البيانات.
يظهر عندها مربع حوار (انظر الشكل 16-4)، يسمح لك بإنشاء قاعدة بيانات من النوع Microsoft Access.
الشكل 16-4 مربع حوار إنشاء ملف قاعدة بيانات.
استخدم مربع الحوار السابق لحفظ قاعدة البيانات باسم Test.MDB، في الدليل C:\Vb5Prg\Ch16. بعد إنشاء الملف الجديد يظهر بعدها الشكل 16-5.
إذا لم تكن ملفات قواعد البيانات والجداول مألوفة لديك، فقط تذكر أن قاعدة البيانات هي عبارة عن مجموعة من البيانات. مثال على ذلك: يمكن لمعمل ما، حفظ جدول بالسلع الموجودة لديه، في قاعدة بيانات.
تعتبر قاعدة البيانات مجموعة من الجداول، مثل جدول أسماء السلع، وجدول عمليات البيع والشراء التي جرت على هذه السلع وهكذا.
ينبغي أن يحتوي الملفTest.MDB جدول واحد، أو أكثر. نرى من الشكل 16-5 قاعدة البيانات Test.MDB لا تحوي أي جدول حتى الآن، ولذلك تصبح مهمتك، إنشاء جدول جديد باسم Parts.
الشكل 16-5 قاعدة البيانات Test.MDB، لا تحوي أي جدول.
انقر الزر اليميني للماوس فوق نافذة Database.
ستظهر قائمة فرعية تحوي بندين هما: Refresh List و New Table.
اختر البند New Table لإنشاء جدول جديد.
تظهر النافذةTable Structure كما في الشكل 16-6. استخدم النافذة السابقة لبناء الجدول Parts.
اكتب Parts في الحقل Table Name، وهو اسم الجدول الجديد.

الشكل 16-6 نافذة بناء الجدول.
أضف إليه الحقول المطلوبة كالتالي:
انقر الزر Add Field ليظهر مربع الحوار Add Field، كما في الشكل 16-7.
اكتبPartNum في المربع Name، وهو اسم أول حقل في الجدول Parts.
حدد النوعText في المربع Type، لأن الحقل PartNum هوحقل نصي.
حدد حجم الحقل بعشرة حروف كحد أقصى.
ينبغي أن يكون شكل النافذة Add Field كما في الشكل 16-7.
الشكل 16-7 إضافة الحقل الأول.
انقر الزر OK في النافذة Add Field.
انقر الزر Close في النافذة Add Field.
كما ترى في الشكل 16-8. أصبح الحقل PartNum موجوداً في المربع Field List.
الشكل 16-8 نافذة بناء الجدول، بعد إضافة الحقل PartNum.
أضف الحقل الثاني للجدول Parts كالتالي:
انقر الزر Add Field في النافذة Table Stracture.
تظهر النافذة Add Field.
اكتب Description في مربع النص Name.
حدد النوع Text، والحجم 20.
يصبح شكل النافذة Add Field كما في الشكل 16-9.
الشكل 16-9 إضافة الحقل Description.
انقر الزر OK ثم الزر Close في النافذة Add Field.
أصبح لدى الجدول Parts حقلين. انظر الشكل 16-10.
الشكل 16-10 نافذة بناء الجدولParts بعد إضافة حقلين إليه.
لقد انتهيت الآن من تصميم الجدول Parts.
انقر الزر Build The Table في النافذة Table Structure.
اختر البند Exit من القائمة File، من نافذة البرنامج VisData.
لقد أنجزت إلى الآن ما يلي:
أنشأت الملف Test.MDB
أنشأت جدولاً يدعى Parts في ملف قاعدة البيانات Test.MDB.
يحتوي الجدول Parts على حقلين هما:
اسم الحقل النوع الحجم
PartNum Text 10
Description Text 20
إدخال البيانات في الجدول Parts
لإضافة البيانات في الجدولParts اتبع ما يلي:
اختر البند Visual Data Manager من القائمة Add Ins، في فيجول بيسك.
يستجيب فيجول بيسك بإظهار النافذة VisData.
اختر البند Open Database من القائمة File، في نافذة البرنامج VisData، ثم اختر البند Microsoft Access.
يظهر مربع الحوار Open Microsoft Access Database.
استخدم مربع الحوار السابق لاختيار الملف Test.MDB التي حفظته في الدليل C:\Vb5Prg\Ch16.
تضم نافذة البرنامج VisData الآن، قاعدة البيانات Test.MDB، انظر الشكل 16-11.
كما ترى، تحوي النافذة Data Bases بندين داخلها هما: Properties و Parts.
لرؤية خصائص قاعدة البيانات، انقر الرمز (+) الظاهر يسار البند Properties.
يمثل البند Parts الجدول Parts المنشأ سابقاً، إذا أضفت المزيد من الجداول لقاعدة البيانات، فإنها ستظهر جميعاً في النافذة Database.
الشكل 16-11 نافذة البرنامج VisData بعد فتح قاعدة البيانات Test.MDB.
انقر الرمز (+) الظاهر يسار البند Parts. لتظهر لائحة خصائص البند Parts، وأحد هذه البنود هو البند Field.
انقر الرمز (+) الظاهر يسار البند Field. لتظهر لائحة حقول البند Parts، وهي نفس الحقول التي أنشأتها في الجدول Parts: PartNum و Description.
الآن، أدخل البيانات إلى الجدول Parts كالتالي:
انقر نقراً مزدوجاً البندParts في النافذة Database.
تظهر النافذة Dynasetarts، يتم إدخال البيانات إلى الجدول، عبر هذه النافذة. انظر الشكل 16-12.
الشكل 16-12 نافذة Dynasetarts مستعدة لإدخال الالبيانات.
انقر الزر Add في نافذة Dynasetarts، لتتمكن من إضافة سجل جديد للجدول Parts.
يتغير شكل النافذة السابقة، كما في الشكل 16-13.
الشكل 16-13 نافذة Dynasetarts بعد نقر الزر Add.
اكتب PC100 في الحقل PartNum.
اكتب PC 100 Megahertz في الحقل Description
ينبغي ظهور النافذة بعد إضافة أول سجل للجدول، كما في الشكل 16-14.
تظهر بيانات السجل الأول في الشكل 16-14. كما قلنا سابقاً، يتألف الجدول Parts من سجلات Records، ويحتوي أول سجل فيه، على القيمة PC100 في الحقل PartNum، والقيمة PC 100 megahertz في الحقل Description.
الشكل 16-14 نافذة Dynasetarts بعد كتابة قيم حقلي السجل الأول.
انقر الزر Update لكتابة السجل الجديد فعلياً إلى الجدول Parts.
انقر الزر Add لإدخال السجل الثاني، وهو سجل فارغ حالياً.
اكتب RAM40 في الحقل PartNum.
اكتب RAM 40 nanosecond في الحقل Description.
انقر الزر Update.
أخيراً، أضف السجل الثالث كالتالي:
انقر الزر Add.
اكتب Key101 في الحقل PartNum.
اكتب 101Keys Keyboard في الحقل Description.
انقر الزر Update.
انقر الزر Close.
اختر البند Exit من القائمة File.
لقد أنجزت حتى الآن ما يلي:
أنشأت ملف قاعدة بيانات باسمTest.MDB في الدليل C:\Vb5Prg\Ch16.
أنشأت الجدول Parts في قاعدة البيانات.
يحتوي الجدول Parts على حقلين هما: PartNum و Description
أضفت ثلاثة سجلات إلى الجدول Parts.
تصميم برنامج البيانات المرئي
ابدأ بتشغيل فيجول بيسك، وأنشئ مشروعاً من النوع Stardard EXE، واحفظ هذا المشروع في الدليل C:\Vb5Prg\Ch16 باسم Data.Vbp، واحفظ النموذج Form1 باسم Data.frm في نفس الدليل السابق.
انقر نقراً مزدوجاً على رمز أداة التحكم فى البيانات في نافذة الأدوات.
يصبح النموذج كما في الشكل 16-15.
الشكل 16-15 إضافة أداة التحكم فى البيانات إلى النموذج.
تستطيع تكبير أو تصغير أو نقل أداة التحكم فى البيانات مثل باقي عناصر التحكم الأخرى.
حرّك أداة التحكم فى البيانات إلى أسفل النموذج، ثم كبرها بسحب مقابضها، حتى تصبح كما في الشكل 16-16.
الشكل 16-16 النموذج بعد تغيير موقع وحجم أداة التحكم فى البيانات.
أسند القيم التالية لخصائص النموذج:
Name: frmData
Caption: برنامج البيانات
RightToLeft: True
تحديد قاعدة البيانات Access لربطها مع أداة التحكم فى البيانات
ينبغي تحديد اسم ومسار ملف قاعدة البيانات، حتى تتمكن أداة التحكم فى البيانات من الوصول إليها، والتعامل معها. يختلف تحديد قاعدة بيانات، ليست من النوع Access، قليلاً عن تحديد قاعدة بيانات Access.
تعتبر قاعدة البيانات Test.MDB، الذي أنشأتها في بداية هذا الفصل، من النوع Access، وهذا يعني أن الملف متوافق مع البرنامج Microsoft Access.
اتبع الخطوات التالية لتحديد اسم ومسار ملف قاعدة البيانات، المطلوب ربطها مع أداة التحكم فى البيانات Data1:
تأكد من اختيار أداة التحكم فى البيانات على النموذج، (يظهر حولها ثمانية مقابض)، ثم اختر البند Properties من القائمة View.
تظهر نافذة الخصائص لأداة التحكم فى البيانات Data1.
اختر الخاصية DatabaseName، من نافذة الخصائص، ثم انقر الزر الذي يحوي ثلاثة نقاط والموجود على نفس سطر الخاصية.
يظهر مربع الحوار DatabaseName، كما في الشكل 16-17.
استخدم مربع الحوار السابق لاختيار الملف C:\Vb5Prg\Ch16\Test.MDB، المُنشأ سابقاً، ثم انقر الزر فتح.
علمت أداة التحكم فى البيانات الآن، الملف الذي ستتحكم به، وهو Test.MDB.
الشكل 16-17 مربع حوار اختيار قاعدة بيانات لأداة التحكم فىالبيانات.
اختر الخاصية RecordSource بنفس الطريقة السابقة، من نافذة الخصائص، ثم انقر الزر الذي يحوي سهماً للأسفل، لسرد لائحة أسماء جميع الجداول الموجودة في ملف قاعدة البيانات الذي اخترته سابقاً.
لو كانت قاعدة البيانات Test.MDB تحوي أكثر من جدول واحد، لظهروا جميعهم في مربع السرد السابق، بما أنها تحوي جدولاً واحداً فقط، لذلك فهو الوحيد الذي يمكن اختياره.
ملاحظة
يجب مراعاة الترتيب في تحديد الخصائص السابقة، بحيث لا يمكن تحديد الخاصية RecordSource قبل تحديد الخاصية DataBaseName.
اختر اسم الجدول Parts من مربع سرد الخاصية RecordSource.
أسند القيمة True للخاصية RightToLeft.
وضع مربع نص لعرض البيانات
يجب ربط مربع نص ما، مع أحد حقول جدول قاعدة البيانات Test.MDB، لإظهار محتوياته للمستخدم. لأداء هذه المهمة اتبع ما يلي:
ضع مربع نص على النموذج frmData، كما في الشكل 16-18. وخصائصه كالتالي:
Name: txtPartNumber
Text: فراغ
RightToLeft: True
ضع لافتة على النموذج frmData، كما في الشكل 16-18. وخصائصها كالتالي:
Name: lblPartNumber
Caption: رقم القطعة
RightToLeft: True
الشكل 16-18 النموذج frmData بعد إضافة مربع نص ولافتة وزر أمر.
أضف زر أمر إلى النموذج واجعل خصائصه كالتالي:
Name: cmdExit
Caption: &خروج
RightToLeft: True
ينبغي ظهور النموذج كما في الشكل 16-18.
اكتب النص التالي للإجراء cmdExit_Click():
Private Sub cmdExit_Click()
End
End Sub
يستخدم مربع النص txtPartNumber لإظهار أو تعديل البيانات المسجلة في الحقل PartNum، أخبر فيجول بيسك الآن، أية أداة تحكم فى البيانات تريد ربطها مع مربع النص هذا:
غيّر الخاصية DataSource لمربع النص txtPartNumber إلى Data1. حيث Data1 هو اسم أداة التحكم فى البيانات الوحيدة الموجودة على النموذج.
بما أن النموذج لديك يحوي فقط أداة تحكم فى البيانات واحدة، لذلك يظهر فقط البند Data1 في مربع سرد الخاصية DataSource.
أخبر فيجول بيسك أيضاً، أن مربع النص هذا، سيُظهر محتويات الحقل PartNum:
غير الخاصية DataField لمربع النص txtPartNumber إلى القيمة PartNum.
احفظ عملك الآن، من خلال القائمة File ثم البند Save Project.


تنبيه
احفظ عملك بصورة متكررة، لأنك لو أخطأت (أو أخطأ فيجول بيسك نفسه)، أثناء تصميم البرنامج، فقد يتسبب ذلك في توقف النظام كاملاً عن العمل، وفقدان كل الأعمال التي لم تحفظها بعد. وظهور الرسالة المألوفة: عليك الاتصال بالبائع، والتي تعني فقدان آخر تعديلاتك. أما إذا حفظت أي تعديل قبل تنفيذ البرنامج مباشرة، ثم حصل خطأ ما، فإنك ببساطة تعيد تنفيذ فيجول بيسك مرة أخرى، وكأن شيئاً لم يكن.
تنفيذ برنامج البيانات
دعنا ننفذ الآن برنامج البيانات لنراه بشكل عملي:
نفّذ البرنامج بضغط المفتاح F5.
يظهر البرنامج كما في الشكل 16-19. وكما ترى فإن قيمة الحقل التي أدخلتها سابقاً قد ظهرت في مربع النص.
الشكل 16-19 تنفيذ برنامج البيانات.
انقر أسهم أداة التحكم فى البيانات، ولاحظ كيف تتغير محتويات مربع النص لتُظهر القيمة الفعلية للحقل PartNum.
نقر السهم الداخلي اليساري لأداة التحكم فى البيانات، يُظهر السجل التالي للسجل الحالي، أما نقر السهم الداخلي اليميني، فيُظهر السجل السابق للسجل الحالي، ونقر السهم اليساري الخارجي، يُظهر آخر سجل موجود في الجدول، كما أن نقر السهم اليميني الخارجي، يُظهر أول سجل موجود في الجدول.
بعد التدرب على برنامج البيانات، انقر الزر خروج لإنهاء عمل البرنامج والعودة إلى فيجول بيسك.
كما ترى في الشكل 16-19، تعرض أداة التحكم فى البيانات نصاً داخلها، والنص الافتراضي هو Data1، يمكنك تغير الخاصيةCaption لأداة التحكم فى البيانات، لتُظهر عنواناً آخر، وذلك في مرحلة التصميم أو في مرحلة التنفيذ.
فمثلاً يمكن كتابة السطر التالي لتغيير العنوان:
Data1.Caption = "Test.MDB قاعدة البيانات"
تعطيل مربع النص
لاحظ أن مربع النص الذي يُظهر محتويات الحقلPartNum، هو مربع نص يمكن تغير محتوياته أوتعديلها. جرب المثال التالي:
نفّذ برنامج البيانات بضغط المفتاح F5.
غير محتويات الحقلPartNum للسجل الأول، منPC100 إلى PC200.
انقر السهم الداخلي اليساري لأداة التحكم فى البيانات، لإظهار السجل الثاني.
انقر السهم الداخلي اليميني لإظهار السجل الأول مرة أخرى.
كما ترى، تغيرت محتويات الحقل PartNum في الجدول.
انقر الزر خروج للعودة إلى فيجول بيسك.
نفّذ البرنامج مرة أخرى.
لاحظ أن البيانات التي عدلتها سابقاً، قد ظهرت في الحقل PartNum.
غير محتويات الحقل PartNum إلىPC100 كما كانت سابقاً.
انقر السهم الداخلي اليساري، ثم السهم الداخلي اليميني، وتأكد أن محتويات الحقل PartNum قد عادت إلى PC100.
اخرج من البرنامج.
هناك أمور تقنية كثيرة، يجب تضمينها في برنامج البيانات هذا، أو أي برنامج Database احترافي، هي ليست موضوع هذا الفصل.
ببساطة امنع تغير محتويات الحقل PartNum، بتعطيل مربع النص الذي يعرض محتوياته، كالتالي:
غير قيمة الخاصيةEnabled الخاصة بمربع النص منTrue إلى False.
احفظ النموذج بضغط المفتاحين Ctrl + S.
نفّذ البرنامج بضغط المفتاح F5.
تأكد أن مربع النص يُظهر محتويات الحقل PartNum، بدون إمكانية تعديلها.
تدرب على برنامج البيانات، ثم اخرج من البرنامج.
تطوير برنامج البيانات
سنطور الآن برنامج البيانات، بإضافة مربع نص آخر إلى النموذج frmData، كما في الشكل 16-20، مهمته إظهار محتويات الحقل Description:
أضف لافتةLabel إلى النموذج، وأسند لها الخصائص التالية:
Name: lblDescription
Caption: Description
RightToLeft: True
أضف مربع نص إلى النموذج، وأسند له الخصائص التالية:
Name: txtDescription
Text: فراغ
Enabled: False
RightToLeft: True

الشكل 16-20 النموذج frmData بعد تطويره.
اربط الآن، مربع النص txtDescription مع أداة التحكم فى البيانات Data1، لتظهر محتويات الحقل Description كالتالي:
أسند لمربع النص txtDescription الخصائص التالية (إضافة للخصائص السابقة):
DataSource: Data1
DataField: Description
احفظ النموذج ثانية. (ضغط المفتاحين Ctrl + S).
تنفيذ برنامج البيانات المطور
نفّذ البرنامج الآن بضغط F5:
يظهر برنامج البيانات، كما في الشكل 16-21.
الشكل 16-21 برنامج البيانات بعد تطويره.
انقر أسهم أداة التحكم فى البيانات، للانتقال بين السجلات.
كما تلاحظ، تمثل محتويات مربعي النص، محتويات السجل الحالي.
اخرج من البرنامج.
إضافة حقل منطقيLogical إلى جدول قاعدة البيانات
بطريقة مشابهة، يمكن إضافة حقل منطقيLogical إلى الجدول Parts. فمثلاً يمكن إضافة الحقل InStock، الذي يحوي قيمة منطقية هي:True أو False. عندما تكون قيمة الحقل InStock هى True، فهذا يعني تواجد المادة ذات الرقم PartNumber في المخزن. أما إذا كانت قيمة الحقل InStock القيمةFalse، فهذا يعني عدم تواجد المادة ذات الرقم PartNumber في المخزن.
يمكن وضع خانة اختيار CheckBox، على النموذج، وربطها مع الحقل InStock الموجود في الجدول Parts، وذلك كالتالي:
أضف خانة اختيار إلى النموذج frmData. وأسند لها الخصائص التالية:
DataSource: Data1
DataField: InStock
RightToLeft: True
استخدام عناصر التحكم المُلْزَمَة Bound Controls
وضح برنامج البيانات كيفية إلزام مربع النص بإظهار محتويات الحقل الموجود في الجدول. تُسمى الأدوات التي تُظهِر محتويات حقول جداول قواعد البيانات، بالعناصر الملزمة Bound Controls.
يمكن استخدام مربعات النصوص، وخانات الاختيار، في البرنامج، كأدوات مُلزَمَة. كما يمكن إضافة حقل صورة، إلى الجدول Parts، يخزن صوراً Bmp، وإضافة عنصر الصورة إلى النموذج، وربطه مع حقل الصورة، وسيعمل عنصر الصورة على إظهار الصورة المخزنة في الحقل.
خصائص وطرق Methods أداة التحكم فى البيانات
يوجد لأداة التحكم فى البيانات خصائص عديدة، وطرق مختلفة لمعالجة البيانات، والتحكم بها، وسيشرح هذا الفصل بعضاً منها:
الطريقة Refresh (إنعاش)
يمكن استخدام الطريقة Refresh، لتحديث البيانات المرتبطة مع أداة التحكم فى البيانات، ومعرفة آخر التعديلات التي جرت على ملف قاعدة البيانات. مثال، تصور وجود ملف قاعدة البيانات في كومبيوتر رئيسي، وموصول مع جهازك الشخصي من خلال شبكة محلية (Local Area Network) LAN، ووجود مستخدم آخر، يعدّل نفس ملف قاعدة البيانات. قد لا تتطابق البيانات الموجودة على شاشتك، مع نفس البيانات التي عدّلها المستخدم الآخر.
لضمان الحصول على آخر التعديلات التي جرت من قبل المستخدمين الآخرين، يجب استخدام الطريقة Refresh على أداة التحكم فى البيانات، لضمان إظهار البيانات الصحيحة على شاشتك، وأنها هي نفسها، آخر ما جرى من تعديلات على ملف قاعدة البيانات.
الخاصية Exclusive (وصول وحيد)
إذا أردت أن يكون برنامجك هو الوحيد القادر على الوصول إلى ملف قاعدة البيانات، وبدون السماح لأي مستخدم آخر بالوصول أيضاً، عليك استخدام الخاصية Exclusive وتغيرها إلى True وذلك كالتالي:
Data1.Exclusive = True
تمنع بهذه الطريقة، أي برنامج أو مستخدم آخر من قدرته على فتح نفس ملف البيانات.
القيمة الافتراضية لهذه الخاصية هي False، ولإعادتها إلى الوضع الافتراضي (السماح للمستخدمين الآخرين بالوصول أيضاً)، اكتب السطر التالي:
Data1.Exclusive = False
أما إذا كانت قاعدة البيانات مفتوحة مسبقاً، وغيرت هذه الخاصية، فيجب تنفيذ الطريقة Refresh بعدها مباشرة، لتنفيذ الأمر بشكل صحيح، وذلك كالتالي:
Data1.Exclusive = False
Data1.Refresh
يعتبر الوصول إلى قاعدة بيانات مفتوحة بشكل خاص (Exclusive = True)، أسرع بكثير من الوصول إليها وهي مفتوحة للعمل المشترك (Exclusive = False). ولكن لا تلجأ لهذا الأسلوب، إلا إذا كنت متأكداً أنك الوحيد الذي يعمل على هذا الملف، وإلا، فإن المستخدمين الآخرين لن يستطيعوا العمل أيضاً، طالما كنت مستمراً في عملك.
الخاصية ReadOnly (للقراءة فقط)
لقد رأيت سابقاً، أن تغيير محتويات مربع النص، والمرتبط مع حقل أحد جداول قاعدة البيانات، يغير قيمة هذا الحقل فعلياً، بمجرد الانتقال لسجل آخر.
ماذا لو أردت استعراض محتويات قاعدة البيانات، دون الحاجة لتعديلها، أو أردت طريقة عملية، لمنع التعديل الحاصل نتيجة خطأ غير مقصود من أحد المستخدمين.
إذا أردت فتح ملف البيانات للقراءة فقط، غير الخاصية ReadOnly إلى True، وذلك من خلال الإجراء Form_Load(). اكتب الأسطر التالية:
Prvat Sub Form_Load()
Data1.ReadOnly = True
Data1.Refresh
End Sub
فعّل مربع النص (Enabled = True) الذي يُظهر محتويات الحقل PartNum.
احفظ المشروع.
نفّذ البرنامج.
غير محتويات مربع النص للسجل الأول.
عند هذه النقطة، ستتغير محتويات مربع النص فقط، بدون تغير محتويات الحقل الفعلي، كما سترى في الخطوات اللاحقة.
انتقل للسجل الثاني بنقر الزر اليساري الداخلي لأداة التحكم فى البيانات.
انتقل للسجل الأول بنقر الزر الداخلي اليميني.
لاحظ عدم تغير قيمة الحقل الأصلية، لأن الخاصية ReadOnly لها القيمة True.
لإعادة قيمة الخاصية ReadOnly إلى القيمة False، عدّل محتويات الإجراء Form_Load() كالتالي:
Prvat Sub Form_Load()
Data1.ReadOnly = False
Data1.Refresh
End Sub
جرب الخطوات السابقة مرة أخرى، ولاحظ أن التعديلات التي أجريتها في مربع النص، قد ثُبتت بالفعل في ملف قاعدة البيانات.
للمرة الثانية نقول، يجب استخدام الطريقة Refresh، بعد كل عملية تغيير أحد خصائص أداة التحكم فى البيانات.
ملاحظة
تأكد من إعادة قيمة الخاصية ReadOnly إلى False مرة أخرى، لضرورة إكمال بقية التمارين في هذا الفصل.
عند تصميم برنامج قاعدة بيانات احترافي، ينبغي إخبار المستخدم (بطريقة ما)، أن قاعدة البيانات هي للقراءة فقط (إذا كانت كذلك)، وإلا فإنه سيعدّل محتويات مربعات النصوص، ظاناً أن تعديلاته تُخزن فعلياً في ملف قاعدة البيانات، وهي لا تخزن عملياً.
استخدام عبارات لغة الاستعلام البنيوية SQL
يمكن استخدام عبارات SQL، لاختيار وتحديد مجموعة من السجلات التي تحقق شرطاً (أو شروطاً) معينة. اتبع الخطوات التالية لعمل ذلك:
ضع زر أمر على النموذج frmData، وأسند له الخصائص التالية:
Name: cmdSelect
Caption: ا&ختيار
RightToLeft: True
ينبغي ظهور النموذج بعد إضافة الزر اختيار كما في الشكل 16-22.
الشكل 16-22 النموذج frmData بعد إضافة الزر اختيار.
أضف الأسطر التالية إلى الإجراء cmdSelect_Click():
Private Sub cmdSelect_Click ()
Data1.RecordSource = "SELECT * FROM Parts _
& "WHERE PartNum = 'PC100'"
Data1. Refresh
End Sub
تُكتب عبارات SQL عادة، بأحرف كبيرة، لتمييزها عن باقي العبارات الأخرى. يختار الإجراء السابق عند تنفيذه، كل السجلات الموجودة في الجدول Parts، والموافقة لشرط مساواة قيمة الحقل PartNum للقيمة PC100. ثم تنفذ الطريقة Refresh عبارة SQL فعلياً.
احفظ عملك ونفذ البرنامج.
تأكد أن قيمةPartNum للسجل الأول تساوي PC100.
استخدم أسهم أداة التحكم فى البيانات لاستعراض السجلات المختلفة.
كما ترى، تستطيع التنقل بين كل السجلات.
انقر الزر اختيار.
بسبب احتواء قاعدة البيانات سجلاً واحداً فقط، مطابقاً للشرط الذي وضعناه في عبارة SQL، فسيظهر هذا السجل لوحده فقط، ويصبح البرنامج كما في الشكل 16-23.
الشكل 16-23 نقر الزر اختيار يؤدي لتحديد سجل واحد فقط.
لن يتغير السجل الظاهر، بنقر أسهم أداة التحكم فى البيانات، بسبب عدم وجود غيره، والمطابق للشرط السابق. تقوم عبارة SQL بتصفية كل السجلات التي لا توافق الشرط المحدد، وتعمل على استبعادها.
اخرج من البرنامج.
يمكن استخدام عبارة SQL لاختيار أية مجموعة من السجلات. مثلاً، افترض أنك أضفت الحقل InSock إلى الجدول Parts (يدلك هذا الحقل على وجود المادة في المخزن)، وأردت معرفة جميع المواد الموجودة في مخزنك، سيكون شكل عبارة SQL مشابهاً لما يلي:
Private Sub cmdSelect_Click ()
Data1.RecordSource = "SELECT * FROM Parts _
& "WHERE InSock = True"
Data1.Refresh
End Sub
عند تنفيذ البرنامج، ثم نقر الزر اختيار، فسوف تظهر في برنامج البيانات، كل السجلات التي توافق المواد المتوفرة في المخزن (InStock = True).
الطريقة AddNew (إضافة سجل)
تستخدم الطريقة AddNew لإضافة سجل جديد في مرحلة التنفيذ:
أضف زر أمر للنموذج frmData، وأسند له الخصائص التالية:
Name: cmdAddRecord
Caption: إ&ضافة سجل
RightToLeft: True
ليصبح النموذج frmData كما في الشكل 16-24.
الشكل 16-24 النموذج frmData بعد إضافة الزر إضافة سجل.
أضف الأسطر التالية للإجراء cmdAddRecord_Click():
Private Sub cmdAddRecord_Click()
Data1.RecordSet.AddNew
End Sub
تُطبق الطريقة AddNew على الخاصية Recordset التابعة لأداة التحكم فى البيانات. (ستشرح الخاصية Recordset لاحقاً).
في التمرين التالي، سنضيف بعض السجلات للجدول Parts:
غير الخاصية Enabled لمربعي النص، إلى القيمة True.
احفظ المشروع ونفذ البرنامج.
انقر الزر إضافة سجل.
بمجرد نقر الزر إضافة سجل، يُظهر برنامج البيانات سجلاً خالياً من البيانات، بمعنى آخر، تمسح كل الأدوات المرتبطة مع أداة التحكم فى البيانات، محتوياتها، استعداداً لكتابة بيانات جديدة عليها.
املأ محتويات مربعي النص بالبيانات الجديدة.
لتحفظ السجل الجديد في ملف قاعدة البيانات، عليك الانتقال إلى سجل آخر، لذلك انقر السهم الداخلي اليميني، للانتقال إلى السجل السابق.
اخرج من البرنامج.
الطريقة Delete (حذف سجل)
لحذف السجل الحالي من قاعدة البيانات، استخدم الطريقة Delete:
أضف زر أمر للنموذج frmData، وضعه أسفل الزر السابق، ثم أسند له الخصائص التالية:
Name: cmdDelete
Caption: &حذف
RightToLeft: True
أضف الأسطر التالية للإجراء cmdDelete_Click():
Private Sub cmdDelete_Click()
Data1.RecordSet.Delete
Data1.RecordSet.MoveNext
End Sub
احفظ المشروع ثم نفّذ البرنامج.
استخدم الأسهم للانتقال إلى السجل الذي ترغب بحذفه.
انقر الزر حذف لحذف السجل الحالي الظاهر.
تدرب على الزرين إضافة سجل و حذف لفترة، ثم اخرج من البرنامج.

ملاحظة
تعتبر عملية حذف سجل ما، أمراً بالغ السهولة، وما عليك سوى نقر الزر حذف. هذه السهولة الشديدة غير مقبولة مطلقاً في الحياة العملية، أو البرامج التجارية. فأنت تحتاج إلى تحذير المستخدم من عملية الحذف، وإظهار مربع حوار يسأله إذا كان متأكداً من حذف السجل، ولا يُحذف السجل فعلياً، إلا في حال موافقة المستخدم على ذلك.
الطريقة MoveNext (سجل لاحق)
تُظهر هذه الطريقة السجل التالي للسجل الحالي، وتقوم بنفس وظيفة السهم الداخلي اليساري، ولها الشكل التالي:
Data1.Recordset.MoveNext
الطريقة MovePrevious (سجل سابق)
تُظهر هذه الطريقة السجل السابق للسجل الحالي، وتقوم بنفس وظيفة السهم الداخلي اليميني، ولها الشكل التالي:
Data1.Recordset.MovePrevious
الطريقة MoveLast (سجل أخير)
تُظهر هذه الطريقة آخر سجل موجود في مجموعة السجلات، وتقوم بنفس وظيفة السهم الخارجي اليساري، ولها الشكل التالي:
Data1.Recordset.MoveLast
الطريقة MoveFirst (سجل أول)
تُظهر هذه الطريقة أول سجل موجود في مجموعة السجلات، وتقوم بنفس وظيفة السهم الخارجي اليميني، ولها الشكل التالي:
Data1.Recordset.MoveFirst
الخاصية Recordset (مجموعة السجلات)
تعتبر هذه الخاصية، الكائن الذي يحوي مجموعة من السجلات، قد تكون هذه السجلات موجودة في جدول معين (مثل الجدول Parts)، أو قد تكون مجموعة من السجلات التي تحقق شرطاً معيناً (PartNum = PC100)، أو قد تكون مجموعة من السجلات الموجودة في أكثر من جدول.
مثال، إذا لم تقم بفرز أو تصفية للسجلات، بواسطة عبارة SQL، فإن هذه الخاصة تمثل كل السجلات الموجودة في الجدول Parts.
يمكن لأداة التحكم فى البيانات التعامل مع أكثر من جدول واحد، لذلك يمكن إنشاء مجموعة سجلات RecordSet، هي عبارة عن سجلات أكثر من جدول واحد.
توضح لك الخطوات التالية كيفية معرفة عدد السجلات الموجودة في مجموعة السجلات الحالية:
أضف زر أمر للنموذج frmData، وأسند له الخصائص التالية:
Name: cmdCountRecords
Caption: &عدد السجلات
RightToLeft: True
بعد إضافة الزر عدد السجلات، يصبح النموذج كما في الشكل 16-25.
الشكل 16-25 النموذج frmData بعد إضافة الزر عدد السجلات.
أضف الأسطر التالية للإجراء cmdCountRecords_Click():
Privat Sub cmdCountRecords_Click()
Data1.Recordset.MoveLast
MsgBox Data1.RecordSet.RecordCount
End Sub
ينقل الإجراء السابق المؤشر، إلى آخر سجل موجود في مجموعة السجلات الحالية، وتحصي الطريقة RecordCount عدد السجلات، من أول سجل وحتى السجل الحالي (آخر سجل)، ولذلك فهي تعود بقيمة عدد السجلات الفعلي الموجودة في الجدول Parts. ثم تُظهر مربع رسالة، لتخبر المستخدم عن عدد السجلات الفعلي.
احفظ المشروع ثم نفّذ البرنامج.
انقر الزر عدد السجلات.
تظهر رسالة تُخبر المستخدم عن عدد السجلات الصحيح.
أضف بعض السجلات للجدول Parts، ثم انقر الزر عدد السجلات، لتعرف عدد السجلات الحالي.
اخرج من البرنامج.
الخاصية Value
يمكن معرفة قيمة حقل ما، بقراءة الخاصية Text، التي تعطي محتويات النص الموجود ضمن مربع نص. فمثلاً، يمكن معرفة قيمة الحقل PartNum للسجل الحالي، بقراءة الخاصية Text التابعة لمربع النص txtPartNumber.
أضف السطر التالي للإجراء Form_Click()، وهو ينفذ عند نقر سطح النموذج مرة واحدة:
Private Sub Form_Click()
MsgBox "PartNumber:" + txtPartNumber.Text
End Sub
احفظ المشروع ومن ثم نفذه.
انقر سطح النموذج مباشرة (المساحة الخالية منه).
تظهر رسالة، تخبرك عن قيمة الحقل PartNum.
اخرج من البرنامج.
تحتاج أحياناً، لمعرفة قيمة حقل ما، غير مرتبط مع مربع نص، أو أي عنصر آخر، لذلك سنستخدم الخاصية Value لمعرفة قيمة الحقل مباشرة، اتبع ما يلي:
عدّل الأسطر الموجودة في الإجراء Form_Click() إلى ما يلي:

Private Sub Form_Click()
Dim MyString As String

MyString = Data1.Recordset.Fields("PartNum").Value
MsgBox MyString
End Sub
احفظ المشروع ومن ثم نفّذ البرنامج.
انقر سطح النموذج.
تظهر رسالة تخبرك عن قيمة الحقلPartNum للسجل الحالي.
اخرج من البرنامج.
يقوم الإجراء السابق، بوضع قيمة الحقلPartNum في المتحول MyString، ثم يُظهر المتحول من خلال العبارة MsgBox.
يمكنك بهذه الطريقة معرفة قيمة أي حقل من حقول السجل الحالي، ولو كان هذا الحقل غير مرتبط مع أي عنصر تحكم.
الخاصيتين EOF و BOF
يمكن استخدام الخاصية EOF (End Of File) والخاصية BOF (Beginning Of File)، لمعرفة أن السجل الحالي، سجل صحيح وموجود. مثال، لو أظهر برنامجك سجل محدد، وقام أحد المستخدمين الآخرين على الشبكة، بحذف هذا السجل الذي تعرضه على شاشتك، هذا سيعني أن مؤشر السجل لديك، أصبح يشير إلى سجل غير صحيح أو غير موجود. يمكن لبرنامجك معرفة أن مؤشر السجل يشير إلى سجل صحيح أو موجود كالتالي:
If Data1.Recordset.EOF = False _
And Data1.Recordset.BOF = False Then
'''''''''''''''''''''''''''''''''
''''مؤشر السجل يشير لسجل صحيح ''''
'''''''''''''''''''''''''''''''''
End If
تفحص كتلة If .. End If السابقة، إذا كان مؤشر السجل، يشير لسجل صحيح أو موجود، وذلك بفحص كلتا الخاصيتين BOF و EOF، فإذا كانت قيمتهما مساوية للقيمة False، يعني أن مؤشر السجل يشير لسجل صحيح وموجود.
أي اختلاف في أحد هاتين القيمتين عن False، يعني أن مؤشر السجل يشير إلى سجل خاطئ أو غير موجود (تم حذفه من قبل مستخدم آخر).
جدول 16-1 احتمالات قيم الخاصيتين BOF و EOF:
إذا كانت قيمة BOF وكانت قيمة EOF يكون:
False False المؤشر يشير إلى سجل حقيقي.
False True المؤشر يشير إلى ما بعد آخر سجل في الجدول.
True False المؤشر يشير إلى ما قبل أول سجل في الجدول.
True True لا يحتوي الجدول على أية سجلات.
ماذا يمكن لأداة التحكم فى البيانات فعله أيضاً ؟
قدمنا لك في هذا الفصل، بعض الخصائص والطرق الأولية لأداة التحكم فى البيانات. يمكن الاستفادة من هذه الخصائص والطرق، في إظهار أو تعديل محتويات حقول جداول قاعدة البيانات.
تدعم أداة التحكم فى البيانات العديد من المزايا، التي تسمح لفيجول بيسك بمعالجة قواعد البيانات والتحكم بها. مثلاً، يمكنك بناء ملف قاعدة بيانات أو تعديل البنية التركيبية له. في الحقيقة، فإن أداة التحكم فى البيانات هي أقوى بكثير مما تتوقع، وسهولتها النسبية لا تلغي قوتها أبداً.
تستطيع أداة التحكم فى البيانات معالجة أنواع أخرى من قواعد البيانات المختلفة عن Microsoft Access، وهي تستخدم نفس مكتبة محرك البيانات DBEngine الذي يستخدمه البرنامج الشهير Access، يضمن لك هذا الأمر، المصداقية والثقه والسرعة وخلو ملفات قواعد البيانات التي تستخدمها من الأخطاء، وتوافقها مع برامج قواعد البيانات الأخرى.
تعتبر قواعد البيانات من النوع Access، من أسهل وأقوى أنواع قواعد البيانات، في نفس الوقت.
الخلاصة
تعرفت في هذا الفصل، على أداة التحكم فى البيانات الموجودة مع لغة فيجول بيسك نفسها، وكيفية تغيير بعض خصائصها المهمة، وربطها مع عناصر أخرى، مثل مربعات النص، لإظهار محتويات الحقول الموجودة في الجدول.
تعلمت أيضاً كيفية إنعاشها، لمعرفة أخر المستجدات. وتعلمت أيضاً مبادىء عبارات SQL، وكيفية إضافة أو حذف أو إستعراض السجلات الموجودة فى الجدول.
الفصل الثامن عشر
محاكاة ضربات المفاتيح
سوف تتعلم في هذا الفصل، كيفية إرسال ضربات المفاتيح عبر برنامجك إلى برامج ويندوز الأخرى، وكيفية توجيه ضربات المفاتيح من البرنامج الذي أنشأته إلى البرنامج نفسه مرة أخرى، تفيد هذه التقنية في إنشاء برامج دعائية Demo أو أية برامج أخرى.
محاكاة ضربات المفاتيح: برنامجي المصدر والمقصد
تستطيع كتابة برنامج ما، عبر لغة فيجول بيسك، يُرسل ضربات المفاتيح، وكأنها أرسلت من لوحة المفاتيح Keyboard الفعلية. سنكتب الآن برنامجين، Source.exe و Dest.exe. يولد البرنامج Source.exe ضربات المفاتيح، ويستقبل البرنامج Dest.exe هذه الضربات المنشأة من البرنامج Source.exe.
التصميم المرئي لبرنامج المصدر
ابدأ مشروعاً جديداً من النوع Standard EXE، واحفظ المشروع باسم Source.Vbp في الدليل C:\VB5Prg\Ch18، واحفظ النموذج باسم Source.frm في نفس الدليل.
أنشأ النموذج frmSource وفقاً للجدول 18-1.
جدول 18-1. جدول خصائص النموذج frmSource.
الكائن الخاصية القيمة
Form Name frmSource
Caption برنامج المصدر
RightToLeft True
CommandButton Name cmdExit
Caption &خروج
RightToLeft True
CommandButton Name cmdSend
Caption إر&سال
RightToLeft True
TextBox Name txtUserArea
MultiLine True
ScrollBars 3-Both
RightToLeft True
بعد انتهاء النموذج ينبغي أن يصبح كما في الشكل 18-1.
إدخال نص البرنامج frmSource
أدخل النص التالي في قسم التصريحات العامة للنموذج frmSource:
'يجب التصريح عن كل المتحولات في البرنامج
Option Explicit
الشكل 18-1 النموذج frmSource بعد انتهاء تصميمه.
أدخل النص التالي في الإجراء Form_Load():
Private Sub Form_Load()
Dim ID
'تنفيذ برنامج المقصد
ChDir App.Path
ID = Shell("Dest.exe", vbNormalFocus)
End Sub
أدخل النص التالي في الإجراء cmdSend_Click():
Private Sub cmdSend_Click()
'جعل برنامج المقصد فعالا
AppActivate "برنامج المقصد"

'إرسال الأحرف إلى برنامج المقصد
SendKeys txtUserArea.Text, True
End Sub
أدخل النص التالي في الإجراء cmdExit_Click():
Private Sub cmdExit_Click()
End
End Sub
احفظ المشروع.
أنشئ الملف التنفيذي Source.exe، باختيار البند Make Source.exe... من القائمة File، واحفظه في الدليل C:\VB5Prg\EXE.
لا تستطيع تنفيذ البرنامج Source.exe بعدْ، لأنه يحتاج إلى البرنامج Dest.exe لكي يعمل بصورة طبيعية.
التصميم المرئي لبرنامج المقصد
ابدأ مشروعاً جديداً من النوع Standard EXE، واحفظ المشروع في الدليل C:\VB5Prg\Ch18 باسم Dest.Vbp، واحفظ النموذج الجديد باسم Dest.Frm في نفس الدليل.
أنشأ النموذج frmDest وفقاً للجدول 18-2.
جدول 18-2. جدول خصائص النموذج frmDest.
الكائن الخاصية القيمة
Form Name frmDest
Caption برنامج المقصد
RightToLeft True
CommandButton Name cmdExit
Caption &خروج
RightToLeft True
CommandButton Name cmdDisplayMessage
Caption &عرض الرسالة
RightToLeft True
بعد انتهاء النموذج ينبغي أن يصبح كما في الشكل 18-2.
الشكل 18-2 النموذج frmDest بعد انتهاء تصميمه.
إدخال نص برنامج المقصد
أدخل النص التالي في قسم التصريحات العامة للنموذج frmDest:
'يجب التصريح عن كل المتحولات في البرنامج
Option Explicit
أدخل النص التالي في الإجراء cmdDisplayMessage_Click():
Private Sub cmdDisplayMessage_Click()
MsgBox "لقد نقرت زر عرض الرسالة"
End Sub
أدخل النص التالي في الإجراء cmdExit_Click():
Private Sub cmdExit_Click()
End
End Sub
سوف ننشئ الآن الملف التنفيذي Dest.exe:
اختر البند Make Dest.exe... من القائمة File، واحفظ الملف التنفيذي Dest.exe في الدليل C:\VB5Prg\EXE.
تأكد من وجود الملفين التنفيذيين Source.exe و Dest.exe في نفس الدليل السابق.
تنفيذ برنامجي المصدر والمقصد معاً
نفّذ أولاً البرنامج Dest.exe:
أنهِ فيجول بيسك، من القائمة File، البند Exit
افتح الدليل C:\VB5Prg\EXE من المستكشف، ثم نفّذ البرنامج Dest.exe، بالنقر المزدوج على رمزه، كأي برنامج آخر.
تظهر نافذة البرنامج Dest.exe كما في الشكل 18-3.
الشكل 18-3 نافذة برنامج المقصد.
انقر الزر عرض الرسالة في البرنامج Dest.exe.
تظهر الرسالة التالية "لقد نقرت زر عرض الرسالة " كما في الشكل 18-4.
الشكل 18-4 الرسالة التي تظهر عقب نقر الزر عرض الرسالة.
انقر الزر خروج في البرنامج Dest.exe لإنهائه.
لاحظ بساطة برنامج المقصد، واحتوائه على زرين فقط، أحدهما لإظهار رسالة، والثاني للخروج.
الهدف من البرنامجين السابقين، توضيح فكرة استطاعتك نقر الزر عرض الرسالة الموجود في برنامج المقصد، من خلال برنامج المصدر.
اتبع الخطوات التالية لرؤية ذلك فعلياً:
تأكد أن البرنامج Dest.exe غير منفذ حالياً.
نفّذ البرنامج Source.exe.
يتم تنفيذ البرنامج Source.exe، وآلياً سوف يتم تنفيذ البرنامج Dest.exe كما في الشكل 18-5.
الشكل 18-5 تنفيذ برنامج المصدر وبرنامج المقصد.
صغّر كافة النوافذ ماعدا نافذتي البرنامجين السابقين، وضعهما بشكل متجاور، بحيث تراهما بشكل واضح ومنفصل.
اكتب %ع (التي تعني ضغط المفتاحين عAlt+ في لوحة المفاتيح) في مربع النص الموجود في برنامج المصدر.
انقر الزر إرسال في برنامج المصدر، لإرسال المفتاحين السابقين إلى برنامج المقصد.
كما ترى، أظهر برنامج المقصد الرسالة الخاصة به، وكأن أحدهم قد نقر الزر عرض الرسالة، (لم يفعل أحد ذلك)، وإنما قلّد البرنامج Source.exe إرسال ضربات المفاتيح، وكأنها أرسلت من لوحة المفاتيح فعلياً.
اكتب هذه المرة %خ (التي تعني ضغط المفتاحين خAlt+ في لوحة المفاتيح) في مربع النص الموجود في برنامج المصدر (تذكر مسح محتويات مربع النص أولاً).
انقر الزر إرسال في برنامج المصدر، لإرسال المفتاحين السابقين إلى برنامج المقصد.
ماذا حصل، لقد تم إنهاء برنامج المقصد، عن طريق نقر الزر خروج، وأيضاً لم يفعل أحد ذلك، وإنما تم هذا الأمر عن طريق برنامج المصدر، الذي أرسل ضربتي المفتاحين خAlt+ إلى برنامج المقصد، وبدوره أُجبر على الخروج.
جرب كتابة % (إضافة لحرف مسافة واحد بعده)، التي تعني ضغط المفتاحين Alt+Space في لوحة المفاتيح.
انقر الزر إرسال في برنامج المصدر، لإرسال المفتاحين السابقين إلى برنامج المقصد.
لقد ظهرت قائمة النظام System Menu، في برنامج المقصد.
أضف للكتابة السابقة (%حرف مسافة واحد)، الحرف (ك)، لتصبح (% ك)، ثم أعد نقر الزر إرسال.
لقد أخذت نافذة البرنامج كامل مساحة الشاشة، وبمعنى آخر، تم تكبيرها Maximized. لماذا؟
كما رأينا في الخطوة قبل السابقة، فإن إرسال المفتاحين Alt+Space، يظهران قائمة النظام لبرنامج المقصد، أما الحرف (ك)، فيمثل اختيار البند تكبير من قائمة النظام.
جرب الخطوة الأخيرة، مع كتابة الحرف (ص)، بدلاً من الحرف (ك)، يمثل الحرف (ص) اختيار البند تصغير من قائمة النظام. لاحظ كيف تم تصغير نافذة برنامج المقصد Minimized.
تمرن على البرنامجين السابقين ثم اخرج من البرنامج.
كيف يعمل برنامج المصدر
يشغل برنامج المصدر عند بدء تنفيذه، برنامج المقصد آلياً، باستخدام التابع Shell()، ويستخدم العبارة Sendkeys، لإرسال ضربات المفاتيح لبرنامج المقصد.
الإجراء Form_Load():
ينفذ هذا الإجراء آلياً، عند بدء تنفيذ برنامج المصدر. ويستخدم التابع Shell()، لتنفيذ البرنامج الآخر، وهو برنامج المقصد:
Private Sub Form_Load()
Dim ID
'تنفيذ برنامج المقصد
ChDir App.Path
ID = Shell("Dest.exe", vbNormalFocus)
End Sub
يمثل الوسيط الأول لهذا التابع، اسم الملف التنفيذي المطلوب تشغيله. أما الوسيط الثاني فهو اختياري، بمعنى أنه يمكننا إهماله (اعتباره غير موجود)، على أي حال، يحدد الوسيط الثاني كيفية تنفيذ البرنامج (نمط تنفيذه)، بمعنى هل سينفذ بشكل طبيعي Normal، أم بشكل مكبر Maximized، أم بشكل مصغر Minimized، أم بشكل مخفي Hidden.
أسندنا قيمة الثابت vbNormalFocus، التي تعني تنفيذ البرنامج بشكل طبيعي Normal، ومع تنشيطه في نفس الوقت.
ملاحظة
إذا لم يحدَد المسار الكامل للملف التنفيذي في الوسيط الأول للتابع Shell()، فإن التابع Shell() يفترض وجود الملف التنفيذي في نفس الدليل الحالي، أو في الأدلة المعرفة في بيئة Dos من خلال السطر Path في الملف Autoexec.bat.
الإجراء cmdSend_Click()
ينفذ هذا الإجراء آلياً عند نقر الزر إرسال:
Private Sub cmdSend_Click()
'جعل برنامج المقصد فعالا
AppActivate "برنامج المقصد"
'إرسال الأحرف إلى برنامج المقصد
SendKeys txtUserArea.Text, True
End Sub
ينشّط هذا الإجراء برنامج المقصد، من خلال العبارة AppActive:
AppActivate "برنامج المقصد"
يمثل الوسيط الأول لهذه العبارة، عنوان النافذة المراد تنشيطها، ويجب مطابقة هذا العنوان تماماً، لما هو مكتوب في شريط عنوان النافذة المراد تنشيطها، وإلا حصل خطأ في مرحلة التنفيذ run time error.
ترسل العبارة التالية Sendkeys، أية ضربة أو ضربات متتالية للمفاتيح، إلى البرنامج النشط الحالي، (هذا يفسر قيامك بتنشيط برنامج المقصد، قبل إرسال ضربات المفاتيح)، لأننا نريد إرسال ضربات المفاتيح لبرنامج المقصد.
بعد انتهاء إرسال ضربات المفاتيح لبرنامج المقصد، يظل برنامج المقصد نشطاً أو فعالاً، وحتى تعيد الفعالية لبرنامج المصدر، أضف للإجراء السابق، العبارة التالية المسؤولة عن تنشيط برنامج ما:
AppActivate "برنامج المصدر"
بعد تعليمة Sendkeys مباشرة، ليصبح الإجراء cmdSend_Click() كالتالي:
Private Sub cmdSend_Click()
'جعل برنامج المقصد فعالا
AppActivate "برنامج المقصد"
'إرسال الأحرف إلى برنامج المقصد
SendKeys txtUserArea.Text, True
AppActivate "برنامج المصدر"
End Sub
العبارة Sendkeys
تستخدم العبارة Sendkeys كما رأيت في برنامج المصدر، لإرسال الأحرف، ومحاكاة جميع ضربات لوحة المفاتيح الفعلية، ترسل هذه الضربات إلى البرنامج النشط الحالي، (لا يسمح النظام ويندوز بتنشيط أكثر من برنامج واحد فقط في نفس الوقت).
تستخدم العبارة Sendkeys وسيطين: يمثل الوسيط الأول ضربات المفاتيح التي نريد إرسالها للبرنامج النشط، أما الوسيط الثاني للعبارة Sendkeys فيمثل كيفية إرسال هذه المفاتيح، ويتقبل قيمتين فقط هما True أو False.
تُجبر القيمة True، الإجراء cmdSend_Click() على الانتظار، حتى تُعالج جميع ضربات المفاتيح المرسلة (من قبل البرنامج الذي أُرسلت إليه)، قبل تنفيذ العبارة التالية للعبارة Sendkeys.
أما عند وضع القيمة False، يستمر تنفيذ العبارة التي تلي عبارة Sendkeys مباشرة، دون انتظارٍ لمعالجة ضربات المفاتيح المرسلة.
في مثالنا السابق، استخدمنا القيمة True في عبارة Sendkeys. لذلك سوف ينتظر برنامج المصدر، لحين انتهاء برنامج المقصد، من معالجة ضربات المفاتيح التي أرسلت إليه.
أما إذا وضعت القيمة False بدلاً من القيمة True، فسوف يعود التحكم إلى برنامج المصدر مباشرة، بعد إرسال ضربات المفاتيح، دون انتظار برنامج المقصد للانتهاء من عمله.
يمكن استخدام العبارة Sendkeys لإرسال مفاتيح خاصة مذكورة في الجدول 18-3. مثل إرسال المفتاح عAlt+، بكتابة "%ع".
عند ضغط المفتاحين عAlt+ في برنامج المقصد، ستحصل على نفس النتيجة، كما لو نقرت الزر عرض الرسالة. بسبب أن قيمة الخاصية Caption للزر عرض الرسالة هي "&عرض الرسالة"، والتي تعني أن الحرف (ع) يمثل حرف الوصول السريع Hotkey للزر عرض الرسالة.


جدول 18-3. شفرة الأحرف الخاصة المستخدمة مع عبارة Sendkeys.
المفتاح طريقة كتابته في العبارة Sendkeys
SHIFT +
CTRL ^
ALT %
BACKSPACE {BACKSPACE}, {BS}, or {BKSP}
BREAK {BREAK}
CAPS LOCK {CAPSLOCK}
DEL or DELETE {DELETE} or {DEL}
DOWN ARROW {DOWN}
END {END}
ENTER {ENTER}or ~
ESC {ESC}
HELP {HELP}
HOME {HOME}
INS or INSERT {INSERT} or {INS}
LEFT ARROW {LEFT}
NUM LOCK {NUMLOCK}
PAGE DOWN {PGDN}
PAGE UP {PGUP}
PRINT SCREEN {PRTSC}
RIGHT ARROW {RIGHT}
SCROLL LOCK {SCROLLLOCK}
TAB {TAB}
UP ARROW {UP}
F1 {F1}
F2 {F2}
... ...
F16 {F16}
كيف يُرسِل البرنامج ضربات المفاتيح إلى نفسه؟
برنامج الرنين
ترسل العبارة Sendkeys ضربات المفاتيح للبرنامج النشط الحالي، ماذا يحصل لو كان برنامج المصدر هو البرنامج النشط، وقت إرسال ضربات المفاتيح؟. كما توقعت تماماً فهذه الضربات، سترسل إلى برنامج المصدر نفسه!
هل يوجد استخدامات خاصة لعملية إرسال الضربات إلى البرنامج نفسه؟. بالتأكيد يوجد، مثال على ذلك، برامج العرض أو البرامج التدريبية، حيث تقوم هذه البرامج بتشغيل نفسها، بغرض شرح كيفية عملها للمستخدم، أو تدريبه على العمل على هذه البرامج. وسوف يشرح برنامج الرنين كيفية عمل ذلك في فيجول بيسك.
التصميم المرئي لبرنامج الرنين:
ابدأ مشروعاً جديداً من النوع Standard EXE واحفظ المشروع في الدليل C:\VB5Prg\Ch18 باسم MySelf.Vbp، واحفظ النموذج الجديد باسم MySelf.Frm في نفس الدليل.
أنشئ النموذج frmMySelf وفقاً للجدول 18-4.
بعد انتهاء النموذج، ينبغي أن يصبح كما في الشكل 18-6.
جدول 18-4. جدول خصائص النموذج frmMySelf.
الكائن الخاصية القيمة
Form Name frmDest
Caption برنامج الرنين
RightToLeft True
CommandButton Name cmdExit
Caption &خروج
RightToLeft True
CommandButton Name cmdBeep
Caption &رنين
RightToLeft True
CommandButton Name cmdSend
Caption إر&سال
RightToLeft True
TextBox Name txtUserArea
MultiLine True
Text (اجعله فارغاً)
RightToLeft True
الشكل 18-6 نموذج برنامج الرنين في مرحلة التصميم.
كتابة نص برنامج الرنين
أدخل النص التالي في قسم التصريحات العامة للنموذج frmMySelf:
'يجب التصريح عن كل المتحولات في البرنامج
Option Explicit
أدخل النص التالي في الإجراء cmdSend_Click():
Private Sub cmdSend_Click()
'تأكيد نشاط برنامج الرنين
AppActivate "برنامج الرنين"
'إرسال النص المكتوب في مربع النص
'للبرنامج نفسه
SendKeys txtUserArea, True
End Sub
أدخل النص التالي في الإجراء cmdBeep_Click():
Private Sub cmdBeep_Click()
Beep
MsgBox "لقد نقرت زر رنين"
End Sub
أدخل النص التالي في الإجراء cmdExit_Click():
Private Sub cmdExit_Click()
End
End Sub
تنفيذ برنامج الرنين
نفّذ برنامج الرنين كالتالي:
اختر البند Make MySelf.exe...، من القائمة File، واحفظ الملف التنفيذي MySelf.exe، في الدليل C:\VB5Prg\EXE.
أنهِ عمل فيجول بيسك، من القائمة File البند Exit.
نفّذ البرنامج MySelf.exe.
انقر الزر رنين.
ينبغي على جهازك إصدار صوت، ولمدة قصيرة (لا ضرورة لوجود بطاقة صوت داخل جهازك، لأن الصوت يصدر عن مكبر الصوت الداخلي).
اضغط المفتاحين رAlt+ في لوحة المفاتيح.
ينبغي على جهازك أيضاً، إصدار صوت، لأن عنوان الزر رنين هو "&رنين"، والحرف (ر) يمثل حرف الوصول السريع له.
اكتب %ر في مربع النص التابع لبرنامج الرنين، ثم انقر الزر إرسال.
ينبغي على جهازك أيضاً، إصدار صوت رنين.
تدرب على برنامج الرنين ثم اخرج منه.
نص الإجراء cmdSend_Click()
ينفذ هذا الإجراء آلياً، عند نقر الزر إرسال في برنامج الرنين:
تقوم العبارة الأولى في هذا الإجراء، على تأكيد نشاط برنامج الرنين. في الحقيقة، لا داعي لهذه العبارة برمجياً، لأنك بمجرد نقر الزر رنين، يُنشط البرنامج آلياً.
أما العبارة التالية Sendkeys، فهي ترسل النص المكتوب في مربع النص، إلى البرنامج النشط الحالي (برنامج الرنين)، وكأنه مرسل من لوحة المفاتيح الفعلية.
إذا كتبت %ر في مربع النص، فإنه يُترجم على أنه المفتاح رAlt+، (كما هو واضح في الشكل 18-6).
وهو يشبه عملية نقر الزر رنين.
يحتوي الإجراء cmdBeep_Click() العبارتين Beep و MsgBox، اللتين تتسببان في إصدار صوت من المكبر الداخلي لجهازك، ثم إظهار مربع رسالة.

الخلاصة
تعلمت فى هذا الفصل كيفية إستخدام الوظسفة Shell ()، لتنفيذ برنامج أخر من خلال برنامجك، وكيفية إرسال المعلومات من تطبيق لأخر، أو من التطبيق وإليه، عبر العبارة Sendkeys.
الفصل الثامن عشر




محاكاة ضربات المفاتيح




سوف تتعلم في هذا الفصل، كيفية إرسال ضربات المفاتيح عبر برنامجك إلى برامج ويندوز الأخرى، وكيفية توجيه ضربات المفاتيح من البرنامج الذي أنشأته إلى البرنامج نفسه مرة أخرى، تفيد هذه التقنية في إنشاء برامج دعائية Demo أو أية برامج أخرى.
محاكاة ضربات المفاتيح: برنامجي المصدر والمقصد
تستطيع كتابة برنامج ما، عبر لغة فيجول بيسك، يُرسل ضربات المفاتيح، وكأنها أرسلت من لوحة المفاتيح Keyboard الفعلية. سنكتب الآن برنامجين، Source.exe و Dest.exe. يولد البرنامج Source.exe ضربات المفاتيح، ويستقبل البرنامج Dest.exe هذه الضربات المنشأة من البرنامج Source.exe.
التصميم المرئي لبرنامج المصدر
ابدأ مشروعاً جديداً من النوع Standard EXE، واحفظ المشروع باسم Source.Vbp في الدليل C:\VB5Prg\Ch18، واحفظ النموذج باسم Source.frm في نفس الدليل.
أنشىء النموذج frmSource وفقاً للجدول 18-1.
جدول 18-1. جدول خصائص النموذج frmSource.
الكائن الخاصية القيمة
Form Name frmSource
Caption برنامج المصدر
RightToLeft True
CommandButton Name cmdExit
Caption &خروج
RightToLeft True
CommandButton Name cmdSend
Caption إر&سال
RightToLeft True
TextBox Name txtUserArea
MultiLine True
ScrollBars 3-Both
RightToLeft True
بعد انتهاء النموذج ينبغي أن يصبح كما في الشكل 18-1.
إدخال نص البرنامج frmSource
أدخل النص التالي في قسم التصريحات العامة للنموذج frmSource:
'يجب التصريح عن كل المتحولات في البرنامج
Option Explicit
الشكل 18-1 النموذج frmSource بعد انتهاء تصميمه.
أدخل النص التالي في الإجراء Form_Load():
Private Sub Form_Load()
Dim ID
'تنفيذ برنامج المقصد
ChDir App.Path
ID = Shell("Dest.exe", vbNormalFocus)
End Sub
أدخل النص التالي في الإجراء cmdSend_Click():
Private Sub cmdSend_Click()
'جعل برنامج المقصد فعالا
AppActivate "برنامج المقصد"

'إرسال الأحرف إلى برنامج المقصد
SendKeys txtUserArea.Text, True
End Sub
أدخل النص التالي في الإجراء cmdExit_Click():
Private Sub cmdExit_Click()
End
End Sub
احفظ المشروع.
أنشئ الملف التنفيذي Source.exe، باختيار البند Make Source.exe... من القائمة File، واحفظه في الدليل C:\VB5Prg\EXE.
لا تستطيع تنفيذ البرنامج Source.exe بعدْ، لأنه يحتاج إلى البرنامج Dest.exe لكي يعمل بصورة طبيعية.
التصميم المرئي لبرنامج المقصد
ابدأ مشروعاً جديداً من النوع Standard EXE، واحفظ المشروع في الدليل C:\VB5Prg\Ch18 باسم Dest.Vbp، واحفظ النموذج الجديد باسم Dest.Frm في نفس الدليل.
أنشأ النموذج frmDest وفقاً للجدول 18-2.
جدول 18-2. جدول خصائص النموذج frmDest.
الكائن الخاصية القيمة
Form Name frmDest
Caption برنامج المقصد
RightToLeft True
CommandButton Name cmdExit
Caption &خروج
RightToLeft True
CommandButton Name cmdDisplayMessage
Caption &عرض الرسالة
RightToLeft True
بعد انتهاء النموذج ينبغي أن يصبح كما في الشكل 18-2.
الشكل 18-2 النموذج frmDest بعد انتهاء تصميمه.
إدخال نص برنامج المقصد
أدخل النص التالي في قسم التصريحات العامة للنموذج frmDest:
'يجب التصريح عن كل المتحولات في البرنامج
Option Explicit
أدخل النص التالي في الإجراء cmdDisplayMessage_Click():
Private Sub cmdDisplayMessage_Click()
MsgBox "لقد نقرت زر عرض الرسالة"
End Sub
أدخل النص التالي في الإجراء cmdExit_Click():
Private Sub cmdExit_Click()
End
End Sub
سوف ننشئ الآن الملف التنفيذي Dest.exe:
اختر البند Make Dest.exe... من القائمة File، واحفظ الملف التنفيذي Dest.exe في الدليل C:\VB5Prg\EXE.
تأكد من وجود الملفين التنفيذيين Source.exe و Dest.exe في نفس الدليل السابق.
تنفيذ برنامجي المصدر والمقصد معاً
نفّذ أولاً البرنامج Dest.exe:
أنهِ فيجول بيسك، من القائمة File، البند Exit
افتح الدليل C:\VB5Prg\EXE من المستكشف، ثم نفّذ البرنامج Dest.exe، بالنقر المزدوج على رمزه، كأي برنامج آخر.
تظهر نافذة البرنامج Dest.exe كما في الشكل 18-3.
الشكل 18-3 نافذة برنامج المقصد.
انقر الزر عرض الرسالة في البرنامج Dest.exe.
تظهر الرسالة التالية "لقد نقرت زر عرض الرسالة " كما في الشكل 18-4.
الشكل 18-4 الرسالة التي تظهر عقب نقر الزر عرض الرسالة.
انقر الزر خروج في البرنامج Dest.exe لإنهائه.
لاحظ بساطة برنامج المقصد، واحتوائه على زرين فقط، أحدهما لإظهار رسالة، والثاني للخروج.
الهدف من البرنامجين السابقين، توضيح فكرة استطاعتك نقر الزر عرض الرسالة الموجود في برنامج المقصد، من خلال برنامج المصدر.
اتبع الخطوات التالية لرؤية ذلك فعلياً:
تأكد أن البرنامج Dest.exe غير منفذ حالياً.
نفّذ البرنامج Source.exe.
يتم تنفيذ البرنامج Source.exe، وآلياً سوف يتم تنفيذ البرنامج Dest.exe كما في الشكل 18-5.
الشكل 18-5 تنفيذ برنامج المصدر وبرنامج المقصد.
صغّر كافة النوافذ ماعدا نافذتي البرنامجين السابقين، وضعهما بشكل متجاور، بحيث تراهما بشكل واضح ومنفصل.
اكتب %ع (التي تعني ضغط المفتاحين عAlt+ في لوحة المفاتيح) في مربع النص الموجود في برنامج المصدر.
انقر الزر إرسال في برنامج المصدر، لإرسال المفتاحين السابقين إلى برنامج المقصد.
كما ترى، أظهر برنامج المقصد الرسالة الخاصة به، وكأن أحدهم قد نقر الزر عرض الرسالة، (لم يفعل أحد ذلك)، وإنما قلّد البرنامج Source.exe إرسال ضربات المفاتيح، وكأنها أرسلت من لوحة المفاتيح فعلياً.
اكتب هذه المرة %خ (التي تعني ضغط المفتاحين خAlt+ في لوحة المفاتيح) في مربع النص الموجود في برنامج المصدر (تذكر مسح محتويات مربع النص أولاً).
انقر الزر إرسال في برنامج المصدر، لإرسال المفتاحين السابقين إلى برنامج المقصد.
ماذا حصل، لقد تم إنهاء برنامج المقصد، عن طريق نقر الزر خروج، وأيضاً لم يفعل أحد ذلك، وإنما تم هذا الأمر عن طريق برنامج المصدر، الذي أرسل ضربتي المفتاحين خAlt+ إلى برنامج المقصد، وبدوره أُجبر على الخروج.
جرب كتابة % (إضافة لحرف مسافة واحد بعده)، التي تعني ضغط المفتاحين Alt+Space في لوحة المفاتيح.
انقر الزر إرسال في برنامج المصدر، لإرسال المفتاحين السابقين إلى برنامج المقصد.
لقد ظهرت قائمة النظام System Menu، في برنامج المقصد.
أضف للكتابة السابقة (%حرف مسافة واحد)، الحرف (ك)، لتصبح (% ك)، ثم أعد نقر الزر إرسال.
لقد أخذت نافذة البرنامج كامل مساحة الشاشة، وبمعنى آخر، تم تكبيرها Maximized. لماذا؟
كما رأينا في الخطوة قبل السابقة، فإن إرسال المفتاحين Alt+Space، يظهران قائمة النظام لبرنامج المقصد، أما الحرف (ك)، فيمثل اختيار البند تكبير من قائمة النظام.
جرب الخطوة الأخيرة، مع كتابة الحرف (ص)، بدلاً من الحرف (ك)، يمثل الحرف (ص) اختيار البند تصغير من قائمة النظام. لاحظ كيف تم تصغير نافذة برنامج المقصد Minimized.
تمرن على البرنامجين السابقين ثم اخرج من البرنامج.
كيف يعمل برنامج المصدر
يشغل برنامج المصدر عند بدء تنفيذه، برنامج المقصد آلياً، باستخدام التابع Shell()، ويستخدم العبارة Sendkeys، لإرسال ضربات المفاتيح لبرنامج المقصد.
الإجراء Form_Load():
ينفذ هذا الإجراء آلياً، عند بدء تنفيذ برنامج المصدر. ويستخدم التابع Shell()، لتنفيذ البرنامج الآخر، وهو برنامج المقصد:
Private Sub Form_Load()
Dim ID
'تنفيذ برنامج المقصد
ChDir App.Path
ID = Shell("Dest.exe", vbNormalFocus)
End Sub
يمثل الوسيط الأول لهذا التابع، اسم الملف التنفيذي المطلوب تشغيله. أما الوسيط الثاني فهو اختياري، بمعنى أنه يمكننا إهماله (اعتباره غير موجود)، على أي حال، يحدد الوسيط الثاني كيفية تنفيذ البرنامج (نمط تنفيذه)، بمعنى هل سينفذ بشكل طبيعي Normal، أم بشكل مكبر Maximized، أم بشكل مصغر Minimized، أم بشكل مخفي Hidden.
أسندنا قيمة الثابت vbNormalFocus، التي تعني تنفيذ البرنامج بشكل طبيعي Normal، ومع تنشيطه في نفس الوقت.
ملاحظة
إذا لم يحدَد المسار الكامل للملف التنفيذي في الوسيط الأول للتابع Shell()، فإن التابع Shell() يفترض وجود الملف التنفيذي في نفس الدليل الحالي، أو في الأدلة المعرفة في بيئة Dos من خلال السطر Path في الملف Autoexec.bat.
الإجراء cmdSend_Click()
ينفذ هذا الإجراء آلياً عند نقر الزر إرسال:
Private Sub cmdSend_Click()
'جعل برنامج المقصد فعالا
AppActivate "برنامج المقصد"
'إرسال الأحرف إلى برنامج المقصد
SendKeys txtUserArea.Text, True
End Sub
ينشّط هذا الإجراء برنامج المقصد، من خلال العبارة AppActive:
AppActivate "برنامج المقصد"
يمثل الوسيط الأول لهذه العبارة، عنوان النافذة المراد تنشيطها، ويجب مطابقة هذا العنوان تماماً، لما هو مكتوب في شريط عنوان النافذة المراد تنشيطها، وإلا حصل خطأ في مرحلة التنفيذ run time error.
ترسل العبارة التالية Sendkeys، أية ضربة أو ضربات متتالية للمفاتيح، إلى البرنامج النشط الحالي، (هذا يفسر قيامك بتنشيط برنامج المقصد، قبل إرسال ضربات المفاتيح)، لأننا نريد إرسال ضربات المفاتيح لبرنامج المقصد.
بعد انتهاء إرسال ضربات المفاتيح لبرنامج المقصد، يظل برنامج المقصد نشطاً أو فعالاً، وحتى تعيد الفعالية لبرنامج المصدر، أضف للإجراء السابق، العبارة التالية المسئولة عن تنشيط برنامج ما:
AppActivate "برنامج المصدر"
بعد تعليمة Sendkeys مباشرة، ليصبح الإجراء cmdSend_Click() كالتالي:
Private Sub cmdSend_Click()
'جعل برنامج المقصد فعالا
AppActivate "برنامج المقصد"
'إرسال الأحرف إلى برنامج المقصد
SendKeys txtUserArea.Text, True
AppActivate "برنامج المصدر"
End Sub
العبارة Sendkeys
تستخدم العبارة Sendkeys كما رأيت في برنامج المصدر، لإرسال الأحرف، ومحاكاة جميع ضربات لوحة المفاتيح الفعلية، ترسل هذه الضربات إلى البرنامج النشط الحالي، (لا يسمح النظام ويندوز بتنشيط أكثر من برنامج واحد فقط في نفس الوقت).
تستخدم العبارة Sendkeys وسيطين: يمثل الوسيط الأول ضربات المفاتيح التي نريد إرسالها للبرنامج النشط، أما الوسيط الثاني للعبارة Sendkeys فيمثل كيفية إرسال هذه المفاتيح، ويتقبل قيمتين فقط هما True أو False.
تُجبر القيمة True، الإجراء cmdSend_Click() على الانتظار، حتى تُعالج جميع ضربات المفاتيح المرسلة (من قبل البرنامج الذي أُرسلت إليه)، قبل تنفيذ العبارة التالية للعبارة Sendkeys.
أما عند وضع القيمة False، يستمر تنفيذ العبارة التي تلي عبارة Sendkeys مباشرة، دون انتظارٍ لمعالجة ضربات المفاتيح المرسلة.
في مثالنا السابق، استخدمنا القيمة True في عبارة Sendkeys. لذلك سوف ينتظر برنامج المصدر، لحين انتهاء برنامج المقصد، من معالجة ضربات المفاتيح التي أرسلت إليه.
أما إذا وضعت القيمة False بدلاً من القيمة True، فسوف يعود التحكم إلى برنامج المصدر مباشرة، بعد إرسال ضربات المفاتيح، دون انتظار برنامج المقصد للانتهاء من عمله.
يمكن استخدام العبارة Sendkeys لإرسال مفاتيح خاصة مذكورة في الجدول 18-3. مثل إرسال المفتاح عAlt+، بكتابة "%ع".
عند ضغط المفتاحين عAlt+ في برنامج المقصد، ستحصل على نفس النتيجة، كما لو نقرت الزر عرض الرسالة. بسبب أن قيمة الخاصية Caption للزر عرض الرسالة هي "&عرض الرسالة"، والتي تعني أن الحرف (ع) يمثل حرف الوصول السريع Hotkey للزر عرض الرسالة.

جدول 18-3. شفرة الأحرف الخاصة المستخدمة مع عبارة Sendkeys.
المفتاح طريقة كتابته في العبارة Sendkeys
SHIFT +
CTRL ^
ALT %
BACKSPACE {BACKSPACE}, {BS}, or {BKSP}
BREAK {BREAK}
CAPS LOCK {CAPSLOCK}
DEL or DELETE {DELETE} or {DEL}
DOWN ARROW {DOWN}
END {END}
ENTER {ENTER}or ~
ESC {ESC}
HELP {HELP}
HOME {HOME}
INS or INSERT {INSERT} or {INS}
LEFT ARROW {LEFT}
NUM LOCK {NUMLOCK}
PAGE DOWN {PGDN}
PAGE UP {PGUP}
PRINT SCREEN {PRTSC}
RIGHT ARROW {RIGHT}
SCROLL LOCK {SCROLLLOCK}
TAB {TAB}
UP ARROW {UP}
F1 {F1}
F2 {F2}
... ...
F16 {F16}
كيف يُرسِل البرنامج ضربات المفاتيح إلى نفسه؟
برنامج الرنين
ترسل العبارة Sendkeys ضربات المفاتيح للبرنامج النشط الحالي، ماذا يحصل لو كان برنامج المصدر هو البرنامج النشط، وقت إرسال ضربات المفاتيح؟. كما توقعت تماماً فهذه الضربات، سترسل إلى برنامج المصدر نفسه!
هل يوجد استخدامات خاصة لعملية إرسال الضربات إلى البرنامج نفسه؟. بالتأكيد يوجد، مثال على ذلك، برامج العرض أو البرامج التدريبية، حيث تقوم هذه البرامج بتشغيل نفسها، بغرض شرح كيفية عملها للمستخدم، أو تدريبه على العمل على هذه البرامج. وسوف يشرح برنامج الرنين كيفية عمل ذلك في فيجول بيسك.
التصميم المرئي لبرنامج الرنين:
ابدأ مشروعاً جديداً من النوع Standard EXE واحفظ المشروع في الدليل C:\VB5Prg\Ch18 باسم MySelf.Vbp، واحفظ النموذج الجديد باسم MySelf.Frm في نفس الدليل.
أنشئ النموذج frmMySelf وفقاً للجدول 18-4.
بعد انتهاء النموذج، ينبغي أن يصبح كما في الشكل 18-6.
جدول 18-4. جدول خصائص النموذج frmMySelf.
الكائن الخاصية القيمة
Form Name frmDest
Caption برنامج الرنين
RightToLeft True
CommandButton Name cmdExit
Caption &خروج
RightToLeft True
CommandButton Name cmdBeep

الكائن الخاصية القيمة
Caption &رنين
RightToLeft True
CommandButton Name cmdSend
Caption إر&سال
RightToLeft True
TextBox Name txtUserArea
MultiLine True
Text (اجعله فارغاً)
RightToLeft True

الشكل 18-6 نموذج برنامج الرنين في مرحلة التصميم.
كتابة نص برنامج الرنين
أدخل النص التالي في قسم التصريحات العامة للنموذج frmMySelf:
'يجب التصريح عن كل المتحولات في البرنامج
Option Explicit
أدخل النص التالي في الإجراء cmdSend_Click():
Private Sub cmdSend_Click()
'تأكيد نشاط برنامج الرنين
AppActivate "برنامج الرنين"
'إرسال النص المكتوب في مربع النص
'للبرنامج نفسه
SendKeys txtUserArea, True
End Sub
أدخل النص التالي في الإجراء cmdBeep_Click():
Private Sub cmdBeep_Click()
Beep
MsgBox "لقد نقرت زر رنين"
End Sub
أدخل النص التالي في الإجراء cmdExit_Click():
Private Sub cmdExit_Click()
End
End Sub
تنفيذ برنامج الرنين
نفّذ برنامج الرنين كالتالي:
اختر البند Make MySelf.exe...، من القائمة File، واحفظ الملف التنفيذي MySelf.exe، في الدليل C:\VB5Prg\EXE.
أنهِ عمل فيجول بيسك، من القائمة File البند Exit.
نفّذ البرنامج MySelf.exe.
انقر الزر رنين.
ينبغي على جهازك إصدار صوت، ولمدة قصيرة (لا ضرورة لوجود بطاقة صوت داخل جهازك، لأن الصوت يصدر عن مكبر الصوت الداخلي).
اضغط المفتاحين رAlt+ في لوحة المفاتيح.
ينبغي على جهازك أيضاً، إصدار صوت، لأن عنوان الزر رنين هو "&رنين"، والحرف (ر) يمثل حرف الوصول السريع له.
اكتب %ر في مربع النص التابع لبرنامج الرنين، ثم انقر الزر إرسال.
ينبغي على جهازك أيضاً، إصدار صوت رنين.
تدرب على برنامج الرنين ثم اخرج منه.
نص الإجراء cmdSend_Click()
ينفذ هذا الإجراء آلياً، عند نقر الزر إرسال في برنامج الرنين:
تقوم العبارة الأولى في هذا الإجراء، على تأكيد نشاط برنامج الرنين. في الحقيقة، لا داعي لهذه العبارة برمجياً، لأنك بمجرد نقر الزر رنين، يُنشط البرنامج آلياً.
أما العبارة التالية Sendkeys، فهي ترسل النص المكتوب في مربع النص، إلى البرنامج النشط الحالي (برنامج الرنين)، وكأنه مرسل من لوحة المفاتيح الفعلية.
إذا كتبت %ر في مربع النص، فإنه يُترجم على أنه المفتاح رAlt+، (كما هو واضح في الشكل 18-6).
وهو يشبه عملية نقر الزر رنين.
يحتوي الإجراء cmdBeep_Click() على العبارتين Beep و MsgBox، اللتين تتسببان في إصدار صوت من المكبر الداخلي لجهازك، ثم إظهار مربع رسالة.
الخلاصة
تعلمت فى هذا الفصل كيفية إستخدام الوظسفة Shell ()، لتنفيذ برنامج أخر من خلال برنامجك، وكيفية إرسال المعلومات من تطبيق لأخر، أو من التطبيق وإليه، عبر العبارة Sendkeys.
الفصل التاسع عشر




تقنية ActiveX، الأصوات، الوسائط المتعددة




تعلمت من الفصول السابقة، أساسيات لغة فيجول بيسك. مثل إنشاء النماذج، ووضع الكائنات على النموذج، وربط نص برنامج معين بهذه الكائنات. يركز هذا الفصل على كيفية تصميم التطبيقات في ويندوز مع تقنية ActiveX.
تقنية ActiveX
تعتبر تقنية ActiveX تقنية مهمة جداً، ويعتمد عليها ويندوز بشكل كبير، وهي بتعريف بسيط: إمكانية تشغيل وحدة نمطية تنفيذية EXE Module، التي تمثل برنامجاً كاملاً، أو جزء من برنامج، أو عنصر تحكم، داخل برنامجك الرئيسي.
بكلام آخر، تضمين برنامجٍ آخر في برنامجك، بدون كتابة سطر إضافي من نص البرنامج.
مثلاً، لو أردت تصميم برنامجٍ، يُشغل ملفات الوسائط المتعددة، مثل ملفات الصوت Wave، أو ملفات الأفلام والحركة AVI، أو ملفات الموسيقى MIDI، لاحتجت إلى وقت طويل جداً لكتابة هذا البرنامج، مع استخدام الكثير من توابع API، (هذا إذا استطعت كتابته أصلاً)، هذا بالإضافة إلى إهدار الكثير من الجهد والوقت.
بدلاً من ذلك، يمكنك الاستفادة من برنامج جاهز (قابل للدمج مع برنامجك الرئيسي)، يقوم بنفس العمل الذي تود تنفيذه. تصور الكسب في الوقت والجهد الذي اختصرته لبناء تطبيقك الرئيسي، وصرف هذا الوقت والجهد عليه.
يشبه هذا الأمر عملية بناء منزل مثلاً، وطلبت من المتعهد فيجول بيسك، بناء هذا المنزل تحت إشرافك الشخصي، هنا لديك احتمالين:
إما أن تبني المنزل كاملاً بنفسك، بمساعدة المتعهد فيجول بيسك.
أو شراء بعض الأشياء الجاهزة من شركات أخرى، كالأبواب والنوافذ والأثاث مثلاً.
تصور الوقت المختصر في الاحتمال الثاني، الذي ينعكس على سرعة الإنجاز. ولا بد أنك تخيلت الآن طريقة عمل تقنية ActiveX، وما توفره من ميزات كثيرة.
في الحقيقة، لقد استعملت هذه التقنية منذ بداية هذا الكتاب.
فزر الأمر Command Button مثلاً، هو عنصر تحكم ActiveX، وجميع الأدوات التي استخدمتها سابقاً هي عناصر تحكم ActiveX.تسمى هذه العناصر بالعناصر القياسية التي تأتي أصلاً مع لغة فيجول بيسك، وهي ليست ملفات منفصلة بل موجودة في نواة اللغة نفسها.
تأتي بعض العناصر الأخرى مع فيجول بيسك أيضاً، ولكنها منفصلة عنه (موجودة في ملف منفصل بامتداد OCX).
لو عدنا لزر الأمر، لوجدنا أن له عملاً معيناً، هو تنفيذ نص برنامج ما، عند النقر عليه، وهو ما فعلناه في معظم أمثلة هذا الكتاب، لكن ألم تسأل نفسك، كيف يغير هذا الزر شكله عند النقر عليه، وأين هي أسطر البرنامج المسئولة عن فعل ذلك؟. قس هذا الأمر على باقي الأدوات والعناصر الأخرى.
للإجابة على هذا السؤال نقول: تعتبر هذه العناصر في الحقيقة، عناصر تحكم تعمل بتقنية ActiveX، وهي عبارة عن وحدة نمطية تنفيذية، لا تعمل بشكل منفصل، إنما ضمن تطبيق رئيسي. (مثل الباب في مثالنا السابق عن بناء المنزل، فالباب بحد ذاته، لا يركب بدون منزل).
دعنا الآن نلخص مزايا استخدام تقنية ActiveX:
تطوير أسرع للبرامج: يوفر استخدام عناصر تحكم ActiveX الوقت اللازم ليناء البرنامج الرئيسي، بدلاً من ضياعه في توفير مزايا موجودة أصلاً. بكلام آخر، أنت لست مضطراً لاختراع العجلة من جديد.
ثقة أعلى لتطبيقاتك: طورت عناصر التحكم ActiveX التي تستخدمها، شركات خاصة، مهمتها توفير هذه العناصر وبيعها، تحت إشراف مبرمجين مختصين. هذا الأمر يضمن لك وثوقية عالية في تطبيقاتك، التي تعني عدم حصول أخطاء غير متوقعة، لأن هذه العناصر قد اختبرت بشكل كامل، وهي خالية تقريباً من الأخطاء والشوائب.
تقليل الوقت اللازم للتعلم: تعمل جميع عناصر تحكم ActiveX بنفس الطريقة تقريباً، وبمجرد تعلم مبدأ عمل تقنية ActiveX، تستطيع استخدام باقي العناصر، مع القليل من معرفة خصوصية كل عنصر بالذات. بالإضافة إلى أنك قد تستخدم عنصر تحكم ما، وأنت لا تعرف بالضبط، كيفية عمل هذا العنصر داخلياً (في الحقيقة، لا يهمك كثيراً كيفية عمله). وبذلك تكون قد وفرت وقتاً طويلاً في تعلم كيف يقوم هذا العنصر بعمله، لو أردت تنفيذ هذا العمل بنفسك.
واجهة استخدام مألوفة للمستخدم: يجعل استخدام عناصر التحكم ActiveX القياسية، برنامجك أو تطبيقك ذو واجهة استخدام مألوفة من قبل المستخدم، وهي مشابهة لباقي واجهات التطبيقات الأخرى، التي اعتاد وتدرب المستخدم عليها. تصور لو أنك أنشأت زر أمر خاص بك، ومختلف عن زر الأمر القياسي، توقع عندئذ أن المستخدم قد لا يعرف أن هذا الشيء الذي أنشأته هو زر أمر.
قواعد استخدام عناصر ActiveX
هناك بعض القواعد الرئيسية التي يجب اتباعها عند استخدام أدوات ActiveX:
لا تسرف في استخدام أدوات ActiveX، بل استخدم ما يلزمك منها فقط. لأن كثرة الأدوات في تطبيقاتك، سوف تبطئ عمل التطبيق بشكل ملحوظ، وخصوصاً عند بداية التنفيذ.
حاول قدر الإمكان، استخدام الأدوات القياسية التي تأتي أصلاً مع لغة فيجول بيسك. وبذلك تحصل على عدة مزايا منها:
ضمان استمرار تطوير هذه العناصر من قبل Microsoft في الإصدارات الجديدة من فيجول بيسك (وهو ما لن تستطيع ضمانه مع الشركات الأخرى، فيما لو استخدمت عناصرها).
تقليل حجم البرنامج الكلي (أقراص الإعداد).
التأكد أن هذه الأدوات القياسية، تعمل بشكل خال من الأخطاء تقريباً، وبتوافق عالي مع النظام ككل.
يظهر برنامجك بالنسبة للمستخدم بشكل مألوف (سرعة في التعلم).
هناك قاعدة تقول: إذا استطعت الاستغناء عن عنصر تحكم ActiveX بقليل من الجهد، فافعل ذلك فوراً. لأن هذا الأمر يزيد من سرعة تنفيذ وثقة تطبيقك بآن واحد.
لا تستخدم عناصر التحكم ActiveX ذات الإصدار الدعائي أو الاستعراضي
Demo Version، بل استخدم العناصر الأصلية الكاملة والمسجلة Register. يسبب استخدام العناصر الدعائية الكثير من المشاكل، وهي نسخة غير قابلة للتوزيع غالباً. طبعاً، الاستخدام الذي قصدته هو الاستخدام النهائي، وليس بقصد تجربة العنصر. هذا يعني أنه يمكنك استخدام العنصر الدعائي لتجربته فقط، ولكن لا تضعه أبداً في أقراص الإعداد.
برنامج الوسائط المتعددة
يوضح لنا برنامج الوسائط المتعددة، كيفية استخدام عنصر التحكم Microsoft Multimedia (اسم الملف هو MCI32.OCX)، لإنشاء برنامج يمكنه تشغيل ملفات الوسائط المتعددة.
يتمكن برنامج الوسائط المتعددة (بالاعتماد على العنصر MCI32.OCX)، من فتح ملفات الصوت ذات الامتداد WAV، وفتح ملفات الحركة ذات الامتداد AVI، وأيضاً فتح ملفات الموسيقى ذات الامتداد MID.
يوفر برنامج الوسائط المتعددة، واجهة استخدام سهلة، وقائمة تمكننا من فتح أحد أنواع الملفات الثلاثة السابقة، بعد فتح الملف يمكننا:
عزف الملف Play.
إيقاف عزف الملف Stop.
إيقاف مؤقت، لعزف الملف Pause.
إعادة المؤشر في أول الملف Back.
وضع المؤشر في نهاية الملف End.
تقديم الملف صورة للأمام Next Frame.
ترجيع الملف صورة للخلف Previous Frame.انظر الشكل 19-1.
الشكل 19-1 برنامج الوسائط المتعددة.
كما يوفر برنامج الوسائط المتعددة، بعض المعلومات عن الملف الحالي تتلخص فيما يلي:
اسم ومسار الملف الحالي المفتوح.
طول الملف الحالي (تتغير وحدة الطول حسب نوع الملف).
موقع العزف الحالي من الملف (إظهاره كرقم صحيح).
مؤشر يدلنا على موقع العزف الحالي في الملف، بمساعدة شريط الإزاحة الأفقي.
إنشاء برنامج الوسائط المتعددة
لنعمل الآن على إنشاء برنامج الوسائط المتعددة:
أنشئ الدليل C:\VB5Prg\Ch19، لكي تحفظ عملك فيه.
ابدأ مشروعاً جديداً بنوع Standard EXE.
احفظ النموذج From1 باسم MCI.frm، في الدليل C:\VB5Prg\Ch19. واحفظ المشروع باسم MCI.Vbp في نفس الدليل السابق.
إضافة عنصر تحكم OCX إلى المشروع
قبل التمكن من وضع عنصر OCX على النموذج، يجب أولاً إضافته إلى المشروع نفسه.
سنضيف العنصر MCI32.OCX إلى مشروعنا MCI.Vbp:
اختر البند Component من قائمة Project.
يستجيب فيجول بيسك بإظهار مريع الحوار Component.
اختر البند Microsoft Multimedia Control 5.0 من صفحة Controls في مربع الحوار Components (انظر الشكل 19-2).
الشكل 19-2 إظهار مربع الحوار Components لاختيار عنصر تحكم الوسائط المتعددة.
قبل الخروج من مربع الحوار Components، اختر البند
Microsoft Common Dialog Control 5.0 أيضاً، لأننا سنحتاجه في برنامج الوسائط المتعددة.
انقر الزر OK للخروج من مربع الحوار Components.
بعد تنفيذ الخطوات السابقة، ينبغي ظهور رمزين جديدين: أحدهما لعنصر تحكم الوسائط المتعددة والثاني لعنصر تحكم مربعات الحوار الشائعة. (انظر الشكل 19-3).
الشكل 19-3 نافذة الأدوات بعد إضافة عنصري الوسائط المتعددة ومربعات الحوار الشائعة.
التصميم المرئي لبرنامج الوسائط المتعددة
لنبدأ الآن عملية التصميم المرئي لبرنامج الوسائط المتعددة:
أسند القيم الموضحة لاحقاً، للخصائص التي تتبع لها للنموذج الافتراضي Form1:
Name: frmMCI
Caption: برنامج الوسائط المتعددة
RightToLeft: True
اربط القائمة الموضحة بالجدول 19-1 مع النموذج frmMCI.
جدول 19-1. قائمة النموذج frmMCI.
Caption Name
&ملف mnuFile
…فتح ملف &صوت mnuOpenWave
…فتح ملف &حركة mnuOpenAVI
…فتح ملف &موسيقى mnuOpenMIDI
…- mnuSep1
…&خروج mnuExit
أضف عنصر الوسائط المتعددة للنموذج frmMCI، وأسند القيمة mciMyMedia للخاصية Name.
أضف عنصر مربعات الحوار الشائعة للنموذج frmMCI، وأسند القيمة dlgGetFile للخاصية Name.
بعد الانتهاء من الخطوات السابقة، ينبغي أن يصبح النموذج frmMCI، كما في الشكل 19-4.
الشكل 19-4 النموذج frmMCI بعد إضافة القائمة وعنصري الوسائط المتعددة ومربعات الحوار الشائعة.
لنكمل الآن عملية بناء النموذج frmMCI:
أضف عنصر تحكم الوقت Timer للنموذج frmMCI.
أسند له الخصائص التالية:
Name: tmrGetPosition
Interval: 50
Enabled: False
أضف باقي العناصر وفقاً للجدول 19-2 (انتبه لأنك أضفت بعض العناصر الموجودة في الجدول 19-2).
جدول 19-2 العناصر المكونة لبرنامج الوسائط المتعددة وخصائصها.
الكائن الخاصية القيمة
Form Name frmMCI
Caption برنامج الوسائط المتعددة
RightToLeft True
MMControl Name mciMyMedia
Common Dialy Name dlgGetFile
Timer Name tmrGetPosition
Interval 50
Enabled False
Label Name lblTitle1
Caption اسم الملف الحالي
Label Name lblTitle2
Caption الموقع الحالي
Label Name lblTitle3
Caption طول الملف
الكائن الخاصية القيمة
Label Name lblCurrentFile
Caption فارغ
Label Name lblCurPosition
Caption فارغ
Label Name lblLastPosition
Caption فارغ
HscrollBar Name hsbPosition
بعد الانتهاء من إضافة جميع العناصر الموجودة في الجدول السابق، ينبغي أن يظهر النموذج frmMCI كما في الشكل 19-5.
الشكل 19-5 النموذج frmMCI بعد الانتهاء من عملية تصميمه.
كتابة نص برنامج الوسائط المتعددة
بعد الانتهاء من تصميم النموذج frmMCI، علينا كتابة نص البرنامج:
اكتب الأسطر التالية في الإجراء mnuOpenWave_Click():
Private Sub mnuOpenWave_Click()
Dim mmFileName As String
'filename تهيئة الخاصية
dlgGetFile.filename = ""
'تحديد نوع الملف الذي سيفتحه مربع الحوار
dlgGetFile.Filter = "ملفات الصوت(*.wav)|*.wav"
'إظهار مربع الحوار فتح ملف
dlgGetFile.ShowOpen
'mmFileName إسناد الملف الذي اختاره المستخدم للمتحول
mmFileName = dlgGetFile.filename
'إذا لم يختر المستخدم ملفا، فاخرج من الإجراء فورا
If mmFileName = "" Then
Exit Sub
End If
'إغلاق الجهاز السابق في حال وجود جهاز مفتوح
mciMyMedia.Command = "Close"
'تحديد نوع الجهاز بأنه جهاز ملفات الصوت
mciMyMedia.DeviceType = "WaveAudio"
'تحديد الملف المراد فتحه
mciMyMedia.filename = mmFileName
'إعطاء أمر فتح للجهاز الصوتي
mciMyMedia.Command = "Open"
'تحديد أكبر موقع ممكن لشريط الإزاحة الأفقي
hsbPosition.Max = mciMyMedia.Length
'عرض قيمة طول الملف في أداة العنونة
lblLastPositiom.Caption = mciMyMedia.Length
'عرض الملف الحالي في أداة العنونة
lblCurrentFile.Caption = mmFileName
End Sub
اكتب الأسطر التالية في الإجراء mnuOpenAVI_Click():
Private Sub mnuOpenAVI_Click()
Dim mmFileName As String

'filename تهيئة الخاصية
dlgGetFile.filename = ""
'تحديد نوع الملف الذي سيفتحه مربع الحوار
dlgGetFile.Filter = "ملفات الحركة(*.avi)|*.avi"
'إظهار مربع الحوار فتح ملف
dlgGetFile.ShowOpen
'mmFileName إسناد الملف الذي اختاره المستخدم للمتحول
mmFileName = dlgGetFile.filename
'إذا لم يختر المستخدم ملفا، فاخرج من الإجراء فورا
If mmFileName = "" Then
Exit Sub
End If

'إغلاق الجهاز السابق في حال وجود جهاز مفتوح
mciMyMedia.Command = "Close"
'تحديد نوع الجهاز بأنه جهاز ملفات الحركة
mciMyMedia.DeviceType = "AVIVideo"
'تحديد الملف المراد فتحه
mciMyMedia.filename = mmFileName
'إعطاء أمر فتح للجهاز الحركي
mciMyMedia.Command = "Open"

'تحديد أكبر موقع ممكن لشريط الإزاحة الأفقي
hsbPosition.Max = mciMyMedia.Length
'عرض قيمة طول الملف في أداة العنونة
lblLastPositiom.Caption = mciMyMedia.Length
'عرض الملف الحالي في أداة العنونة
lblCurrentFile.Caption = mmFileName
End Sub
اكتب الأسطر التالية في الإجراء mnuOpenMIDI_Click():
Private Sub mnuOpenMIDI_Click()
Dim mmFileName As String

'filename تهيئة الخاصية
dlgGetFile.filename = ""
'تحديد نوع الملف الذي سيفتحه مربع الحوار
'dlgGetFile.Filter = "All Files|(*.rmi)"
'إظهار مربع الحوار فتح ملف
dlgGetFile.ShowOpen
'mmFileName إسناد الملف الذي اختاره المستخدم للمتحول
mmFileName = dlgGetFile.filename
'إذا لم يختر المستخدم ملفا، فاخرج من الإجراء فورا
If mmFileName = "" Then
Exit Sub
End If

'إغلاق الجهاز السابق في حال وجود جهاز مفتوح
mciMyMedia.Command = "Close"
'تحديد نوع الجهاز بأنه جهاز ملفات الموسيقى
mciMyMedia.DeviceType = "Sequencer"
'تحديد الملف المراد فتحه
mciMyMedia.filename = mmFileName
'إعطاء أمر فتح للجهاز الصوتي
mciMyMedia.Command = "Open"
'تحديد أكبر موقع ممكن لشريط الإزاحة الأفقي
hsbPosition.Max = mciMyMedia.Length
'عرض قيمة طول الملف في أداة العنونة
lblLastPositiom.Caption = mciMyMedia.Length
'عرض الملف الحالي في أداة العنونة
lblCurrentFile.Caption = mmFileName
End Sub
اكتب الأسطر التالية في الإجراء mnuExit_Click():
Private Sub mnuExit_Click()
End
End Sub
اكتب الأسطر التالية في الإجراء trmGetPosition_Timer():
Private Sub tmrGetPosition_Timer()
lblCurPosition.Caption = mciMyMedia.Position
hsbPosition.Value = mciMyMedia.Position
End Sub
اكتب الأسطر التالية في الإجراء mciMyMedia_PlayClick():
Private Sub mciMyMedia_Click()

End Sub
اكتب الأسطر التالية في الإجراء Form_Unload():
Private Sub Form_Unload(Cancel As Integer)
mciMyMedia.Command = "Close"
End Sub
احفظ عملك الآن.
تنفيذ برنامج الوسائط المتعددة
بعد الانتهاء من كتابة نص البرنامج، يصبح جاهزاً للتنفيذ:
نفّذ البرنامج بضغط المفتاح F5.
يستجيب فيجول بيسك بإظهار نافذة برنامج الوسائط المتعددة.
اختر البند فتح ملف صوتي من قائمة ملف.
يستجيب برنامج الوسائط المتعددة بإظهار مربع الحوار فتح.
اختر أحد الملفات الصوتية التي لها الامتداد Wav، ثم انقر الزر فتح في مربع الحوار فتح.
تجد أمثلة عن ملفات الصوت في القرص المدمج المرفق مع الكتاب، في دليل الوسائط المتعددة.
يعرض برنامج الوسائط المتعددة اسم الملف الذي اخترته ومساره الكامل، كما يعرض أيضاً طول الملف بوحدة جزء من الألف من الثانية.
استعد برنامج الوسائط المتعددة لعزف الملف الذي اخترته:
انقر الزر Play الموجود على عنصر تحكم الوسائط المتعددة.
يستجيب برنامج الوسائط المتعددة بعزف الملف الذي اخترته، ويظهر لك الموقع الحالي للعزف بطريقتين:
رقم يحدد الزمن الذي تم عزفه إلى الآن.
استخدام مؤشر شريط الإزاحة الأفقي.
لإعادة عزف الملف مرة ثانية، يجب نقر الزر Back (السهم الموجود فى أقصى اليسار)، لإعادة مؤشر العزف إلى بداية الملف مرة أخرى، ثم نقر الزر Play.
أثناء عزف الملف، تستطيع نقر الزر Stop (مربع غامق)، لإيقاف العزف نهائياً، أو زر Pause (خطين شاقوليين) لإيقاف العزف مؤقتاً.
لعزف نوع آخر من الملفات وليكن ملفات الحركة، اختر البند فتح ملف حركة من قائمة ملف، واختر أحد الملفات التي لها الامتداد AVI (ملفات حركة).
تجد أمثلة عن ملفات الحركة، في القرص المدمج المرفق مع الكتاب، في دليل الوسائط المتعددة.
يعرض البرنامج أيضاً معلومات عن الملف الذي اخترته مثل اسم الملف ومساره الكامل، وطول الملف بالثواني.
انقر الزر Play لعرض الملف الذي اخترته.
يستجيب برنامج الوسائط المتعددة بفتح نافذة، يعرض الفيلم (ملف AVI) عبرها. وعنوان النافذة عبارة عن اسم الملف الذي يتم عرضه فيها.
انقر الزر Next Frame أو الزر Previous Frame، لعرض الملف صورة صورة (Frame by Frame).
تستطيع إغلاق نافذة عرض الفيلم بنقر أيقونة الإغلاق في النافذة نفسها، أو ببساطة فتح ملف آخر (مهما كان نوعه). لأن فتح ملف جديد يتسبب في إغلاق الملف الحالي آلياً.
لفتح النوع الثالث من ملفات الوسائط المتعددة:
اختر البند فتح ملف موسيقي من قائمة ملف، واختر أحد الملفات التي لها الامتداد MID.
تجد أمثلة عن ملفات الموسيقى في القرص المدمج المرفق مع الكتاب، في دليل الوسائط المتعددة.
انقر الزر Play لعزف الملف الموسيقي الذي اخترته.
تمرن على البرنامج بجميع أقسامه ثم اختر البند خروج من قائمة ملف لإنهاء البرنامج.
كيف يعمل برنامج الوسائط المتعددة
يعتمد برنامج الوسائط المتعددة اعتماداً أساسياً على عنصر تحكم الوسائط المتعددة mciMyMedia. وتنحصر وظيفة البرنامج في تحديد الخصائص، وإعطاء الأوامر لهذا العنصر، ليقوم بفتح وعزف ملفات الوسائط المتعددة المختلفة.
نص البرنامج للإجراء mnuOpenWave_Click()
ينفذ هذا الإجراء عند اختيار المستخدم البند فتح ملف صوتي من قائمة ملف في برنامج الوسائط المتعددة. يسمح هذا الإجراء للمستخدم، باختيار ملف صوتي (WAV)، ومن ثم فتحه وعزفه.
لقد كتبت النص التالي في الإجراء mnuOpenWave_Click():
Private Sub mnuOpenWave_Click()
Dim mmFileName As String

'filename تهيئة الخاصية
dlgGetFile.filename = ""
'تحديد نوع الملف الذي سيفتحه مربع الحوار
dlgGetFile.Filter = "ملفات الصوت(*.wav)|*.wav"
'إظهار مربع الحوار فتح ملف
dlgGetFile.ShowOpen
'mmFileName إسناد الملف الذي اختاره المستخدم للمتحول
mmFileName = dlgGetFile.filename
'إذا لم يختر المستخدم ملفا، فاخرج من الإجراء فورا
If mmFileName = "" Then
Exit Sub
End If
'إغلاق الجهاز السابق في حال وجود جهاز مفتوح
mciMyMedia.Command = "Close"
'تحديد نوع الجهاز بأنه جهاز ملفات الصوت
mciMyMedia.DeviceType = "WaveAudio"
'تحديد الملف المراد فتحه
mciMyMedia.filename = mmFileName
'إعطاء أمر فتح للجهاز الصوتي
mciMyMedia.Command = "Open"
'تحديد أكبر موقع ممكن لشريط الإزاحة الأفقي
hsbPosition.Max = mciMyMedia.Length
'عرض قيمة طول الملف في أداة العنونة
lblLastPositiom.Caption = mciMyMedia.Length
'عرض الملف الحالي في أداة العنونة
lblCurrentFile.Caption = mmFileName
End Sub
صرحت العبارة الأولى عن المتحول mmFileName، ووظيفته تخزين اسم الملف الذي اختاره المستخدم. أما العبارة:
dlgGetFile.filename = ""
تهيئ الخاصية FileName التابعة لمربع الحوار dlgGetFile وإسناد القيمة "لا شيء" لها.
بعد ذلك، جاء دور معرفة نوع الملف الذي سيفتحه المستخدم (معرفة امتداد الملف) عن طريق العبارة التالية:
dlgGetFile.Filter = "ملفات الصوت(*.wav)|*.wav"
يتم إسناد أنواع الملفات التي يستطيع مربع الحوار فتحها، إلى الخاصية Filterالتابعة لمربع الحوارdlgGetFile.
بعد معرفة نوع الملفات التي نريد فتحها، نعطي الأمر بالظهور لمربع الحوار فتح، عن طريق الأمر ShowOpen وذلك كالتالي:
dlgGetFile.ShowOpen
تتوقف عملية التنفيذ عند هذا السطر، لحين انتهاء المستخدم من اختيار ملف ما، ونقر الزر فتح الموجود في مربع الحوار.
هنا لدينا احتمالان:
اختار المستخدم ملفاً صوتياً.
لم يختر المستخدم أي ملف، أو نقر الزر إلغاء الأمر في مربع الحوار.
لمعرفة نوع الاحتمال الحاصل، لجأنا إلى فحص اسم الملف الذي اختاره المستخدم، عن طريق العبارة If … Then التالية:
If mmFileName = "" Then
Exit Sub
End If
يفحص هذا الشرط قيمة المتحول mmFileName، الممثل لاسم الملف الذي اختاره المستخدم، إذا كانت قيمته تساوي "لا شيء"، (لم يختر المستخدم ملفاً)، فإنه ببساطة يخرج بدون إكمال تنفيذ باقي الإجراء.
لا بد أن تكون لاحظت الآن، لماذا قمنا بتهيئة الخاصية FileName التابعة لمربع الحوار، وإسناد القيمة "لا شيء" لها، قبل إظهار مربع الحوار. لأننا سنفحص هذه الخاصية بعد الخروج من مربع الحوار، ونرى هل أصبح لها قيمة أخرى غير قيمة "لا شيء"، والتي تعني أن المستخدم لم يختر ملفاً كما ذكرنا سابقاً.
ينفذ باقي الإجراء، عند اختيار ملف صوتي، ويبدأ من العبارة التالية:
mciMyMedia.Command = "Close"
تُغلق هذه العبارة، أي جهاز مفتوح مسبقاً، (يقصد بالجهاز هنا: أحد ملفات الوسائط المتعددة المفتوحة والجاهزة للعزف).
بعد إغلاق الجهاز المفتوح (في حال وجوده)، يُحدد نوع الجهاز المطلوب فتحه أو تشغيله (وهو في هذه الحالة، الجهاز "Wave Audio"). يحدد نوع الجهاز حسب نوع الملف المطلوب فتحه.
إذا كان نوع الملف صوتياً، يحدد الجهاز على أنه من النوع "Wave Audio"، أما في حال كونه موسيقياً، يكون نوع الجهاز الصحيح هو "Sequencer"، وفي حال كونه نوع الجهاز فيلماً متحركاً، يكون نوع الجهاز "AVI Video".
نُسند نوع الجهاز المطابق، للخاصية DeviceType التابعة لعنصر الوسائط المتعددة كالتالي:
mciMyMedia.DeviceType = "WaveAudio"
بعد تحديد نوع الجهاز المطلوب، نسند اسم الملف الذي اختاره المستخدم إلى الخاصية FileName التابعة لعنصر الوسائط المتعددة mciMyMedia، حتى يتعرف عنصر الوسائط المتعددة على اسم ومسار الملف المراد فتحه.
بعد معرفة اسم الملف، نُعطى لعنصر الوسائط المتعددة، الأمر Open عن طريق العبارة التالية:
mciMyMedia.Command = "Open"
ليعمل على فتح الملف وتهيئته للعزف، ومعرفة كل المعلومات الخاصة بهذا الملف.
أحد هذه المعلومات، هي طول الملف الصوتي، (بوحدة الملي ثانية)، حيث نستطيع الحصول عليها عن طريق الخاصية Length التابعة لعنصر الوسائط المتعددة mciMyMedia.
استفدنا من قيمة طول الملف الصوتي، في تحديد أكبر مجال ممكن لشريط الإزاحة الأفقي، عن طريق إسناد هذه القيمة للخاصية Max التابعة لشريط الإزاحة الأفقي كالتالي:
hsbPosition.Max = mciMyMedia.Length
أظهرنا قيمة طول الملف الصوتي في اللافتة، حتى يعرف المستخدم طول الملف المفتوح، بأجزاء من الألف من الثانية، وذلك كالتالي:
lblLastPosition.Caption = mciMyMedia.Length
أيضاً، أظهرنا اسم الملف ومساره الكامل، (حتى يعرف المستخدم اسم الملف المفتوح الحالي) في لافتة أخرى، عن طريق العبارة التالية:
lblCurrentFile.Caption = mmFileName
بعد الانتهاء من تنفيذ كامل عبارات هذا الإجراء، يصبح الملف الذي اختاره المستخدم جاهزاً للعزف.
نص البرنامج للإجراء mnuOpenMIDI_Click ()
ينفذ هذا الإجراء عند اختيار المستخدم البند فتح ملف موسيقى من قائمة ملف:
Private Sub mnuOpenMIDI_Click()
Dim mmFileName As String
'filename تهيئة الخاصية
dlgGetFile.filename = ""
'تحديد نوع الملف الذي سيفتحه مربع الحوار
dlgGetFile.Filter = "ملفات الموسيقى(*.mid)|*.mid"
'إظهار مربع الحوار فتح ملف
dlgGetFile.ShowOpen
'mmFileName إسناد الملف الذي اختاره المستخدم للمتحول
mmFileName = dlgGetFile.filename
'إذا لم يختر المستخدم ملفا، فاخرج من الإجراء فورا
If mmFileName = "" Then
Exit Sub
End If
'إغلاق الجهاز السابق في حال وجود جهاز مفتوح
mciMyMedia.Command = "Close"
'تحديد نوع الجهاز بأنه جهاز ملفات الموسيقى
mciMyMedia.DeviceType = "Sequencer"
'تحديد الملف المراد فتحه
mciMyMedia.filename = mmFileName
'إعطاء أمر فتح للجهاز الصوتي
mciMyMedia.Command = "Open"
'تحديد أكبر موقع ممكن لشريط الإزاحة الأفقي
hsbPosition.Max = mciMyMedia.Length
'عرض قيمة طول الملف في أداة العنونة
lblLastPositiom.Caption = mciMyMedia.Length
'عرض الملف الحالي في أداة العنونة
lblCurrentFile.Caption = mmFileName
End Sub
يعمل هذا الإجراء، بنفس الأسلوب الذي شرحناه سابقاً مع وجود اختلافين اثنين هما:
تحديد نوع الملف الذي يستطيع المستخدم اختياره عن طريق مربع الحوار، على أنه النوع ذو الامتداد (MID). والعبارة المسئولة عن ذلك هي:
dlgGetFile.Filter = "ملفات الموسيقى(*.mid)|*.mid"
تحديد نوع جهاز آخر يمكنه فتح الملفات الموسيقية، وهو الجهاز ذو النوع "Sequencer"، عن طريق العبارة التالية:
mciMyMedia.DeviceType = "Sequencer"
نص البرنامج للإجراء mnuOpenAVI_Click()
ينفذ هذا الإجراء آلياً، عند اختيار البند فتح ملف حركة من قائمة ملف:
Private Sub mnuOpenAVI_Click()
Dim mmFileName As String

'filename تهيئة الخاصية
dlgGetFile.filename = ""
'تحديد نوع الملف الذي سيفتحه مربع الحوار
dlgGetFile.Filter = "ملفات الحركة(*.avi)|*.avi"
'إظهار مربع الحوار فتح ملف
dlgGetFile.ShowOpen
'mmFileName إسناد الملف الذي اختاره المستخدم للمتحول
mmFileName = dlgGetFile.filename
'إذا لم يختر المستخدم ملفا، فاخرج من الإجراء فورا
If mmFileName = "" Then
Exit Sub
End If

'إغلاق الجهاز السابق في حال وجود جهاز مفتوح
mciMyMedia.Command = "Close"
'تحديد نوع الجهاز بأنه جهاز ملفات الحركة
mciMyMedia.DeviceType = "AVIVideo"
'تحديد الملف المراد فتحه
mciMyMedia.filename = mmFileName
'إعطاء أمر فتح للجهاز الحركي
mciMyMedia.Command = "Open"

'تحديد أكبر موقع ممكن لشريط الإزاحة الأفقي
hsbPosition.Max = mciMyMedia.Length
'عرض قيمة طول الملف في أداة العنونة
lblLastPositiom.Caption = mciMyMedia.Length
'عرض الملف الحالي في أداة العنونة
lblCurrentFile.Caption = mmFileName
End Sub
يعمل هذا الإجراء أيضاً، بنفس أسلوب عمل الإجراءين السابقين، ومع وجود نفس الاختلافين السابقين وهما:
تحديد نوع الملفات التي نريد اختيارها من مربع الحوار، على أنها من النوع AVI، وذلك كالتالي:
dlgGetFile.Filter = "ملفات الحركة(*.avi)|*.avi"
تحديد نوع الجهاز القادر على عرض الملف الحركي، وهو الجهاز ذو النوع "AVIVideo"، عن طريق العبارة التالية:
mciMyMedia.DeviceType = "AVIVideo"

ملاحظة
يتطلب برنامج الوسائط المتعددة وجود بطاقة صوت، لإصدار الأصوات والموسيقى من خلاله، أما إظهار الملفات الحركية، فهي لا تتطلب بطاقات إضافية.
التقنية المستخدمة لعرض الموقع الحالي خلال عزف الملف
بعد اختيار أحد ملفات الوسائط المتعددة، وفتحه عن طريق القائمة ملف، يصبح البرنامج جاهزاً لعزف هذا الملف، عن طريق النقر على الزر Play، يظهر لك الموقع الحالي للعزف خلال عزفه، بأسلوبين:
إظهار الموقع الحالي للعزف، كرقم يمثل الوقت الذي انقضى منه، في اللافتة lblCurPosition.
إظهار الموقع الحالي للعزف، عن طريق مؤشر شريط الإزاحة الأفقي hsbPosition.
كيف يعلم البرنامج الموقع الحالي للعزف ويظهره للمستخدم؟
نستطيع معرفة الموقع الحالي للعزف، عن طريق قراءة قيمة الخاصية Position التابعة لعنصر الوسائط المتعددة mciMyMedia.
لكننا نريد معرفة الموقع الحالي للعزف، خلال مرحلة العزف نفسها، وعلى فترات صغيرة جداً. لذلك استخدمنا لهذه الغاية، عنصر تحكم الميقاتية Timer، وجعلناه يقرأ الموقع الحالي للعزف، وإظهاره كل 1/20 من الثانية.
أسندنا القيمة 50 للخاصية Interval التابعة للميقاتية trmGetPosition، خلال مرحلة التصميم، وتعني تنفيذ الحادثة Timer التابعة للميقاتية، كل 50 ميلي ثانية.
نص البرنامج المكتوب في الحادثة Timer هو:
Private Sub tmrGetPosition_Timer()
lblCurPosition.Caption = mciMyMedia.Position
hsbPosition.Value = mciMyMedia.Position
End Sub
كما قلنا سابقاً، يُنفذ هذا الإجراء آلياً كل 50 ميلي ثانية، ويُظهر قيمة الخاصية Position التابعة لعنصر الوسائط المتعددة (الممثلة لموقع العزف الحالي)، في اللافتة lblCurPosition كالتالي:
lblCurPosition.Caption = mciMyMedia
يُسند أيضاً قيمة الخاصية Position التابعة لعنصر الوسائط المتعددة، للخاصية Value التابعة لشريط الإزاحة الأفقي، لتنقل مؤشر شريط الإزاحة الأفقي للموقع الحالي للعزف، كالتالي:
hsbPosition.Valve = mciMyMedia.Position
وبذلك نضمن تحديث دائم، لموقع العزف الحالي الظاهر للمستخدم.
لكن توجد مشكلة مع التوقيت، هل عرفتها؟.
يعمل التوقيت دائماً خلال مرحلة عزف الملف، وخلال فترة التوقف أيضاً، وهذا الأمر غير مقبول برمجياً (عمل التوقيت الدائم، خلال فترة تنفيذ البرنامج).
إذاً، يجب تشغيل الميقاتية خلال فترة عزف الملف فقط، وإيقافه في الفترات الأخرى، وذلك عن طريق الخاصية Enabled، التي تعطّله إذا أُسندت القيمة False إليه، أو تجعله يعمل إذا أُسندت القيمة True إليها.
أسندنا القيمة False للخاصية Enabled التابعة للتوقيت، خلال مرحلة تصميم البرنامج، لأننا نريد تعطيل التوقيت عند بداية تشغيل البرنامج. لذلك، يجب تفعيل التوقيت فقط، خلال فترة عزف الملف، وتعطيلها خارج هذه الفترة.
يوفّر عنصر تحكم الوسائط المتعددة، الحادثة Play_Click()، التي تنفذ آلياً عند نقر المستخدم للزر Play (بدء العزف)، وهي أنسب مكان لوضع العبارة التي تفعّل التوقيت، وذلك كالتالي:
Private Sub mciMyMedia_PlayClick(Cancel As Integer)
tmrGetPosition.Enabled = True
End Sub
بعد الانتهاء من العزف، ينفذ عنصر تحكم الوسائط المتعددة الحادثة Done (نهاية العزف) آلياً. لذلك، هذه الحادثة تعتبر الموقع المناسب لوضع العبارة التي تعطّل التوقيت مرة ثانية، (لأن العزف انتهى، ولا داعي لبقاء التوقيت تعمل في هذه الفترة). وذلك كالتالي:
Private Sub mciMyMedia_Done(NotifyCode As Integer)
tmrGetPosition.Enabled = False
End Sub
نص البرنامج للإجراء Form_Unload ()
ينفذ الإجراء Form_Unload() آلياً، عند إنهاء البرنامج وإزالته من ذاكرة ويندوز. كما أن الحادثة Form_Load() تنفذ آلياً، عند بداية تشغيل البرنامج ووضع النافذة في الذاكرة.
لضمان إغلاق كافة الأجهزة المفتوحة من قِبل عنصر تحكم الوسائط المتعددة، وضعنا العبارة التالية في الإجراء Form_Unload() كالتالي:
Private Sub Form_Unload(Cancel As Integer)
mciMyMedia.Command = "Close"
End Sub
تطوير برنامج الوسائط المتعددة
سنطور الآن برنامج الوسائط المتعددة، ليصبح قادراً على قراءة الأقراص الليزرية الموسيقية.
أضف بنداً جديداً للقائمة ملف، باسم mnuOpenCDAudio، وعنوان فتح قرص ليزري موسيقي.
بعد إضافة البند الجديد، ينبغي أن يصبح البرنامج كما في الشكل 19-6.
الشكل 19-6 برنامج الوسائط المتعددة بعد إضافة البند فتح قرص ليزري موسيقى له.
اكتب الأسطر التالية في الإجراء mnuOpenCDAudio_Click():
Private Sub mnuOpenCDAudio_Click()
'إغلاق الجهاز السابق في حال وجود جهاز مفتوح
mciMyMedia.Command = "Close"
'تحديد نوع الجهاز بأنه جهاز القرص الموسيقي
mciMyMedia.DeviceType = "CDAudio"
'إعطاء أمر الفتح لجهاز القرص الليزري الموسيقي
mciMyMedia.Command = "Open"
hsbPosition.Max = mciMyMedia.Length
'عرض قيمة طول المسار في أداة العنونة
lblLastPositiom.Caption = mciMyMedia.Length
lblCurrentFile.Caption = "فتح القرص الليزري الموسيقي"
End Sub
لا يعتبر القرص الليزري الموسيقي ملفاً، لذلك لا حاجة لوجود مربع حوار اختيار ملف.
ينفذ هذا الإجراء آلياً عند اختيار المستخدم البند فتح قرص ليزري موسيقي من قائمة ملف.
يُغلق الجهاز السابق أولاً، ثم يُفتح الجهاز "CDAudio" الخاص بالأقراص الليزرية الموسيقية، ‏كما هو واضح من عبارات الإجراء السابق.
ملاحظة
لكي تستطيع تشغيل هذا الجزء من البرنامج، يجب تواجد قرص ليزري موسيقي لديك. وأن يكون مشغل الأقراص الليزرية موصول بسلك مباشر مع بطاقة الصوت. أو يمكنك سماع الأقراص الليزرية الموسيقية، من زر سماعة الرأس الموجود في واجهة مشغل الأقراص الليزرية.
بعد فتح الجهاز الليزري الموسيقي، يصبح عزف المسار الأول من القرص الليزري الموسيقي ممكناً، للانتقال إلى المسار اللاحق من القرص، انقر الزر NextTrack (هو نفس الزر الذي ينقلنا لنهاية الملف). للانتقال إلى المسار السابق،
انقر الزر PreviousTrack (هو نفس الزر الذي ينقلنا لبداية الملف).
انقر الزر Eject لفتح علبة مشغل الأقراص الليزرية.
لاحظ أن الأزرار التابعة لعنصر تحكم الوسائط المتعددة، تختلف معانيها تقريباً، حسب نوع الجهاز المفتوح.
أضف الآن الأسطر التالية للإجراء mciMyMedia_NextClick():
Private Sub mciMyMedia_NextClick(Cancel As Integer)
hsbPosition.Max = mciMyMedia.Length
lblLastPositiom.Caption = mciMyMedia.Length
End Sub
ينفذ هذا الإجراء آلياً، عند نقر الزر NextTrack (مسار لاحق)، حيث يقوم بإظهار طول المسار اللاحق الذي تم الانتقال إليه.
أضف الآن الأسطر التالية للإجراء mciMyMedia_PrevClick():
Private Sub mciMyMedia_PrevClick(Cancel As Integer)
hsbPosition.Max = mciMyMedia.Length
lblLastPositiom.Caption = mciMyMedia.Length
End Sub
ينفذ هذا الإجراء آلياً، عند نقر الزر PrevTrack (مسار لاحق)، وله نفس وظيفة الإجراء السابق.
لمحة عن أنواع ملفات الوسائط المتعددة
سنشرح الآن بعض أهم أنواع ملفات الوسائط المتعددة، مع ذكر أهم الفروقات بين هذه الأنواع، وسبب وجود هذه الأنواع أصلاً:
الملفات الصوتية Wave
تملك هذه الملفات الامتداد (wav)، ويخزن الصوت فيها بشكل رقمي Digital.تستطيع هذه الملفات، تخزين جميع أنواع الأصوات، مثل الموسيقى والغناء والكلام البشري أيضاً. بكلام آخر، يمكن اعتبار ملف الصوت wav، مثل جهاز التسجيل المنزلي Recorder.
يمكن تخزين الصوت في هذه الملفات على عدة تنسيقات، أهمها:
صوت 8 كيلو بايت/الثانية 8 بت أحادي 8000 هرتز
صوت 16 كيلو بايت/الثانية 8 بت استريو 8000 هرتز
صوت 43 كيلو بايت/الثانية 16 بت أحادي 22050 هرتز
صوت 86 كيلو بايت/الثانية 16 بت استريو 22050 هرتز
صوت 86 كيلو بايت/الثانية 16 بت أحادي 22050 هرتز
صوت 172 كيلو بايت/الثانية 16 بت استريو 44100 هرتز
يعتبر تخزين الصوت بتنسيق أحادي 8000 هرتز، هو أدنى جودة ممكنة، وهي مشابهة لجودة صوت سماعة التلفون.
أما تخزين الصوت بتنسيق 22050 هرتز، فهي جودة متوسطة تشابه جودة صوت الراديو.
وتخزين الصوت بتنسيق 44100 هرتز، فهي جودة عالية جداً تشابه جودة صوت القرص الليزري الموسيقي.
يأتي تخزين الصوت بجودة عالية، على حساب حجم الملف، فمثلاً، تخزين خمسة دقائق من الصوت بجودة عالية جداً وصوت ستيريو، يحتاج لحجم مقداره 172 × 5 × 60 = 51600 كيلو بايت، أو 51.6 ميجا بايت.
ولتخزين نفس الملف بجودة متوسطة مثلاً، وصوت أحادي، يحتاج لحجم مقداره 43 × 5 × 60 = 12900 كيلو بايت أو 12.9 ميغا بايت. وهكذا.
إذاً، توصلنا لنتيجة مفادها: كلما زادت جودة الصوت المسجل، كلما زاد حجم الملف الذي نسجل فيه الصوت.
الملفات الموسيقية MIDI
تصور أنك تريد تخزين الموسيقى أو النوتات الموسيقية في ملف ما، فليس من المعقول أبداً تخزين الموسيقى في ملف Wave، لأنه في هذه الحالة، سيأخذ حجماً كبيراً جداً، لذلك يمكنك تخزين النوتات الموسيقية، مع جميع الأوامر الموسيقية الأخرى، داخل الملف من النوع MID.
يكون حجم الملف MID صغيراً جداً، مقارنة مع أحجام الملفات Wave.
عند عزف الملف الموسيقي MID، يتعرف ويندوز على نوع النوتة الموسيقية التي يجب عزفها، ويرسلها كأمر إلى بطاقة الصوت (أو جهاز الأورج مثلاً)، ليصدر الصوت الخاص بهذه النوتة.
نستطيع تخيل الملف الموسيقي MID، على أنه تسجيل لضربات المفاتيح التي يقوم بها العازف على الأورج.
لا بد أنك توصلت إلى نتيجة أنه لا يمكنك تخزين صوت آخر غير النوتات الموسيقية في الملف MID، مثل صوت الكلام البشري أو الغناء.
الملفات الحركية AVI
تخزن هذه الملفات صوراً متتابعة، يتم عرضها بشكل متتالي لتشكل فيلماً متحركاً. في الحقيقة فإن هذه الملفات قادرة على تخزين الصوت أيضاً مع الصور المتحركة. وتستطيع تخيل هذه الملفات على أنها جهاز فيديو منزلي.
تأخذ هذه الملفات حجماً كبيراً جداً على وسائط التخزين، يعتمد الحجم على دقة الصور التي تخزنها، بالإضافة لعدد الألوان وجودة الصوت المخزن مع الصورة المتحركة.
هناك تنسيقات مختلفة جداً لهذا الملف منها:
تنسيق 15 صورة بالثانية الواحدة، أو 24 صورة بالثانية الواحدة، أو 30 صورة بالثانية الواحدة.
كلما زادت عدد الصور بالثانية الواحدة، زاد حجم الملف النهائي.
تعرفنا مما سبق على بعض أهم أنواع ملفات الوسائط المتعددة القياسية وكيفية تخزين المعلومات بداخلها. وأنشأت برنامجاً يستطيع عزف هذه الملفات للمستخدم.
الخلاصة
تعلمت في هذا الفصل عن تقنية OCX ActiveX، وكيف تتعامل مع كائنات ActiveX المختلفة. وتعلمت أيضاً قواعد استخدام هذه العناصر، وكيفية إضافة أحد هذه العناصر إلى مشروعك، لتتمكن من استخدامها.
تعلمت أيضاً كيفية بناء برنامج الوسائط المتعددة، الذي يتيح لك إمكانية فتح الملفات القياسية للوسائط المتعددة، مثل ملفات الصوت Wave، والموسيقى MIDI، والحركة AVI، وأيضاً تشغيل القرص الليزري الموسيقى.
أخيراً تعلمت عن الملفات القياسية للوسائط المتعددة بشكل أعمق وكيفيةة تخزين المعلومات بداخلها وتنسيقاتها المختلفة وأحجامها التقريبية.

الفصل العشرون




استخدام توابع النظام Windows API




سوف تتعلم في هذا الفصل كيفية استدعاء توابع النظام API من داخل برامج فيجول بيسك، تتيح لك هذه التقنية استخدام قوة وسرعة وشمولية هذه التوابع، مباشرة من برنامجك في فيجول بيسك.
توابع فيجول بيسك القياسية
لقد استخدمت فعلياً العديد من توابع فيجول بيسك خلال قراءتك هذا الكتاب، مثال على ذلك التابع Str() الذي يحول المتحول الرقمي إلى متحول نصي، والتابع MsgBox() الذي يُظهر رسالة للمستخدم بأزرار معينة، ومن ثم يعود بقيمة تمثل رد المستخدم على هذه الرسالة.
ماذا لو كانت هناك بعض المهام التي تريد تأديتها، غير مدعومة أو موجودة في لغة فيجول بيسك؟ في هذه الحالة، قد تجد دعماً لهذه المهمة مع توابع النظام ويندوز API، المشروحة لاحقاً في هذا الفصل؟.
مكتبات الربط الديناميكية
يمكن أن يكون امتداد ملف مكتبة الربط الديناميكية، الامتداد DLL (مثل الملف MyFile.DLL)، أو أن يكون له الامتداد EXE (مثل الملف MyFile.EXE). والأشهر هو النوع الأول، لذلك أخذ الأحرف الأولى من اسمها Dynamic Link Libraries.
تحتوي ملفات مكتبات الربط الديناميكية DLL، على توابع داخلها، يمكن استدعاؤها من أي برنامج آخر، وكأنها جزء من هذا البرنامج.
دعنا نفترض وجود ملف DLL معين، يتضمن التابع المسمى MyFunction()، ولنفترض أيضاً أن هذا التابع يتطلب وسيطاً واحداً، ويعود بقيمة معينة. وهو مشابه للتابع Str() الموجود ضمناً في فيجول بيسك، ويتطلب وسيطاً واحداً هو قيمة رقمية ما، ويعود بقيمة نصية String تمثل هذا الرقم.
تستطيع الآن، كتابة برنامج فيجول بيسك يستخدم هذا التابع MyFunction()، الموجود في الملف MyFile.DLL، في هذه الحالة يستطيع برنامجك استخدام هذا التابع، بنفس الطريقة التي تستخدم فيها أي تابع داخلي في فيجول بيسك.
بمعنى آخر، تستطيع زيادة عدد التوابع التي يمكنك استخدامها في فيجول بيسك، بواسطة تقنية مكتبات الربط الديناميكية DLL.
تعتبر الميزة الرائعة لملفات الربط الديناميكية، هي في إمكانية استخدامها من قبل أكثر من برنامج وبنفس الوقت، مختصرة بذلك الكثير من التكرار الغير ضروري، والمستهلك لمساحة القرص الصلب.
يمكن كتابة برنامج فيجول بيسك، يستدعي تابعاً معيناً من مكتبة DLL ما، يقوم هذا البرنامج خلال عملية تنفيذه، بتحميل الجزء الحاوي على شفرة التابع المستدعى، والموجودة في ملف مكتبة DLL، يقوم بتحميله في الذاكرة ومن ثم ينفذه.
يمكنك الآن فهم سبب تسمية هذه الملفات بمكتبات الربط الديناميكية.
هذه الملفات عبارة عن مكتبات من التوابع، تحمَّل هذه المكتبات (ربط هذه المكتبات) مع برنامجك حسب الحاجة فقط (ديناميكياً)، وهي ليست جزءاً من ملف برنامجك التنفيذي وإنما تتواجد في ملف منفصل عنه.
علاوةً على ذلك، يمكنك كتابة برنامج فيجول بيسك آخر، يستخدم نفس التابع الموجود في مكتبة DLL (أو تابع آخر موجود في نفس المكتبة). عند تنفيذ هذا البرنامج (والبرنامج الأول مازال منفذاً)، يصبح لديك برنامجان يقومان باستدعاء نفس التابع الموجود في الملف DLL نفسه. وفي الواقع، يمكن وجود أكثر من برنامج يقوم بالاستفادة من نفس مكتبة DLL.
بكلام ملخص جداً، تعتبر مكتبات DLL، ملفات تحوي توابع بداخلها، وهي متاحة للاستخدام من أي برنامج وفي نفس الوقت.
توابع النظام ويندوز API
قد تلاحظ (كمشغل لويندوز)، وجود العديد من المزايا المتوفرة في النظام ويندوز، مثل تحريك الفأرة، نقر الفأرة، اختيار البنود من القوائم، الخ.
بالطبع، يستطيع ويندوز تنفيذ العديد من المهام الأخرى، مثل حفظ الملفات، إظهار الصور، إدارة أجهزة الكومبيوتر المختلفة، وأداء الآلاف من العمليات الهامة الأخرى.
يعتبر ويندوز بحد ذاته برنامجاً، مثل بقية البرامج الأخرى، ولكن بالنسبة للمستخدمين، فإنهم لا يميلون لاعتباره برنامجاً، بل يعتبرونه آليةً تمكنهم من تنفيذ البرامج الأخرى (وآليةً لتطوير برامج، بواسطة لغات البرمجة مثل فيجول بيسك).
بكلمة أصح، معظم الأعمال التي ينفذها ويندوز، هي في الحقيقة استدعاءات للتوابع الموجودة في ملفات مكتبات DLL.
وعندما يريد ويندوز أداء مهمة معينة، فإنه فعلياً يستدعي التابع الخاص بهذه المهمة من خلال ملف مكتبة DLL المحتوية على هذا التابع.
لقد رأيت مسبقاً كيف أن العديد من البرامج يمكنها استخدام نفس التابع من الملف DLL نفسه وبشكل آني وهذا يعني أن برنامجك المطور في لغة فيجول بيسك يمكنه استخدام التوابع الموجودة في نفس ملف DLL والذي يستخدمه ويندوز نفسه.
والآن دعنا نرى الفوائد من استخدام التوابع التي يستخدمها ويندوز نفسه:
تعتبر مكتبات DLL التي يستخدمها ويندوز موجودة في جهازك الشخصي فعلياً، ويفترض أن مستخدمي برنامجك لديهم ويندوز أيضاً وهذا يعني أنه لا حاجة لتوزيع ملفات DLL الخاصة بويندوز (وهي كبيرة جداً) مع ملفات برنامجك، لأن ملفات الويندوز موجودة مسبقاً عل أجهزة باقي المستخدمين.
تعمل توابع مكتبات DLL بشكل جيد وخالي من الأخطاء وبذلك تضمن الثقه فى برامجك وتوافقيتها على جميع أجهزة الكمبيوتر الشخصية التي تستخدم النظام ويندوز.
لا توجد لغة برمجة يمكنها تنفيذ كل المهام التي يمكن للنظام ويندوز أن يؤديها، حتى أعقد اللغات مثل فيجول سي++، لذلك لابد لك من استخدام توابع النظام ويندوز API بشكل مباشر.
يوجد العديد من التوابع الخاصة بالنظام ككل، وعند استدعاء أحد هذه التوابع من مكتبات ويندوز نفسه، تضمن وثوقية عمل النظام بشكل كامل.
لنفرض مثلاً احتياج برنامجك في مرحلة ما، لإعادة إقلاع الجهاز Reset. في حال اعتمدت على تابع إعادة الإقلاع الخاص بك، توقع أن يسبب تابعك بعض المشاكل.
مثلاً، هناك برنامج منفذ حالياً، ويحتاج لحفظ آخر التعديلات التي جرت على ملف ما، أو هناك مستخدمين آخرين متصلين مع جهازك الشخصي، وإعادة إقلاع الجهاز بدون تنبيه وتنفيذ بعض المهام قبل عملية إعادة الإقلاع، يتسبب في الكثير من الضرر.
أما في حال استخدمت ما إذا تابع إعادة الإقلاع الخاص بالنظام ويندوز، فتأكد بأنه سيقوم بالعمل بدون أي أضرار، وسيقوم بجميع الإجراءات الضرورية، مثل تنبيه باقي البرامج أو المستخدمين على ضرورة الخروج حالياً، ويمكن في بعض الأحيان إلغاء أمر إعادة الإقلاع لأسباب خاصة.
لقد رأيت الآن، وجود أسباب كثيرة ومنطقية، لاستخدام توابع الويندوز API، لنكتب الآن برنامجاً يستخدم توابع النظام ويندوز، ونرى كيفية عمله.
ملاحظة
صممت مايكروسوفت النظام ويندوز، بطريقة تسمح له باستخدام التوابع من ملفات DLL. بكلمة أصح، صممت مايكروسوفت هذه المكتبات بطريقة تسمح للبرامج الأخرى (مثل البرامج المطورة في فيجول بيسك)، بقابليتها لاستخدام هذه التوابع، من ملفات DLL الخاصة بويندوز. تسمى توابع النظام ويندوز (واجهة برمجة التطبيقات) ويطلق عليها اختصاراً API (Application Programming Interface).
برنامج API
سننشئ الآن، البرنامج API، يوضح هذا البرنامج، كيفية استخدام توابع API من خلال برامجك المطورة في فيجول بيسك.
أنشئ الدليل C:\VB5Prg\Ch20، لكي تحفظ المشروع فيه.
أنشئ مشروعاً جديداً بنوع Standard EXE، من القائمة File.
اختر البند Save Form1 As من القائمة File، ثم احفظه باسم MyApi.Frm، في نفس الدليل.
اختر البند Save Project As من القائمة File، ثم احفظه باسم MyApi.Vbp في نفس الدليل السابق أيضاً.
صمم النموذج frmMyApi وفق الجدول 20-1.
بعد انتهائك من بناء النموذج frmMyApi، ينبغي ظهوره كالشكل 20-1.


الجدول 20-1. جدول خصائص النموذج frmMyApi.
القيمة الخاصية الكائن
frmMyApi Name Form
برنامج API Caption
True RightToLeft
cmdBeep Name CommandButton
&رنين Caption
cmdExit Name CommandButton
&خروج Caption

الشكل 20-1 النموذج frmMyApi بعد انتهاء تصميمه.
أضف النص التالي لقسم التصريحات العامة للنموذج frmMyApi:
'يجب التصريح عن كل المتحولات
Option Explicit
أضف النص التالي لحادثة Click الخاصة بالزر cmdExit:
Private Sub cmdExit_Click()
End
End Sub
يتسبب نقر الزر خروج، بإنهاء البرنامج والعودة إلى فيجول بيسك.
إضافة وحدة نمطية BAS جديدة للمشروع
تحتوي نافذة المشروع على نموذج واحد فقط هو frmMyApi، (انظر الشكل 20-2 الممثل لنافذة المشروع).
أظهر نافذة المشروع، من القائمة View، البند Project Explorer.
الشكل 20-2 يحتوي المشروع MyApi على نموذج وحيد.
سنضيف وحدة نمطية جديدة BAS إلى المشروع MyApi:
اختر البند Add Module، من القائمة Project.
يستجيب فيجول بيسك بإظهار نافذة Add Module (انظر الشكل 20-3).
تأكد أن صفحة New هي الظاهرة في نافذة Add Module.
اختر الرمز Module، ثم انقر الزر فتح.
نتيجة ذلك، تضاف وحدة نمطية جديدة BAS إلى المشروع.
الشكل 20-3 إضافة وحدة نمطية جديدة للمشروع MyApi.Vbp.
للوحدة النمطية المضافة اسم افتراضي هو Module1، لذلك يجب تغيير الاسم إلى MyApi.BAS كالتالي:
اختر البند Save Module1 As من القائمة File، واحفظه باسم MyApi.BAS في الدليل C:\VB5Prg\Ch20.
انظر لنافذة المشروع مرة أخرى، وكما ترى (انظر الشكل 20-4)، تتضمن نافذة المشروع النموذج frmMyApi، والوحدة النمطية MyApi.BAS.
الشكل 20-4 تتضمن نافذة المشروع النموذج frmMyApi، والوحدة النمطية MyApi.BAS.
التصريح عن توابع API
هدفنا من هذا البرنامج، تنفيذ تابع API من خلال البرنامج API، لذلك يجب إخبار فيجول بيسك عن اسم التابع التي تود استخدامه، وأين يوجد (اسم الملف DLL الذي يحويه)، وكيفية عمل هذا التابع (الوسائط المطلوبة لهذا التابع والقيمة العائدة منه).
تدعى عملية إخبار فيجول بيسك عن تفاصيل التابع بالتصريح Declare عن هذا التابع.
أضف الأسطر التالية إلى قسم التصريحات العامة للوحدة النمطية MyApi.BAS:
'يجب التصريح عن كل المتحولات
Option Explicit
Declare Function MessageBeep Lib "User32" _
(ByVal wType As Long) As Long
اختر البند Save Project من القائمة File، لحفظ المشروع كاملاً.
يعتبر السطر التالي في قسم التصريحات العامة للوحدة النمطية MyApi.BAS، سطر التصريح عن تابع API:
Declare Function MessageBeep Lib "User32" _
(ByVal wType As Long) As Long
يبدأ سطر التصريح عن تابع API بالعبارة Declare، بعد Declare مباشرة، يأتي دور تحديد نوع التابع، هل يعود التابع بقيمة (Function)، أم لا يعود بقيمة (Sub).
بعد تحديد نوع التابع، ينبغي تحديد اسم التابع المراد استدعاؤه. في مثالنا الحالي، يسمى التابع MessageBeep.
بعد تحديد اسم التابع، ينبغي تحديد موقعه. في مثالنا الحالي، التابع موجود في المكتبة Lib المسماة User32.
يتواجد الملف User32.DLL، في الدليل الفرعي System، الموجود في الدليل الرئيسي C:\Windows، (بالنسبة للنظام Windows95).
ويتواجد في الدليل C:\WinNT\System32، (بالنسبة للنظام WinNT).
عَلِم فيجول بيسك نتيجة سطر التصريح السابق، موقع التابع MessageBeep()، (المكتبة User32.DLL).
بعد تحديد موقع التابع، ينبغي تحديد الوسائط المطلوبة لعمله، ونوع البيانات الخاصة بكل وسيط. يتطلب التابع MessageBeep() وسيطاً واحداً فقط، هو wType من النوع Long.
أخيراً، بعد تحديد كل الوسائط المطلوبة (بشكل عام)، يأتي دور تحديد نوع القيمة التي يعود بها التابع بعد انتهاء مهمته. يعود التابع MessageBeep() بقيمة من النوع Long، لذلك كتبت العبارة As Long آخر سطر التصريح.
ستتعلم في آخر هذا الفصل، كيفية إيجاد أسطر التصريحات الخاصة بتوابع API الأخرى.
تنفيذ التابع MessageBeep()
لنكتب الآن العبارات الخاصة بتنفيذ التابع MessageBeep:
يجب ملاحظة أمر هام جداً، هو كون عبارة تنفيذ التابع، مطابقة تماماً لما جاء في سطر التصريح عن هذا التابع، من حيث الوسائط المطلوبة ونوع كل وسيط، ونوع القيمة العائدة من التابع.
اكتب الأسطر التالية في الإجراء cmdBeep_Click():
Private Sub cmdBeep_Click()
Dim Dummy
Dummy = MessageBeep(1)
End Sub
اختر البند Save Project من القائمة File، لحفظ المشروع كاملاً.
صرحت في الإجراء السابق عن متحول محلي باسم Dummy كالتالي:
Dim Dummy
ثم استدعيت التابع MessageBeep():
Dummy = MessageBeep(1)
وأسندت القيمة العائدة من التابع MessageBeep() إلى المتحول Dummy.
فعلياً، وفي هذا المثال بالذات، لا فائدة أبداً من القيمة العائدة من هذا التابع، ولكن فقط لتوضيح أن تابع API يعود بقيمة، يجب إسنادها إلى متحول ما.
يحتاج التابعMessageBeep() إلى وسيط واحد فقط، ويعرِّف هذا الوسيط كيفية إصدار الصوت بالضبط، كما سيتم شرحه لاحقاً.
نفّذ برنامج API.
انقر الزر رنين، وتأكد من سماعك صوتاً.
تمرن على البرنامج، ثم انقر الزر خروج لإنهاء البرنامج.
بالتأكيد، يمكن استخدام العبارة Beep الجاهزة في فيجول بيسك، بدلاً من هذه الطريقة الطويلة لعمل نفس الشيء. لكن الهدف من هذا التمرين، هو معرفة كيفية استدعاء تابع API ما.
تعتمد طريقة إصدار الصوت، على كيفية تعريف بطاقة الصوت لديك. قد يصدر الصوت من خلال بطاقة الصوت، وليس من خلال سماعة الجهاز الداخلية.
غيِّر قيمة الوسيط المطلوب للتابع MessageBeep() من 1 إلى -1 وذلك كما يلي:
Dummy = MessageBeep(-1)
نفّذ البرنامج مرة أخرى، وتأكد من إصدار الصوت عبر سماعة الجهاز هذه المرة. تُجبر القيمة -1، التابع MessageBeep() على إصدار الصوت عبر سماعة الجهاز الداخلية، حتى لو كان لديك بطاقة صوت معرفة بشكل صحيح.
عند إصدار الصوت عبر سماعة الجهاز الداخلية، تكون فترة إصدار الصوت صغيرة جداً (بالكاد تسمعها). لكي تطيل فترة إصدار الصوت، غيِّر الإجراء cmdBeep_Click() إلى:
Private Sub cmdBeep_Click()
Dim Dummy
Dim I
For I=0 To 100
Dummy = MessageBeep(1)
Next
End Sub
تتسبب إضافة الحلقة For-Next في تنفيذ التابع مائة مرة متتالية.
معرفة اسم دليل Windows
كمثال على استدعاء تابعAPI آخر، دعنا نستخدم تابع API، الذي يخبرنا عن اسم الدليل الذي جُهِّز فيه النظام Windows:
ضع زراً جديداً على النموذج frmMyApi.
أسند القيم التالية لخصائصه:
Name: cmdWhereWindows
Caption: دليل ويندوز
ينبغي ظهور النموذج بعد الانتهاء من تصميمه، كما في الشكل 20-5.
الشكل 20-5 النموذج frmMyApi بعد إضافة الزر دليل ويندوز.
أضف الأسطر التالية إلى قسم التصريحات العامة للوحدة النمطية MyApi.Bas.
بعد الانتهاء من إضافة الأسطر الجديدة، يصبح كالتالي:
'يجب التصريح عن كل المتحولات
Option Explicit
Declare Function MessageBeep Lib "User32" _
(ByVal wType As Long) As Long
Declare Function GetWindowsDirectory Lib "Kernel32" _
(ByVal lpBuffer As String,ByVal nSize As Long) As Long
لاحظ، أن التصريح الجديد عن التابع GetWindowsDirectory()، أصعب وأعقد قليلاً من التصريح عن التابع السابق MessageBeep().
اسم التابع الثاني GetWindowsDirectory()، وهو موجود في ملف المكتبة Kernel32.Dll.
ظهر قسم جديد في سطر التصريح الثاني، هو العبارة Alias. حيث يمكننا تغيير اسم التابع الأصلي إلى اسم مستعار آخر، وذلك في حال حدوث تعارض بين أسماء التوابع مع بعضها البعض، أو مع عبارات فيجول بيسك المحجوزة الأخرى. يكفينا ما تعلمناه عن العبارة Alias، ولن نخوض في تفاصيلها أكثر من ذلك.
يتطلب التابع GetWindowsDirectory() وسيطين هما: الوسيط lpBuffer من النوع String، والوسيطnSize من النوع Long:
(ByVal lpBuffer As String,ByVal nSize As Long)
يعود التابع بقيمة بعد تنفيذه، من النوع Long.
اختر البندSave Project من القائمة File، لحفظ المشروع كاملاً.
ربط نص البرنامج الخاص بحادثةClick للزر دليل ويندوز
اتبع الخطوات التالية:
اكتب الأسطر التالية في الإجراء cmdWhereWindows_Click():
Private Sub cmdWhereWindows_Click ()
Dim Result
Dim WindowsDirectory A String
WindowsDirectory = Space(144)
Result = GetWindowsDirectory(WindowsDirectory,144)
If Result = 0 Then
MsgBox "لم أستطع الحصول على اسم مجلد ويندوز"
Else
WindowsDirectory = Trim(WindowsDirectory)
MsgBox "مجلد ويندوز هو:" & WindowsDirectory
End If
End If
اختر البندSave Project من القائمة File، لحفظ المشروع كاملاً.
صرحت في الأسطر السابقة عن متحولين هما:
Dim Result
Dim WindowsDirectory A String
ثم ملأت المتحول WindowsDirectory، بأحرف مسافات (144 حرف مسافة):
WindowsDirectory = Space(144)
يغنينا التابع Space()، عن كتابة أحرف المسافات فعلياً، لإسنادها للمتحول. ولولا هذا التابع، لاضطررنا لكتابة السطر التالي:
WindowsDirectory = " (اضغط مفتاح المسافة 144 مرة هنا) "
بعد ذلك، نفّذ التابع GetWindowsDirectory() كالتالي:
Result = GetWindowsDirectory(WindowsDirectory,144)
تُسند النتيجة (القيمة العائدة من التابع) للمتحول Result. لا يحتوي المتحولResult على اسم مجلد النظام Windows، بل يحتوي على رقم، يمثل نجاح التابع في أداء عمله أو فشله.
إذا كانت قيمة المتحول Result مساوية للصفر، يكون التابع قد فشل في أداء مهمته ولسبب من الأسباب، أما إذا كانت قيمة المتحولResult لا تساوي الصفر، يكون التابع قد نجح في أداء مهمته.
تساوي قيمة الوسيط الثاني 144، وهي تمثل طول سلسلة الأحرف التي ينبغي وضعها في المتحول WindowsDirectory، يُستخدم المتحول WindowsDirectory كخرج Output لمعلومات التابع GetWindowsDirectory().
بكلام آخر، يضع التابع GetWindowsDirectory() اسم مجلد الويندوز في المتحول WindowsDirectory. من الضروري جداً ملء المتحولWindowsDirectory بأحرف مسافات وبطول 144 حرف، قبل استدعاء التابع GetWindowsDirectory()، لأن التابع يُحدِّث سلسلة الأحرف الموجودة في المتحول WindowsDirectory، ويفترض هذا التابع وجود منطقة من الذاكرة، لوضع سلسلة الأحرف الجديدة (اسم مجلد ويندوز)، قبل عملية تنفيذه.
بعد ذلك، نفذت العبارة If-Else-End If التالية:
If Result = 0 Then
MsgBox "لم أستطع الحصول على اسم مجلد ويندوز"
Else
WindowsDirectory = Trim(WindowsDirectory)
MsgBox "مجلد ويندوز هو:" & WindowsDirectory
End If
إذا كانت قيمة Result تساوي الصفر (القيمة العائدة من التابع)، هذا يعني فشل التابع GetWindowsDirectory() في الحصول على اسم الدليل الذي جُهِّز فيه النظام Windows لسبب من الأسباب. ينبغي على المبرمج، توضيح هذا الأمر للمستخدم، وإظهار رسالة له، تخبره عن عدم قدرته في الحصول على اسم مجلد الويندوز.
أما إذا كانت قيمة المتحولResult لا تساوي الصفر، هذا يعني نجاح التابع في الحصول على اسم الدليل، وتنفذ الأسطر الواقعة بعد العبارة Else. وهي:
WindowsDirectory = Trim(WindowsDirectory)
MsgBox "مجلد ويندوز هو:" & WindowsDirectory
تكون قيمة المتحول WindowsDirectory مبدئياً، سلسلة من المسافات بطول 144 حرف مسافة. لذلك اضطررنا لاستخدام التابع Trim() لجعل المتحول WindowsDirectory خالياً من المسافات الزائدة.
ملاحظة
يزيل التابع Trim() أحرف المسافات الزائدة من يمين المتحول ويساره، لكنه لا يزيل أحرف المسافات الفاصلة بين الكلمات الموجودة في المتحول.
مثلاً، لو كان لدينا العبارات التالية:
myName = " Ahmad Waddah "
myName = Trim(myName)
Print myName
بعد تنفيذها، تكون النتيجة:
Ahmad Waddah
نلخص الكلام السابق فنقول:
هيأت المتحول WindowsDirectory لاستقبال المعلومات من التابع GetWindowsDirectory().
أرسلت هذا المتحول للتابع عن طريق استدعاء التابع فعلياً.
وَضع التابع اسم مجلد Windows في المتحول WindowsDirectory.
غير التابع GetWindowsDirectory() قيمة المتحول WindowsDirectory من سلسلة أحرف مسافات، إلى سلسلة أحرف تمثل اسم الدليل، مع بقاء المسافات الزائدة في آخر المتحول.
حَذف التابع Trim() المسافات الزائدة من المتحول WindowsDirectory.
أظهرت العبارة MsgBox اسم الدليل، للمستخدم.
احفظ النموذج بضغط مفتاحي Ctrl + S.
نفذ البرنامج وتأكد من ظهور رسالة تخبرك عن اسم مجلد Windows، عند نقر الزر دليل ويندوز.
إضافة زر الخروج من الويندوز
اتبع ما يلي:
ضع زراً جديداً على النموذج frmMyApi.
أسند القيم التالية لخصائصه:
Name: cmdExitWindows
Caption: خروج &من الويندوز
ينبغي أن يصبح النموذج كما في الشكل 20-6.
الشكل 20-6 النموذجfrmMyApi بعد إضافة زر الخروج من الويندوز.
أين توجد أسطر التصريح عن توابع API
رأيت سابقاً، كلاً من التابع MessageBeep()، والتابع GetWindowsDirectory()، وعرفت كيفية استخدامهما عن طريق هذا الكتاب. تصور أنك تريد الآن، استخدام تابع يتسبب في إعادة إقلاع الجهاز Reboot.
كيف تعرف اسم التابعAPI الصحيح؟ وما هو السطر الذي يصرح عنه بشكل صحيح؟ أين أجد هذه المعلومات؟.
انظر إلى دليل فيجول بيسك، ستجد مجلداً فرعياً يسمى \Winapi، والملف التنفيذي Apiload.exe.
نفّذ البرنامج Apiload.exe عن طريق مستكشف Windows، أو عن طريق قائمة زر ابدأ، ثم بند البرامج، ثم بند Microsoft Visual Basic، ثم بند API Text Viewer، وهو أحد بنود المجموعة Microsoft Visual Basic.
تظهر نافذة API Viewer نتيجة تشغيل البرنامج، (الشكل 20-7).
الشكل 20-7 نافذة API Viewer.
استخدم النافذة السابقة، لمعرفة كيفية التصريح عن تابع معين. كالتالي:
اختر البند Load Text File من قائمة File، في البرنامج API Viewer.
يظهر مربع الحوار Select a Text API File.
اختر الملف Win32api.txt من الدليل الفرعي Winapi، ثم انقر فتح.
تُحمَّل جميع البنود الموجودة في الملف Win32api.txt، إلى مربع السرد Available Items.
تأكد من اختيار البند Declare في الحقلAPI Type.
يتضمن مربع السرد Available Items الآن، جميع تصريحات توابع النظامAPI.
ابحث عن البند ExitWindowsEx، وانقره مرة واحدة لاختياره.
انقر الزر Add الموجود في نافذة البرنامج API Viewer.
يظهر البند المضاف في الحقل Selected Items (أسفل نافذة البرنامج).
استخدم الفأرة لاختيار محتويات الحقل Selected Items، ثم انقر الزر Copy.
يتم نسخ محتويات الحقل Selected Items المختارة، إلى حافظة النظام Windows.
ضع مؤشر الفأرة على قسم التصريحات العامة للوحدة النمطية MyApi.Bas، وذلك بنقر موقع الكتابة (لتنشيط نافذة نص البرنامج)، ثم انتقل إلى آخر سطر.
الصق النص الموجود في حافظة Windows، (وذلك بضغط المفتاحين Ctrl+V).
يصبح النص الموجود في قسم التصريحات العامة للوحدة النمطية MyApi.Bas كما يلي:
'يجب التصريح عن كل المتحولات
Option Explicit
Declare Function MessageBeep Lib "User32" _
(ByVal wType As Long) As Long
Declare Function GetWindowsDirectory Lib "Kernel32" _
(ByVal lpBuffer As String,ByVal nSize As Long) As Long
Declare Function ExitWindowsEx Lib "User32" _
(ByVal uFlags As Long,ByVal dwReserved As Long) As Long
تحتاج من برنامج API Viewer أيضاً، الثوابت المستخدمة مع توابع API.
عد ثانية إلى البرنامج API Viewer، واختر البند Constant من الحقل API Type (حتى تظهر لائحة بثوابت توابع API).
قد يظهر لك مربع حوار، يسألك إذا كنت تريد تحويل الملف المحمَّل الحالي، إلى ملف Database، جاوب بنعم، فيظهر مربع الحوار Select a Name for New Database.
احفظ ملف قاعدة البيانات باسم Win32api.Mdb في الدليل \Winapi.
تأخذ عملية التحويل بعض الوقت، ولكن عند تنفيذ البرنامج API Viewer في المرة المقبلة، اختر البند Load Database File، واختر الملف Win32api.Mdb.
يتعامل البرنامج في هذه الحالة، مع ملف قاعدة بيانات، وليس مع ملف نصي، وستلاحظ الفرق الكبير في السرعة التي يتعامل فيها مع البنود من حيث العرض أو البحث الخ.
في جميع الحالات، تظهر الآن جميع ثوابت التوابع API.
أزح البنود عن طريق الأسهم أو شريط التمرير الأفقي، حتى ترى البند EWX_SHUTDOWN، انقر عليه مرة واحدة فقط، ثم انقر الزر Add.
يظهر البند EWX_SHUTDOWN في المربع السفلي من البرنامج API Viewer.
اختر البند نفسه من المربع السفلي، ثم انقر الزر Copy.
يتم نسخ هذا البند إلى الحافظة Clipboard.
انقل مؤشر الفأرة إلى آخر سطر في الوحدة النمطية MyApi.Bas، ثم الصق النص الموجود في الحافظة.
يصبح الآن النص الموجود في قسم التصريحات العامة للوحدة النمطية MyApi.Bas كالتالي:
'يجب التصريح عن كل المتحولات
Option Explicit
Declare Function MessageBeep Lib "User32" _
(ByVal wType As Long) As Long
Declare Function GetWindowsDirectory Lib "Kernel32" _
(ByVal lpBuffer As String,ByVal nSize As Long) As Long
Declare Function ExitWindowsEx Lib "User32" _
(ByVal uFlags As Long,ByVal dwReserved As Long) As Long
Public Const EWX_SHUTDOWN = 1
اختر البند Save Project من القائمة File، لحفظ المشروع كاملاً.
إسناد نص برنامج حادثة Click للزر cmdExitWindows
اتبع ما يلي:
اكتب ما يلي في الإجراء cmdExitWindows_Click():
Private Sub cmdExitWindows_Click()
Dim Dummy
Dim Answer
Answer = MsgBox("هل تريد الخروج من الويندوز بالتأكيد؟", _
vbYesNo)
If Answer = vbYes Then
Dummy = ExitWindowsEx(EXW_SHUTDOWN,0)
End If
End Sub
يصرح نص البرنامج الذي كتبته سابقاً، عن متحولين محليين هما: Dummy و Answer.
لكتابة برنامج احترافي ووثوقي، يجب التأكد أن المستخدم يريد وبشكل مؤكد، تنفيذ العمل الذي طلبه من البرنامج.
في هذا المثال، تم التأكد من نية المستخدم على الخروج، قبل تنفيذ تابع الخروج من الويندوز، بإظهار رسالة واضحة قابلة للتراجع (نقر الزر لا).
إذا نقر المستخدم زر نعم، ينفذ السطر الذي يلي تعليمة If:
Dummy = ExitWindowsEx(EXW_SHUTDOWN,0)
لاحظ عدم استخدام القيمة العائدة من التابع (لا تهمك حالياً)، لذلك تم وضعها في متحول باسم Dummy (زائف).
يغلق التابع النظامWindows بكامله، بسبب وضع قيمة الوسيط الأول مساوية لقيمة الثابت EXW_SHUTDOWN.
بالعودة إلى قسم التصريحات العامة للوحدة النمطية MyApi.Bas، نجد السطر التالي:
Public Const EXW_SHUTDOWN = 1
يدل هذا السطر على أن قيمة الثابت EXW_SHUTDOWN تساوي الواحد، وهي قيمة ثابتة لا يجوز تغيرها ضمن البرنامج.
إذاً، السطرين التاليان متكافئان من حيث النتيجة:
Dummy = ExitWindowsEx(EXW_SHUTDOWN,0)
Dummy = ExitWindowsEx(1,0)
تستخدم تقنية تعريف الثوابت، لجعل البرنامج أوضح في الفهم، ومن البديهي أن السطر الأول أوضح من السطر الثاني.
قبل تجريب البرنامج API، تأكد من حفظ المشروع، وإغلاق كافة التطبيقات الأخرى.
نفّذ البرنامج API.
انقر زر خروج من الويندوز.
تظهر رسالة تأكيد، تطلب منك إجابة صريحة بنعم أو لا.
انقر نعم.
تأكد من إغلاق النظام Windows.
معرفة اسم مجلد Windows\System
بطريقة مشابهة جداً لمعرفة اسم مجلد Windows، يمكننا معرفة اسم مجلد Windows\System، اتبع ما يلي:
أضف زراً جديداً للنموذج frmMyApi.
أسند القيم التالية لخصائصه:
Name: cmdWhereSystem
Caption: System &دليل
يصبح النموذج بعد الانتهاء كما في الشكل 20-8.
الشكل 20-8 النموذج بعد إضافة زر دليل System.
أضف سطر التصريح التالي لقسم التصريحات العامة للوحدة النمطية MyApi.Bas:
Declare Function GetSystemDirectory Lib "kernel32" Alias _
"GetSystemDirectoryA" _
(ByVal lpBuffer As String, _
ByVal nSize As Long) As Long
أضف الأسطر التالية للإجراء cmdWhereSystem_Click():
Private Sub cmdWhereSystem_Click()
Dim Result
Dim SystemDirectory A String

SystemDirectory = Space(144)

Result = GetSystemDirectory(SystemDirectory,144)

If Result = 0 Then
MsgBox "لا يمكن الحصول على اسم مجلد النظام"
Else
MsgBox "مجلد النظام هو:" & SystemDirectory
End If
End Sub
من المؤكد أنك وجدت الأسطر السابقة، مشابهة جداً للأسطر التي كتبتها في إجراء الحصول على اسم دليل Windows، مع اختلاف بسيط جداً هو في اسم التابع API.

الخلاصة
تعلمت في هذا الفصل، كيفية استخدام توابع النظام API Windows من برامج فيجول بيسك. ورأيت أيضاً وجوب التصريح عن التابع قبل التمكن من استخدامه، وبمجرد التصريح عن التابع، يمكنك استخدامه وكأنه موجود فعلاً في فيجول بيسك. تزيد بهذه الطريقة عدد التوابع الممكن استخدامها.
شاهدت أيضاً برنامج API Viewer، الذي يساعدك على نسخ الأسطر المصرحة عن التوابع، ولصقها في برنامجك.
صحيح أن هذا البرنامج لا يعلمك طريقة استخدام التوابع، لكن يمكن في بعض الأحيان اكتشاف ما يفعله التابع من اسمه المجرد.
تتواجد المعلومات الكاملة عن توابع API، في ملفات التعليمات Help Files، والوثائق التي تأتي مع بعض اللغات الأخرى مثل لغة Visual C++.

ودا اشرح الكامل لبرنامج الفيجوال بيسك قسمته على عشرين فصل لتسهيل فهمه وما تنسونيش فى الردود اوكى بااااااااااااى
(swb) (swb) (swb) ;) ;) ;)

المصدر: منتديات كتاب العرب
شرح فيجوال بيسك للمبتدئين والمحترفين

المصدر: http://university.arabsbook.com/threads/1056-شرح-فيجوال-بيسك-للمبتدئين-والمحترفين?s=1426bd99ccf36c14be3484c699f9d389#ixzz1RW9uVk3g

ليست هناك تعليقات:

إرسال تعليق