Mostafa Sayed
01-03-09, 05:47 PM
أولا ما هي شاشة التوقف ؟
شاشة التوقف هي عبارة عن برنامج يحمل اللاحقة scr بدلاً عن اللاحقة exe ويوجد في مجلد الوينذوز يقوم في معظم حالاته بإظهار ألوان و رسوم
متحركة بغرض حماية الشاشة و لذلك يسمى حافظ الشاشة أو Screen Saver وذلك لان الشاشة تتأثر بوجود اللون الواحد في نفس المكان لمدة طويلة ولذلك نجد أن شاشات التوقف تحتوي على الكثير من الألوان و الرسوم المتحركة التي تقوم بعملية تجديد العرض في جميع أجزاء الشاشة* و يقوم نظام التشغيل باستدعاء شاشة التوقف بعد مرور فترة زمنية دون أن يقوم المستخدم بتحريك الفأرة أو الضغط على أي زر وذلك على افتراض أن المستخدم ليس امام الجهاز وبالتالي فانه من الأفضل حماية الشاشة بشاشة التوقف...
خصائص شاشة التوقف و بماذا تختلف عن البرنامج العادي ؟
1 – شاشة التوقف تشغل الشاشة كاملة وتغطي حتى شريط المهام.
2 – لايوجد لها شريط عنوان او ازرار تكبير*تصغير او إغلاق.
3 – تحتوي على الكثير من الحركة والألوان.
4 – تختفي بمجرد تحريك الماوس او الضغط على احد ازرار لوحة المفاتيح.
5 – لايجب ان تشتغل اكثر من نسخة من شاشة التوقف في نفس الوقت.
6 – عند ترجمة البرنامج نستخدم اللاحقة SCR بدلاً عن EXE كما ذكر سابقاً.
7 – يجب وضع شاشة التوقف في مجلد الوينذوز.
8 – يفضل أن تحتوي على فورم للإعدادت تمكن المستخدم من تغير سرعة الحركة مثلاً.
سنناقش الآن النقاط السابقة بحسب الترتيب...
1- 2 - لكي يكون لدينا فورم تغطي الشاشة كاملة نبدأ برنامج جديد ونعين الخصائص التالية للفورم1 :
Caption = “” لايوجد عنوان
MinButton = false لايوجد زر تصغير
MaxButton = false لايوجد زر تكبير
ControlBox = false لايوجد شريط عنوان ولا زر إغلاق
WindowState = Maximized جعل الفورم تغطي الشاشة كاملة
BackColor = Black يفضل جعل لون الخلفية اسود(يمكنك تغير اللون)
3 – اما موضوع الالوان والحركة فهي متروكة لك ولكن لمزيد من التوضيح سوف اجعل شاشة التوقف تقوم بعرض الكثير من الدوائر العشوائية على
الفورم كمثال توضيحي :
أ – غير الخاصية FillStyle التابعة للفورم الى القيمة Solid .
ب – اضف Timer الى الفورم.
ج – غير الخاصية Interval التابعة له الى القيمة 100.
ح – اكتب الشفرة التالية :
code: Private Sub Timer1_Timer()
Dim X As Integer
Dim Y As Integer
X = Int(Rnd * Me.ScaleWidth) إحداثيات الدائرة على المحور السيني
Y = Int(Rnd * Me.ScaleHeight) إحداثيات الدائرة على محور الصادات
Me.FillColor = QBColor(Int(Rnd * 14) + 1) تحديد لون عشوائي للدائرة
Circle (X* Y)* 100 رسم الدائرة المطلوبة في الموقع العشوائي
End Sub
الشفرة السابقة تقوم برسم دوائر ملونة عشوائية صغيرة حول الفورم.
4 – يجب ان تحتوي الفورم على وسيلة للإغلاق وذلك بتحريك الفأرة او الضغط على زر في لوحة المفاتيح * فكما نعلم انه عند تحريك الفأرة على
الفورم فأنه يستدعى الحدث MouseMove وكذلك عند الضغط على أي زر يستدع الحدث KeyPress ويمكن ان تضع الامر End الذي ينهي البرنامج
في كلا الحدثين كالتالي :
code: Private Sub Form_KeyPress(KeyAscii As Integer)
End
End Sub
Private Sub Form_MouseMove(Button As Integer* Shift As Integer* X As Single* Y As Single)
Static Num As Integer
Num = Num + 1
If Num > 3 Then End
End Sub
ملاحظة : يقوم البرنامج باستدعاء الحدث MouseMove عند بداية التشغيل ولذلك سوف ينتهي برنامجنا قبل ان يبدأ وذلك لوجود الامر End فيه* لهذا وضعنا شرط بحيث نتجاهل الاستدعاءات الثلاثة الاولى ..
5 – يجب ان نمنع تنفيذ اكثر من نسخة من برنامجنا في نفس الوقت وذلك ياستخدام الخاصية PrevInstance لبرنامجنا حيث انه اذا كانت توجد نسخة سابقة من البرنامج تعمل من قبل فأن قيمة هذه الخاصية تكون True ونضع شفرة الفحص في الحدث Load قبل ان يتم عرض البرنامج كالتالي :
code: Private Sub Form_Load()
If App.PrevInstance Then End
End Sub
أي انه عندما تكون هذه الخاصية True فانه يوجد نسخة من البرنامج تعمل مسبقاً ولا يوجد داعي لتعمل نسخة أخرى وبذلك ننهي النسخة
الجديدة.
6 – 7 – عندما نترجم البرنامج بواسطة الامر Make Project1.exe من القائمة ملف نكتب اسم شاشة التوقف ثم نتبعها باللاحقة scr ( مثلاً
Circles.scr ) ثم نقوم بحفظ البرنامج في مجلد الوينذوز وذلك لكي يظهر في قائمة شاشات التوقف التي يمكن عرضها من خلال خصائص سطح
المكتب .
كان القسم الاول من الدرس يتعلق بأساسيات تصميم شاشة التوقف ولكن يجب علينا ان نعرف ان شاشة التوقف اكثر تعقيداً من ذلك نظراً لان الوينذوز يستدعيها اكثر من مرة و لأغراض مختلفة* مثلاً عندما يختار المستخدم اسم برنامجنا من قائمة شاشات التوقف الموجودة في خصائص سطح المكتب فان المطلوب هنا ان تعمل نسخة مصغرة من برنامجنا في شاشة العرض الصغيرة المجاورة* وكذلك عندما يختار المستخدم الزر اعدادت يجب عرض الفورم الذي يهتم بجزء الإعدادات وليس الفورم الذي يحتوي على شاشة التوقف ( وهي الشاشة التي تعرض الدوائر الملونة في مثالنا السابق ) * وكذلك الحال عند تغير كلمة المرور لهذه الشاشة.
وبذلك أصبحنا نعرف انه يجب أن يحتوي برنامجنا على أكثر من فورم وانه يجب معرفة الفورم المناسب لكل استدعاء ثم عرض الفورم المناسب....!
ويبقى السؤال كيف يمكننا أن نعرف ما هو الوضع أو الفورم المطلوب عرضه ؟
الإجابة تكمن في البيانات التي يحملها لنا المتغير Command* كلنا يعرف أن هذا المتغير يستخدمه نظام التشغيل لتمرير بيانات للبرامج فمثلاً عند النقر المزدوج على احد ملفات برنامج الرسام والتي تحتوي على اللاحقة bmp في مستكشف وينذوز فانه يتم عرض البرنامج محتوياً الملف المذكور فكيف عرف الرسام هذا الملف ومن ثم قام بتحميله؟* وذلك لان الرسام يفحص المتغير command قبل العرض فإذا احتوى على اسم ملف يعمل على تحميل هذا الملف مباشرة...
وبنفس الطريقة يمكن لبرنامجنا معرف نوع الاستدعاء الذي يقصده نظام التشغيل هل للعرض ام لتغير الإعدادات أم لعرض نسخة مصغرة...الخ
هنا عرض لبعض الاستدعاءات الممكنة* بحسب القيمة التي يحملها المتغير command :
Command = “/s”
تدل القيمة "/s" على انه يجب عرض او تشغيل شاشة التوقف كاملة أي عرض الفورم الموجودة في المثال السابق.
Command = “/c”
يدل على انه يجب عرض شاشة الإعدادت التي تمكن المستخدم من تغير السرعة او الألوان او أي شي يتعلق بشاشة التوقف الخاصة بنا.
Command = “/p 12344”
يجب عرض نسخة مصغرة من شاشة التوقف (الرقم المجاور يختلف في كل مرة) حيث يدل هذا الرقم المجاور للحرف /p على رقم الشاشة المصغرة الذي يمكن ان نستخدمه لجعل شاشتنا تعمل داخل إطار الشاشة المخصصة للعرض.
Command = “/a 34765”
يستخدم ليدل على انه يجب عرض الفورم الخاص بتغيير كلمة المرور كما ان الرقم قد يتغير..
دعونا الآن نحاول البدء بتصميم شاشة توقف مثالية مع استخدام الفورم التي انشئناها سابقاً مع تغيير ما يلزم...
سنقوم اولاً بإضافة فورم جديد Form2 إلى البرنامج يمكن بواسطة ان نغير إعدادت شاشة التوقف وسيكون هذا الفورم بسيطاً حيث يحتوي على زرين و شريط تمرير افقي و عنوان (Label)* غير الخصائص التابعة لكل عنصر كما يلي :
Form1
Caption = “إعدادت شاشة التوقف”
BorderStyle = Fixed Dialog
Command1
Caption = “موافق”
Command2
Caption = “إلغاء الامر”
HScroll1
Min = 1
Max = 1000
Value = 100
Label1
Caption =“اختر السرعة التي تناسبك”
سوف نستخدم شريط التمرير لتغيير سرعة ظهور الدوائر في شاشة التوقف وسوف نخزن القيمة في Registry ( او مسجل النظام ) وذلك حتى تظل محفوظة عند تشغيل شاشة التوقف في المرة المقبلة.
قم الآن بكتابة الشفرة التالية :
code: Private Sub Command1_Click()
SaveSetting "ScreenSaver"* "Options"* "Speed"* HScroll1.Value
End
End Sub
Private Sub Command2_Click()
End
End Sub
Private Sub Form_Load()
HScroll1.Value = GetSetting("ScreenSaver"* "Options"* "Speed"* 100)
End Sub
و بذلك نكون قد انتهينا من فورم الاعدادات...
نقوم بتعديل الشفرة الموجودة في الحدث Load للفورم1 بحيث يصبح كالتالي :
code: Private Sub Form_Load()
Timer1.Interval = 1001 - Clng(GetSetting("ScreenSaver"* "Options"* "Speed"* "100"))
End Sub
تقوم الشفرة السابقة بمعرفة سرعة الرسم التي تم تخزينها في Registry وذلك بواسطة شاشة الاعدادت التي انشئناها قبل قليل.
بقي امامنا ان نعرف كيف يمكن لبرنامجنا اختيار الفورم الصحيحة للتشغيل اعتماداً على قيمة المتغير Command المذكور سابقاً .
نظراً لان البرنامج لن يشغل فورم معينة دائماً وانما سيختار احداهما فانه من الافضل ان نغير كائن بدء التشغيل في برنامجنا وجعله Sub Main بدلاً من فورم1* وذلك كالتالي :
من القائمة Project نختار خصائص التشغيل او Project1 Properties ثم نغير الـ Startup Object من Form1 الى ٍ ٍSub Main * ثم نقوم بإضافة
Module جديد الى المشروع ونكتب فيه التالي :
code: Sub Main()
End Sub
ونكون بذلك قد جعلنا هذا الاجرء Sub Main هو الاجراء الذي سيتم استدعائه عند بدء التشغيل بدلاً عن فورم1 وفيه سنضع الشفرة التي سوف تمكنا من تحديد الفورم المطلوب تشغيله .
عند هذة النقطة اجد نفسي مضطراً لأن اقوم بتوضيح كيفية تعامل نظام التشغيل مع النوافذ المختلفة التي تعمل في نفس الوقت وذلك كأساس
لفهم الخطوات التي سنقوم بها لاحقاً لنصل في النهاية الى تصميم شاشة توقف تمتلك كل خصائص شاشة التوقف القياسية في الوينذوز....
عند تشغيل أي نافذة جديدة فان نظام التشغيل يحدد لها رقم معين يمكنك معرفة الرقم المعين لأي فورم وذلك بواسطة الخاصية hWand التي توجد في كل فورم* لطباعة الرقم الخاص على الفورم اكتب السطر التالي : Print Form1.hWand
وتكمن فائدة هذا الرقم في أن معظم دوال API تتعامل معه لتمكينك من التحكم في أي نافذة موجودة في النظام مثل تحريك* تغيير حجم* إخفاء* إظهار وكل ما يخطر ببالك من انواع التحكم.
كما أنه يوجد نوعان من النوافذ Parent و Child وكما هو واضح من التسمية احدهما هو الأب والآخر هو الابن حيث لا يسمح للابن بالعمل خارج إطار الاب مثل برنامج الـ Word فانه يمكن أن تفتح اكثر من مستند في نوافذ مختلفة داخل البرنامج نفسه بحيث لا تخرج نوافذ هذه المستندات من إطار الـ Word وبكلمات اخرى أن الورد هو الاب وكل المستندات بداخله هي ابنا اما الورد فهو اب ولا يوجد له اب آخر غير سطح المكتب طبعاً * وكل الفورمات الموجودة في الفيجوال بيسك هي من النوع Parent بشكل افتراضي ويمكنك تغيرها طبعاً!....
ويمكنك معرفة رقم النافذة الاب لاي نافذة اخرى عن طريق دالة GetParent وهي احدى دوال الـ API وذلك بتمرير رقم النافذة التي تريد معرفة رقم الاب لها * مثلاً :
code: Msgbox GetParent( Form1.hwnd )
يقوم السطر السابق بعرفة رقم الاب للفورم1 .
كما يمكنك جعل نافذة اب لنافذة اخرى فلجعل فورم1 اب لفورم2 استخدم الدالة SetParent كالتالي :
code: SetParent Form2.hwnd * Form1.hwnd
يمكن تنفيذ الامر السابق اذ كان الفورمان يعملان في نفس الوقت حيث يجعل فورم2 تعمل داخل فورم2....
ملاحظة : اذا كانت النافذة هي نافذة اب وحاولت أن تعرف رقم الـ Parent لها باستخدام الدالة GetParent فان الناتج سوف يكون صفر....
ولكن ماعلاقة كل ذلك بتصميم شاشة توقف ؟؟...
يجدر ملاحظة أن فورم1 في شاشة التوقف التي انشئناها يجب أن تعمل بطريقتن الاولى هي الطريقة العادية أي أن تغطي كل الشاشة وذلك عند مرور الوقت المحدد دون تحريك الفأرة أو لوحة المفاتيح(أي أن شاشة التوقف تكون في هذة الحالة نافذة Parent)* ام الحالة الثانية فهي عندما يختار المستخدم شاشتنا من خصائص سطح المكتب فانه يجب أن تعمل نافذتنا في النافذة الصغيرة التي تظهر في خصائص سطح المكتب حتى يقرر المستخدم ما إذا كان سوف يستخدمها ام لا وبذلك يجب أن تعمل شاشتنا داخل اطار نافذة العرض أي تكون نافذة ابن* ويمكن معرفة رقم نافذة العرض الصغيرة حتى نمررها للدالة SetParent بواسطة المتغير Command حيث تكون قيمته في هذة الحالة مثلاً هي : “/p 131792”
ويمثل الرقم الذي يلي الحرف رقم نافذة العرض...
بعد ان تعرفنا على هذة المبادئ يمكن الآن أن نكتب الشفرة التي سوف تختار أي فورم تشغل وكيفية الوضع المناسب لها وهي الشفرة التي
سوف توضع في Module1 الجديد الذي اضفناه سابقاً :
code: Public Declare Function SetParent Lib "user32" (ByVal hWndChild As Long* ByVal hWndNewParent As Long) As Long
Sub Main()
Dim S As String
Dim W As Long
S = LCase(Left(Command* 2)) استخراج الحرفان الأوليان
If S = "/s" Then عرض شاشة التوقف الكاملة
Form1.Show
Exit Sub
End If
If S = "/c" Then عرض الاعدادات
Form2.Show
Exit Sub
End If
If S = "/p" Then عرض شاشة توقف مصغرة
W = CLng(Mid(Command* 4))
Load Form1
SetParent Form1.hwnd* W
Form1.Show
End If
End Sub
في الشفرة اعلاه قمنا بحفظ الحرفين الأوليين للمتغير Command في المتغير S وهما الحرفان اللذان يمكننا بواسطتهما معرفة الفورم المطلوبة* ثم
نفحص قيمة هذا المتغير S :
S=”/s” يجب تشغيل شاشة التوقف في الوضع الكامل أي فورم1
S=”/c” يجب تشغيل فورم الإعدادات أي فورم2
S=”/p” يجب تشغيل فورم1 للعرض في النافذة الصغيرة
لاحظ اننا قمنا بإستدعاء الفورم المناسبة في كل مرة ماعدا في الحالة الاخيرة فانه لتشغيل فورم1 للعرض في النافذة الصغيرة أي كابن لها فانه
يجب علينا معرفة رقم هذة النافذة الصغيرة وذلك عن طريق المتغير Command حيث استخرجنا الرقم ثم قمنا بحفظه في المتغير W وبعد ذلك قمنا بتحميل فورم1 وذلك للحصول على رقمها هي ايضاً وبعد ذلك اصبح لدينا الرقمان المطلوبان وهما رقم الاب(نافذة العرض الصغيرة) و رقم الابن (فورم1) ثم استدعينا الدالة SetParent التي قامت بتحويل فورم1 من نافذة اب الى نافذة ابن لنافذة العرض* وبعد نجاح العملية يمكننا الان أن نجعل فورم1 مرئية عن طريق Form1.Show وذلك لان الامر Load Form1 يعمل على تحميل الفورم وليس عرضها...وبذلك نكون قد انهينا تصميم شاشة
توقف كاملة بجميع خصائصها ....
قم بترجمة شاشة التوقف ولكن باستخدام اللاحقة Scr بدلاً من exe كما هو موضح مسبقاً و احفظها في مجلد الوينذوز * ثم اذهب الى خصائص سطح المكتب واختار شاشة توقفنا من قائمة شاشات التوقف الموجودة ستلاحظ أن شاشتنا ستظهر بشكل مصغر داخل نافذة العرض وكذلك إذا اخترت الزر اعدادت ستظهر لك فورم الاعدادات اما إذا اخترت الزر عرض فان شاشة التوقف سوف تظهر لك بشكلها الكامل بحيث انك لو حركت الفأرة ستختفي فوراً .....
ملاحظة بسيطة :
اختر شاشتنا من قائمة شاشات التوقف ستظهر لك كنموذج للعرض اذهب فوق هذا النموذج المصغر بالفارة ستجد أن شاشتنا قد اختفت من
شاشة العرض وذلك لان الحدث MouseMove قد تم استدعائه فقام بإغلاق البرنامج...
الآن كرر العملية السابقة على أي شاشة اخرى من القائمة ستجد أن شاشة العرض لم تختفي حتى لو حركت الفارة فوقها .....
كيف يمكن أن نتلافى هذه المشكلة ؟؟
يمكن حل هذه المشكلة بإضافة فورم3 تحمل كل خصائص فورم1 ولكنها لاتحتوي على شفرة الاغلاق الموجودة في الحدثان MouseMove و
KeyPress* في الواقع لاتحتوي إلا على الكود الموجود في الحدث Timer فقط مع تغيير قطر الدائرة حتى يتناسب مع حجم شاشة العرض الصغيرة* يمكنك تغييره من 100 الى 20 مثلاً:
code: Private Sub Timer1_Timer()
Dim X As Integer
Dim Y As Integer
X = Int(Rnd * Me.ScaleWidth)
Y = Int(Rnd * Me.ScaleHeight)
Me.FillColor = QBColor(Int(Rnd * 14) + 1)
Circle (X* Y)* 20
End Sub
كما يجب أن نستبدل الشفرة في الاجراء الرئيسي بحيث يعرض الفورم3 بدلاً من الفورم1 * كالتالي :
code: If S = "/p" Then
W = CLng(Mid(Command* 4))
Load Form3
SetParent Form3.hwnd* W
Form3.Show
End If
ملاحظة :
كانت شاشة التوقف السابقة شاشة بسيطة جداً ولا تحتوي على أي من المؤثرات مثل الصوت والصور وغيرها وذلك لإيصال الطريقة الاساسية
لعمل شاشات التوقف...
كما أن تخصيص شاشة مستقلة للعرض المصغر هي طريقة تفي بالغرض مع وجود طريقة اخرى ولكن هذه الطريقة تعتمد على بعض دوال API وهذا هو السبب الذي جعلني أتجنبها حتى يبقى الموضوع مفهوماً حتى لمن لا يمتلك الخبرة الكافية في دوال API ...
وبذلك اكون قد وصلت الى نهاية حديثي الذي حاولت أن اوضح فيه اكبر قدر من المعلومات للذي يحاول أن يلم بموضوع شاشات التوقف *واعذروني
على اي تقصير في شرح الموضوع.....
والسلام عليكم ورحمة الله...
شاشة التوقف هي عبارة عن برنامج يحمل اللاحقة scr بدلاً عن اللاحقة exe ويوجد في مجلد الوينذوز يقوم في معظم حالاته بإظهار ألوان و رسوم
متحركة بغرض حماية الشاشة و لذلك يسمى حافظ الشاشة أو Screen Saver وذلك لان الشاشة تتأثر بوجود اللون الواحد في نفس المكان لمدة طويلة ولذلك نجد أن شاشات التوقف تحتوي على الكثير من الألوان و الرسوم المتحركة التي تقوم بعملية تجديد العرض في جميع أجزاء الشاشة* و يقوم نظام التشغيل باستدعاء شاشة التوقف بعد مرور فترة زمنية دون أن يقوم المستخدم بتحريك الفأرة أو الضغط على أي زر وذلك على افتراض أن المستخدم ليس امام الجهاز وبالتالي فانه من الأفضل حماية الشاشة بشاشة التوقف...
خصائص شاشة التوقف و بماذا تختلف عن البرنامج العادي ؟
1 – شاشة التوقف تشغل الشاشة كاملة وتغطي حتى شريط المهام.
2 – لايوجد لها شريط عنوان او ازرار تكبير*تصغير او إغلاق.
3 – تحتوي على الكثير من الحركة والألوان.
4 – تختفي بمجرد تحريك الماوس او الضغط على احد ازرار لوحة المفاتيح.
5 – لايجب ان تشتغل اكثر من نسخة من شاشة التوقف في نفس الوقت.
6 – عند ترجمة البرنامج نستخدم اللاحقة SCR بدلاً عن EXE كما ذكر سابقاً.
7 – يجب وضع شاشة التوقف في مجلد الوينذوز.
8 – يفضل أن تحتوي على فورم للإعدادت تمكن المستخدم من تغير سرعة الحركة مثلاً.
سنناقش الآن النقاط السابقة بحسب الترتيب...
1- 2 - لكي يكون لدينا فورم تغطي الشاشة كاملة نبدأ برنامج جديد ونعين الخصائص التالية للفورم1 :
Caption = “” لايوجد عنوان
MinButton = false لايوجد زر تصغير
MaxButton = false لايوجد زر تكبير
ControlBox = false لايوجد شريط عنوان ولا زر إغلاق
WindowState = Maximized جعل الفورم تغطي الشاشة كاملة
BackColor = Black يفضل جعل لون الخلفية اسود(يمكنك تغير اللون)
3 – اما موضوع الالوان والحركة فهي متروكة لك ولكن لمزيد من التوضيح سوف اجعل شاشة التوقف تقوم بعرض الكثير من الدوائر العشوائية على
الفورم كمثال توضيحي :
أ – غير الخاصية FillStyle التابعة للفورم الى القيمة Solid .
ب – اضف Timer الى الفورم.
ج – غير الخاصية Interval التابعة له الى القيمة 100.
ح – اكتب الشفرة التالية :
code: Private Sub Timer1_Timer()
Dim X As Integer
Dim Y As Integer
X = Int(Rnd * Me.ScaleWidth) إحداثيات الدائرة على المحور السيني
Y = Int(Rnd * Me.ScaleHeight) إحداثيات الدائرة على محور الصادات
Me.FillColor = QBColor(Int(Rnd * 14) + 1) تحديد لون عشوائي للدائرة
Circle (X* Y)* 100 رسم الدائرة المطلوبة في الموقع العشوائي
End Sub
الشفرة السابقة تقوم برسم دوائر ملونة عشوائية صغيرة حول الفورم.
4 – يجب ان تحتوي الفورم على وسيلة للإغلاق وذلك بتحريك الفأرة او الضغط على زر في لوحة المفاتيح * فكما نعلم انه عند تحريك الفأرة على
الفورم فأنه يستدعى الحدث MouseMove وكذلك عند الضغط على أي زر يستدع الحدث KeyPress ويمكن ان تضع الامر End الذي ينهي البرنامج
في كلا الحدثين كالتالي :
code: Private Sub Form_KeyPress(KeyAscii As Integer)
End
End Sub
Private Sub Form_MouseMove(Button As Integer* Shift As Integer* X As Single* Y As Single)
Static Num As Integer
Num = Num + 1
If Num > 3 Then End
End Sub
ملاحظة : يقوم البرنامج باستدعاء الحدث MouseMove عند بداية التشغيل ولذلك سوف ينتهي برنامجنا قبل ان يبدأ وذلك لوجود الامر End فيه* لهذا وضعنا شرط بحيث نتجاهل الاستدعاءات الثلاثة الاولى ..
5 – يجب ان نمنع تنفيذ اكثر من نسخة من برنامجنا في نفس الوقت وذلك ياستخدام الخاصية PrevInstance لبرنامجنا حيث انه اذا كانت توجد نسخة سابقة من البرنامج تعمل من قبل فأن قيمة هذه الخاصية تكون True ونضع شفرة الفحص في الحدث Load قبل ان يتم عرض البرنامج كالتالي :
code: Private Sub Form_Load()
If App.PrevInstance Then End
End Sub
أي انه عندما تكون هذه الخاصية True فانه يوجد نسخة من البرنامج تعمل مسبقاً ولا يوجد داعي لتعمل نسخة أخرى وبذلك ننهي النسخة
الجديدة.
6 – 7 – عندما نترجم البرنامج بواسطة الامر Make Project1.exe من القائمة ملف نكتب اسم شاشة التوقف ثم نتبعها باللاحقة scr ( مثلاً
Circles.scr ) ثم نقوم بحفظ البرنامج في مجلد الوينذوز وذلك لكي يظهر في قائمة شاشات التوقف التي يمكن عرضها من خلال خصائص سطح
المكتب .
كان القسم الاول من الدرس يتعلق بأساسيات تصميم شاشة التوقف ولكن يجب علينا ان نعرف ان شاشة التوقف اكثر تعقيداً من ذلك نظراً لان الوينذوز يستدعيها اكثر من مرة و لأغراض مختلفة* مثلاً عندما يختار المستخدم اسم برنامجنا من قائمة شاشات التوقف الموجودة في خصائص سطح المكتب فان المطلوب هنا ان تعمل نسخة مصغرة من برنامجنا في شاشة العرض الصغيرة المجاورة* وكذلك عندما يختار المستخدم الزر اعدادت يجب عرض الفورم الذي يهتم بجزء الإعدادات وليس الفورم الذي يحتوي على شاشة التوقف ( وهي الشاشة التي تعرض الدوائر الملونة في مثالنا السابق ) * وكذلك الحال عند تغير كلمة المرور لهذه الشاشة.
وبذلك أصبحنا نعرف انه يجب أن يحتوي برنامجنا على أكثر من فورم وانه يجب معرفة الفورم المناسب لكل استدعاء ثم عرض الفورم المناسب....!
ويبقى السؤال كيف يمكننا أن نعرف ما هو الوضع أو الفورم المطلوب عرضه ؟
الإجابة تكمن في البيانات التي يحملها لنا المتغير Command* كلنا يعرف أن هذا المتغير يستخدمه نظام التشغيل لتمرير بيانات للبرامج فمثلاً عند النقر المزدوج على احد ملفات برنامج الرسام والتي تحتوي على اللاحقة bmp في مستكشف وينذوز فانه يتم عرض البرنامج محتوياً الملف المذكور فكيف عرف الرسام هذا الملف ومن ثم قام بتحميله؟* وذلك لان الرسام يفحص المتغير command قبل العرض فإذا احتوى على اسم ملف يعمل على تحميل هذا الملف مباشرة...
وبنفس الطريقة يمكن لبرنامجنا معرف نوع الاستدعاء الذي يقصده نظام التشغيل هل للعرض ام لتغير الإعدادات أم لعرض نسخة مصغرة...الخ
هنا عرض لبعض الاستدعاءات الممكنة* بحسب القيمة التي يحملها المتغير command :
Command = “/s”
تدل القيمة "/s" على انه يجب عرض او تشغيل شاشة التوقف كاملة أي عرض الفورم الموجودة في المثال السابق.
Command = “/c”
يدل على انه يجب عرض شاشة الإعدادت التي تمكن المستخدم من تغير السرعة او الألوان او أي شي يتعلق بشاشة التوقف الخاصة بنا.
Command = “/p 12344”
يجب عرض نسخة مصغرة من شاشة التوقف (الرقم المجاور يختلف في كل مرة) حيث يدل هذا الرقم المجاور للحرف /p على رقم الشاشة المصغرة الذي يمكن ان نستخدمه لجعل شاشتنا تعمل داخل إطار الشاشة المخصصة للعرض.
Command = “/a 34765”
يستخدم ليدل على انه يجب عرض الفورم الخاص بتغيير كلمة المرور كما ان الرقم قد يتغير..
دعونا الآن نحاول البدء بتصميم شاشة توقف مثالية مع استخدام الفورم التي انشئناها سابقاً مع تغيير ما يلزم...
سنقوم اولاً بإضافة فورم جديد Form2 إلى البرنامج يمكن بواسطة ان نغير إعدادت شاشة التوقف وسيكون هذا الفورم بسيطاً حيث يحتوي على زرين و شريط تمرير افقي و عنوان (Label)* غير الخصائص التابعة لكل عنصر كما يلي :
Form1
Caption = “إعدادت شاشة التوقف”
BorderStyle = Fixed Dialog
Command1
Caption = “موافق”
Command2
Caption = “إلغاء الامر”
HScroll1
Min = 1
Max = 1000
Value = 100
Label1
Caption =“اختر السرعة التي تناسبك”
سوف نستخدم شريط التمرير لتغيير سرعة ظهور الدوائر في شاشة التوقف وسوف نخزن القيمة في Registry ( او مسجل النظام ) وذلك حتى تظل محفوظة عند تشغيل شاشة التوقف في المرة المقبلة.
قم الآن بكتابة الشفرة التالية :
code: Private Sub Command1_Click()
SaveSetting "ScreenSaver"* "Options"* "Speed"* HScroll1.Value
End
End Sub
Private Sub Command2_Click()
End
End Sub
Private Sub Form_Load()
HScroll1.Value = GetSetting("ScreenSaver"* "Options"* "Speed"* 100)
End Sub
و بذلك نكون قد انتهينا من فورم الاعدادات...
نقوم بتعديل الشفرة الموجودة في الحدث Load للفورم1 بحيث يصبح كالتالي :
code: Private Sub Form_Load()
Timer1.Interval = 1001 - Clng(GetSetting("ScreenSaver"* "Options"* "Speed"* "100"))
End Sub
تقوم الشفرة السابقة بمعرفة سرعة الرسم التي تم تخزينها في Registry وذلك بواسطة شاشة الاعدادت التي انشئناها قبل قليل.
بقي امامنا ان نعرف كيف يمكن لبرنامجنا اختيار الفورم الصحيحة للتشغيل اعتماداً على قيمة المتغير Command المذكور سابقاً .
نظراً لان البرنامج لن يشغل فورم معينة دائماً وانما سيختار احداهما فانه من الافضل ان نغير كائن بدء التشغيل في برنامجنا وجعله Sub Main بدلاً من فورم1* وذلك كالتالي :
من القائمة Project نختار خصائص التشغيل او Project1 Properties ثم نغير الـ Startup Object من Form1 الى ٍ ٍSub Main * ثم نقوم بإضافة
Module جديد الى المشروع ونكتب فيه التالي :
code: Sub Main()
End Sub
ونكون بذلك قد جعلنا هذا الاجرء Sub Main هو الاجراء الذي سيتم استدعائه عند بدء التشغيل بدلاً عن فورم1 وفيه سنضع الشفرة التي سوف تمكنا من تحديد الفورم المطلوب تشغيله .
عند هذة النقطة اجد نفسي مضطراً لأن اقوم بتوضيح كيفية تعامل نظام التشغيل مع النوافذ المختلفة التي تعمل في نفس الوقت وذلك كأساس
لفهم الخطوات التي سنقوم بها لاحقاً لنصل في النهاية الى تصميم شاشة توقف تمتلك كل خصائص شاشة التوقف القياسية في الوينذوز....
عند تشغيل أي نافذة جديدة فان نظام التشغيل يحدد لها رقم معين يمكنك معرفة الرقم المعين لأي فورم وذلك بواسطة الخاصية hWand التي توجد في كل فورم* لطباعة الرقم الخاص على الفورم اكتب السطر التالي : Print Form1.hWand
وتكمن فائدة هذا الرقم في أن معظم دوال API تتعامل معه لتمكينك من التحكم في أي نافذة موجودة في النظام مثل تحريك* تغيير حجم* إخفاء* إظهار وكل ما يخطر ببالك من انواع التحكم.
كما أنه يوجد نوعان من النوافذ Parent و Child وكما هو واضح من التسمية احدهما هو الأب والآخر هو الابن حيث لا يسمح للابن بالعمل خارج إطار الاب مثل برنامج الـ Word فانه يمكن أن تفتح اكثر من مستند في نوافذ مختلفة داخل البرنامج نفسه بحيث لا تخرج نوافذ هذه المستندات من إطار الـ Word وبكلمات اخرى أن الورد هو الاب وكل المستندات بداخله هي ابنا اما الورد فهو اب ولا يوجد له اب آخر غير سطح المكتب طبعاً * وكل الفورمات الموجودة في الفيجوال بيسك هي من النوع Parent بشكل افتراضي ويمكنك تغيرها طبعاً!....
ويمكنك معرفة رقم النافذة الاب لاي نافذة اخرى عن طريق دالة GetParent وهي احدى دوال الـ API وذلك بتمرير رقم النافذة التي تريد معرفة رقم الاب لها * مثلاً :
code: Msgbox GetParent( Form1.hwnd )
يقوم السطر السابق بعرفة رقم الاب للفورم1 .
كما يمكنك جعل نافذة اب لنافذة اخرى فلجعل فورم1 اب لفورم2 استخدم الدالة SetParent كالتالي :
code: SetParent Form2.hwnd * Form1.hwnd
يمكن تنفيذ الامر السابق اذ كان الفورمان يعملان في نفس الوقت حيث يجعل فورم2 تعمل داخل فورم2....
ملاحظة : اذا كانت النافذة هي نافذة اب وحاولت أن تعرف رقم الـ Parent لها باستخدام الدالة GetParent فان الناتج سوف يكون صفر....
ولكن ماعلاقة كل ذلك بتصميم شاشة توقف ؟؟...
يجدر ملاحظة أن فورم1 في شاشة التوقف التي انشئناها يجب أن تعمل بطريقتن الاولى هي الطريقة العادية أي أن تغطي كل الشاشة وذلك عند مرور الوقت المحدد دون تحريك الفأرة أو لوحة المفاتيح(أي أن شاشة التوقف تكون في هذة الحالة نافذة Parent)* ام الحالة الثانية فهي عندما يختار المستخدم شاشتنا من خصائص سطح المكتب فانه يجب أن تعمل نافذتنا في النافذة الصغيرة التي تظهر في خصائص سطح المكتب حتى يقرر المستخدم ما إذا كان سوف يستخدمها ام لا وبذلك يجب أن تعمل شاشتنا داخل اطار نافذة العرض أي تكون نافذة ابن* ويمكن معرفة رقم نافذة العرض الصغيرة حتى نمررها للدالة SetParent بواسطة المتغير Command حيث تكون قيمته في هذة الحالة مثلاً هي : “/p 131792”
ويمثل الرقم الذي يلي الحرف رقم نافذة العرض...
بعد ان تعرفنا على هذة المبادئ يمكن الآن أن نكتب الشفرة التي سوف تختار أي فورم تشغل وكيفية الوضع المناسب لها وهي الشفرة التي
سوف توضع في Module1 الجديد الذي اضفناه سابقاً :
code: Public Declare Function SetParent Lib "user32" (ByVal hWndChild As Long* ByVal hWndNewParent As Long) As Long
Sub Main()
Dim S As String
Dim W As Long
S = LCase(Left(Command* 2)) استخراج الحرفان الأوليان
If S = "/s" Then عرض شاشة التوقف الكاملة
Form1.Show
Exit Sub
End If
If S = "/c" Then عرض الاعدادات
Form2.Show
Exit Sub
End If
If S = "/p" Then عرض شاشة توقف مصغرة
W = CLng(Mid(Command* 4))
Load Form1
SetParent Form1.hwnd* W
Form1.Show
End If
End Sub
في الشفرة اعلاه قمنا بحفظ الحرفين الأوليين للمتغير Command في المتغير S وهما الحرفان اللذان يمكننا بواسطتهما معرفة الفورم المطلوبة* ثم
نفحص قيمة هذا المتغير S :
S=”/s” يجب تشغيل شاشة التوقف في الوضع الكامل أي فورم1
S=”/c” يجب تشغيل فورم الإعدادات أي فورم2
S=”/p” يجب تشغيل فورم1 للعرض في النافذة الصغيرة
لاحظ اننا قمنا بإستدعاء الفورم المناسبة في كل مرة ماعدا في الحالة الاخيرة فانه لتشغيل فورم1 للعرض في النافذة الصغيرة أي كابن لها فانه
يجب علينا معرفة رقم هذة النافذة الصغيرة وذلك عن طريق المتغير Command حيث استخرجنا الرقم ثم قمنا بحفظه في المتغير W وبعد ذلك قمنا بتحميل فورم1 وذلك للحصول على رقمها هي ايضاً وبعد ذلك اصبح لدينا الرقمان المطلوبان وهما رقم الاب(نافذة العرض الصغيرة) و رقم الابن (فورم1) ثم استدعينا الدالة SetParent التي قامت بتحويل فورم1 من نافذة اب الى نافذة ابن لنافذة العرض* وبعد نجاح العملية يمكننا الان أن نجعل فورم1 مرئية عن طريق Form1.Show وذلك لان الامر Load Form1 يعمل على تحميل الفورم وليس عرضها...وبذلك نكون قد انهينا تصميم شاشة
توقف كاملة بجميع خصائصها ....
قم بترجمة شاشة التوقف ولكن باستخدام اللاحقة Scr بدلاً من exe كما هو موضح مسبقاً و احفظها في مجلد الوينذوز * ثم اذهب الى خصائص سطح المكتب واختار شاشة توقفنا من قائمة شاشات التوقف الموجودة ستلاحظ أن شاشتنا ستظهر بشكل مصغر داخل نافذة العرض وكذلك إذا اخترت الزر اعدادت ستظهر لك فورم الاعدادات اما إذا اخترت الزر عرض فان شاشة التوقف سوف تظهر لك بشكلها الكامل بحيث انك لو حركت الفأرة ستختفي فوراً .....
ملاحظة بسيطة :
اختر شاشتنا من قائمة شاشات التوقف ستظهر لك كنموذج للعرض اذهب فوق هذا النموذج المصغر بالفارة ستجد أن شاشتنا قد اختفت من
شاشة العرض وذلك لان الحدث MouseMove قد تم استدعائه فقام بإغلاق البرنامج...
الآن كرر العملية السابقة على أي شاشة اخرى من القائمة ستجد أن شاشة العرض لم تختفي حتى لو حركت الفارة فوقها .....
كيف يمكن أن نتلافى هذه المشكلة ؟؟
يمكن حل هذه المشكلة بإضافة فورم3 تحمل كل خصائص فورم1 ولكنها لاتحتوي على شفرة الاغلاق الموجودة في الحدثان MouseMove و
KeyPress* في الواقع لاتحتوي إلا على الكود الموجود في الحدث Timer فقط مع تغيير قطر الدائرة حتى يتناسب مع حجم شاشة العرض الصغيرة* يمكنك تغييره من 100 الى 20 مثلاً:
code: Private Sub Timer1_Timer()
Dim X As Integer
Dim Y As Integer
X = Int(Rnd * Me.ScaleWidth)
Y = Int(Rnd * Me.ScaleHeight)
Me.FillColor = QBColor(Int(Rnd * 14) + 1)
Circle (X* Y)* 20
End Sub
كما يجب أن نستبدل الشفرة في الاجراء الرئيسي بحيث يعرض الفورم3 بدلاً من الفورم1 * كالتالي :
code: If S = "/p" Then
W = CLng(Mid(Command* 4))
Load Form3
SetParent Form3.hwnd* W
Form3.Show
End If
ملاحظة :
كانت شاشة التوقف السابقة شاشة بسيطة جداً ولا تحتوي على أي من المؤثرات مثل الصوت والصور وغيرها وذلك لإيصال الطريقة الاساسية
لعمل شاشات التوقف...
كما أن تخصيص شاشة مستقلة للعرض المصغر هي طريقة تفي بالغرض مع وجود طريقة اخرى ولكن هذه الطريقة تعتمد على بعض دوال API وهذا هو السبب الذي جعلني أتجنبها حتى يبقى الموضوع مفهوماً حتى لمن لا يمتلك الخبرة الكافية في دوال API ...
وبذلك اكون قد وصلت الى نهاية حديثي الذي حاولت أن اوضح فيه اكبر قدر من المعلومات للذي يحاول أن يلم بموضوع شاشات التوقف *واعذروني
على اي تقصير في شرح الموضوع.....
والسلام عليكم ورحمة الله...