برامج

۝ ::.كما وعدكم الفرعون قنبله جديده دوره بلغه الدلفي.::۝ [الأرشيف] - برامج نت

المساعد الشخصي الرقمي

مشاهدة النسخة كاملة : ۝ ::.كما وعدكم الفرعون قنبله جديده دوره بلغه الدلفي.::۝


الفرعون المحترف
12-08-2006, 03:08 PM
نريد شي دا فائدة للجميع :
لذلك قررت ان ابدا في فكرة جميلة , وهي دورة دلفي يتعاون فيها الجميععععععععع , كل مرة نطرح موضوع و الجميع يضيف على هذا الموضوع ما يفيد من ملاحضات حتى تعم الفائدة

انبدا

برنامج دلفي يتكون من وحدتين رئيسيتين هما
1-program البرنامج الرئيسي
2-unit وحدات اخري

البرنامج في دلفي يتكون من برنامج رئيسي واحد , ومجموعة وحدات اخرى (عددها غير محدد).

1- البرنامج الرئيسي ياخد الهيكلية التالية :

program اسم البرنامج;

uses
جزاء يستخدم عندما نريد استخدام دوال او برامج موجودة في ملف أخر .


begin
اوامر البرنامج الرئيسي
end.

----

2- الوحدات الاخرى

وتاخد الهيكليةالتالية

unit Unit1; { تعريف الوحدة}
interface جزء التعريفات حيت يتم في هذا الجزء تعريف كل المتغيرات الخارجية في هذه الوحدة
uses { جملة استخدام دوال و تجهيزات اضافية}

implementation جزء الذي يكتب فيه اوامر و دوال لغة الدلفي

initialization جزء اعطاء القيم البتدائية للمتغيرات
finalization تنفد عندما ينتهي تنفيد البرنامج الرئيسي , لكي نتمكن من التعامل مع المتغيرات التي قد نكون قد حجزناه في جملة initialization ز
{ }
end.نهاية الوحدة
عبارة IF,Then,Else:


هذه العبار هي عبارة اشتراطيه
فمثلاً انت تريد انه اذا كان المتغير i يساوي القيمة 5 يتم اغلاق البرنامج
فاليك هذا الكود

var
i:integer;
begin
if i=5 then
close
else
ShowMessage('arabdevelopers');


ففي هذا الكود يقوم البرنامج بفحص I فعندما تكون I=5 يقوم بأغلاق البرنامج
وعبارة else تفيد عدم حدوث الشرط فعندما تكون I لاتساوي 5 فعندها ستظر لك رسالة مكتوب بها (arabdevelopers)
ولكن الكود السابق يطبق لك السطر الأول بعد الشرط فقط فعندما تريد فعل اكثر من امر قم بكتابة Begin بعد الشرط وفي نهاية الأوامر ضع End
كما في هذا المثال:
var
i:integer;
begin
if i=5 then
begin
form1.Hide;
ShowMessage('OK');
end
else
begin
ShowMessage('arabdevelopers');
end;ارجو ان تكون قداضحت لكم (( وهذه العبارة كثيرة الأستخدام في دلفي ))
عبارة case


هذه العبارة مشابهه للعبارة IF,Then ولكنها متطورة بعض الشيء
ففي هذه العبارة تستطيع اشتراط اموامر كثيرة فبدلاً من ان تكتب هذا الكود في عبارة IF,ThenVar
i:integer;
begin
if i=1 then
ShowMessage('1');
if i=2 then
ShowMessage('2');
if i=3 then
ShowMessage('3');
....فيمكنك عملها بعبارة case ببضعة اسطر انظر الى المثال التالي:


var
i:integer;
begin
case i of
1: ShowMessage('1');
2: ShowMessage('2');
3: ShowMessage('3');
...وهاكذا
ارجو ان تكون قد اتضحت لكم

فان اي جملة اساسية في لغة تستخدم نضام block المقاطع .
وساشرح معني ذلك

متلا جملة if , تستطيع تنفيد مقطع واحد فقط بعدها
والمقطع ينقسم الى جزئين :
1- جملة واحدة
2- مجموعة جمل وفي هذه الحالة نستخدم عبارة begin ,end

متلا
الحالة الاولى

if(x > 5) then
;y=5الحالة التانية
if(x=5) then
begin
;y=6
;h=2
;endاي انه اذا احتجنا لتنفيد اكتر من جملة تحت جملة رئيسية فاننا نستخدم begin , end

برنامج دلفي يتكون من

مشروع project و هو البرنامج الرئيسي
ووحدات اخري unit.


مشروع اارة مكتبة

-------------------------------------------- ......
| | |
الشاشة الرئيسية عرض الكتب شؤو الموظفين .....

نلا حظ ان مشروع ادارة المكتبة يتكون من ملف المشروع نفسه

ومجموعة وحدات اخرى متل الشاشة الرئيسية او عرض الكتب ....


المشروع يتكون من ملف واحد
بينما الوحدات تتكون من
وحدة و شكل unit ,Form
الوحدة هي المكان الذي نكتب فيه خطوات البرمجو
و الشكل هو المكان الذي نقوم بتصميمه و و ضع الاشكال الاخرى عليه (بمعنى انه واجهة التطبيق)التعبيرات والعامِلات
لا توجد قاعدة عامة لبناء التعبيرات expressions ، حيث تعتمد اساسا على العامِلات التي تستخدم، و التي لباسكال العديد منها. هناك المنطقي logical والحسابي arithmetic والبولي Boolean والعلائقي relational ، و عاملات الفئة set، بالاضافة الى عدد آخر. يمكن استعمال التعبيرات لتحديد القيمة التي ستخصص للمتغير، او لحساب المحدد parameter التابع لوظيفة او اجراء، او لاختبار شرط. و قد تتضمن التعبيرات استدعاء وظائف ايضا. في كل مرة تقوم فيها باجراء عملية على قيمة في معرّف، و ليس استعمال المعرف في حد ذاته، فان هذا يعدّ تعبيرا .

تعد التعبيرات امرا شائعا في لغات البرمجة. التعبير هو أي توليفة من الثوابت constants ، المتغيرات، القيم الحرفية literal ، عاملات، و نتائج الوظائف. التعبيرات يمكن ايضا تمريرها الى المحددات القيمية value parameters في الاجراءات و الوظائف، و لكن ليس دائما الى المحددات المرجعية reference parameters (التي تحتاج الى قيمة يمكن تخصيصها).

** العامِلات و أسبقيتها
فيما يلي قائمة بعاملات اللغة، مجمعة حسب الأسبقية

1- عاملات أحدادية (أسبقية عليا)

@ عنوان المتغير أو الوظيفة (ترجّع مؤشّر)
not بولي أو ما يخص الجزيئات


2- العاملات الضربية و ما يخص الجزئيات
* ضرب حسابي أو تقاطع فئة
/ تقسيم نقطة عائمة
div تقسيم عدد صحيح
mod البواقي (باقي تقسيم عدد صحيح)
as تلبيس نوع آمن (RTTI)
and بولي أو ما يخص الجزيئات
shl ازاحة لليسار فيما يخصّ الجزئيات
shr ازاحة لليمين فيما يخصّ الجزئيات

3- العاملات الجمعية
+ جمع حسابي، اتحاد فئة، ربط جمل، اضافة رصيف مؤشّر
- طرح حسابي، طرح وتخالف فئة، طرح صف مؤشّر
or بولي أو ما يخص الجزيئات
xor بولي أو ما يخص الجزيئات


4- عاملات العلاقة والمقارنة (أسبقية دنيا)
= اختبار مساواة
<> اختبار عدم مساواة
< اختبار أقل من
> اختبار اكبر من
<= اختبار أقل من أو يساوي، أو فئة فرعية من فئة
>= اختبار أكبر من أو يساوي، أو فئة عليا تعلو فئة
in اختبار اذا ما عنصر عضو في فئة
is اختبار توافقية نوع لكائن(عامل RTTI آخر)



** عاملات الفئة

عاملات الفئة تتضمن اتحاد union (+)، طرح difference (-)، تقاطع intersection ( * )، اختبار عضوية membership (in)، بالإضافة الى مجموعة من العاملات العلائقية. لاضافة عنصر لمجموعة، يمكنك جعل اتحاد فئةة مع آخرى تملك فقط العنصر الذي تحتاجه. فيما يلي مثال بدلفي له علاقة بنمط الخطّ font styles:




Style := Style + [fsBold];
Style := Style + [fsBold, fsItalic] - [fsUnderline];


المتغيرات
تتطلّب دلفي ان تكون كل المتغيرات معرّفة قبل استخدامها. وحتى في الوقت الذي تعرّف فيه المتغير، يجب أن تحدّد نوع البيانات. ها هنا بعض نماذج تعريف المتغيرات:var

Value: Integer;

IsCorrect: Boolean;

A, B: Char;

المصطلح var يمكن استخدامه في اماكن مختلفة في الكود، كأن يكون في بداية توليف وظيفة أو اجراء، او ان يتم تعريف المتغيرات محليا local في الروتين ، أو داخل الوحدة لتعريف متغيرات جامعة global. بعد مصطلح var تأتي قائمة اسماء المتغيرات، متبوعة بشارحة واسم نوع البيانات. يمكنك كتابة اكثر من اسم متغير واحد في السطر الواحد، كما هو في آخر تعليمة أعلاه.

حالما تقوم بتحديد متغير من نوع ما، تستطيع ان تقوم فقط بمباشرة العمليات الداعمة لنوع بياناته. على سبيل المثال، يمكنك استعمال القيمة البولية للاختبار و القيمة الصحيحة في التعبير الرقمي.

باستخدام تخصيصات بسيطة، نستطيع كتابة التوليف التالي:

Value := 10;

IsCorrect := True;
لكن التعليمة التالية ليست صحيحة، لأن المتغيرين يملكان نوع بيانات مختلف

Value := IsCorrect; // errorاذا حاولت تحويل هذا التوليف، فان دلفي تقوم باصدار خطأ تحويل رفق هذا التوضيح: Incompatible types: 'Integer' and 'Boolean'. عادة، مثل هذه الأخطاء هي أخطاء برمجية، لأنه لامعنى لتخصيص قيمة True أو False لقيم من نوع بيانات صحيح. يجب أن لا تلوم دلفي على مثل هذه الأخطاء. هي فقط تنبهك لوجود خطأ ما في التوليف.

بالطبع، غالبا مايمكن تبديل قيمة متغير من نوع بيانات الى نوع مختلف. في بعض الحالات، هذا التبديل يكون آليا، لكن عادة ما تحتاج الى استدعاء وظائف محددة في النظام لتغيير التمثيل الداخلي للبيانات.

تستطيع في دلفي ان تخصص قيمة تمهيدية لمتغير جامع global variable أثناء تعريفك له. مثلا، تستطيع كتابة:





var

Value: Integer = 10;

Correct: Boolean = True;



تقنية التمهيد initialization هذه تصلح فقط للمتغيرات الجامعة، وليس للمتغيرات المعرفة داخل نطاق اجراء أو مسار.


الثوابت

تسمح دلفي ايضا بتعريف ثوابتا constants لتسمية القيم التي لاتتغير خلال عمل البرنامج. لتعريف ثابت لاتحتاج لتحديد نوع البيانات، فقط تخصيص قيمة ابتدائية. المحوّل سيتفحّص القيمة وآليا يستخدم نوع بياناته المناسب. هنا بعض امثلة التعريفات:



const

Thousand = 1000;

Pi = 3.14;

PName = 'Open';



يقرر دلفي نوع البانات للثابت بناء على قيمته. في المثال أعلاه، الثابت Thousand يفترض ان يكون من نوع صحيح صغير SmallInt ، اصغر نوع صحيح يمكنه احتواء القيمة. اذا اردت الطلب من دلفي استخدام نوع محدد؛ يمكنك ببساطة اضافة اسم النوع في التعريف، كما هو في:



const

Thousand: Integer = 1000;



عندما تقوم بتعريف ثابت، يستطيع المحوّل أن يختار بين أن يخصص موقعا في الذاكرة للثابت، و يحفظ فيه قيمته، أو أن ينسخ قيمته الحقيقية في كلّ مرة يتم فيها استخدامه فيها

المرجع
كتاب ماركو كانتو




أنواع بيانات جديدة

إن أحد أعظم الأفكار التي قدمتها لغة دلفي هي القدرة على تحديد أنواع بيانات جديدة في البرنامج. يستطيع المبرمجون تحديد أنواع بيانات خاصة بهم بواسطة مشيّدات النوع type constructors، مثل أنواع المدى الفرعي subrange، نوع مصفوفة array، نوع تسجيلة record، نوع سردي enumerated، نوع مؤشّر pointer ، ونوع فئة set. أكثر أنواع البيانات المحددة بالمستعمل أهمية هي الطبقة أو الفصيلة class، و التي هي جزء من اضافات الاتجاه الكائني object-oriented في باسكال،


الأنواع المسماة وغير المسماة

هذه الأنواع يمكن إعطاؤها اسما للرجوع اليه لاحقا أو أن تطبّق على المتغيرات مباشرة. عندما تعطي اسما لنوع، يجب أن توفّر مساحة خاصة في التوليف، مثل الآتي:





type

// subrange definitionتعريف نطاق

Uppercase = 'A'..'Z';



// array definition تعريف مصفوفة

Temperatures = array [1..24] of Integer;



// record definition تعريف سجل او هيكل بيانات Strucure

Date = record

Month: Byte;

Day: Byte;

Year: Integer;

end;



// enumerated type definition المتعددات

Colors = (Red, Yellow, Green, Cyan, Blue, Violet);



// set definition فئات

Letters = set of Char;



ويمكن تعريف متغير من غير تسمية صريحة للنوع، كما هو في التوليف التالي








var

DecemberTemperature: array [1..31] of Byte;

ColorCode: array [Red..Violet] of Word;

Palette: set of Colors;



ملاحظة:
عموما يجب عليك أن تتجنّب استخدام الأنواع غير المسمّاة unnamed مثل التوليف السابق، و ذلك لأنك لن تستطيع أن تمرّرها كمحدّدات الى الإجرائيات، أو أن تقوم بتصريح متغيّرات أخرى من نفس النوع. إن قواعد توافقية النوع في باسكال تعتمد في الواقع على أسماء الأنواع، و ليس على ما تم تحديده فعليا من أنواع. إن متغيّرين من نوعين متطابقين لايعتبران متوافقين، إلا إذا كانا نوعاهما يحملان نفس الإسم حرفيا، أما الأنواع غير المسمّاة فإنها تُعطى أسماء داخلية من قبل المجمّع compiler. حاول أن تتعوّد على عمليات تحديد نوع البيانات في كل مرّة تحتاج فيها إلى متغير مركب و غير بسيط،




امتلة

أنواع مدى فرعي
نوع المدى الفرعي subrange يحدد مدىً من القيم داخل نوع مدى آخر (من هنا اسم مدى فرعي). يمكنك تحديد مدى فرعي لنوع صحيح، من 1 إلى 10 او من 100 إلى 1000، أو تستطيع ان تحدد مدى فرعي من نوع حرف Char، كما في:





type

Ten = 1..10;

OverHundred = 100..1000;

Uppercase = 'A'..'Z';



تحديد المدى الفرعي، لا تحتاج إلى تحديد اسم النوع الأساسي. أنت تحتاج فقط إلى تقديم ثابتين من نفس ذلك النوع. النوع الأصلي يجب أن يكون من نوع تراتبي ordinal، و النوع الناتج سوف يكون نوعا تراتبيا آخر.

عندما تكون قد حدّدت مدى فرعيا، يمكنك رسميا أن تخصص قيمة داخل ذلك المدى. هذا التوليف يعتبر صحيحا



var

UppLetter: UpperCase;

begin

UppLetter := 'F';


ولكن هذا ليس كذلك:


var

UppLetter: UpperCase;

begin

UppLetter := 'e'; // compile-time error

كتابة التوليف السابق ينتج عنه خطأ في زمن التجميع compile-time error بالرسالة التالية:، "Constant expression violates subrange bounds." ("تعبير لثابت يتخطّى حدود المدى."). أما إذا كتبت بدلا من ذلك التوليف التالي:





var

UppLetter: Uppercase;

Letter: Char;

begin

Letter :='e';

UppLetter := Letter;



فإن دلفي ستقوم بتجميعه. و لكن في زمن التشغيل run-time ، و إذا قمت بتمكين خيار المجمّع لتفحّص المدى Range Checking فستحصل على رسالة خطأ Range check error. (تمكين الخيار من خلال مربع Project Options ثم صفحة Compiler).


الأنواع السردية
تشكّل الأنواع السردية enumerated نوعا تراتبيا آخرا محددة بالمستعمل. فبدلا من الإشارة إلى مدى من نوع موجود، فإنك في السردية تقوم بعرض القيم المحتملة للنوع. بمعنى آخر، السردية هي قائمة بالقيم. فيما يلي بعض الأمثلة:
[





type

Colors = (Red, Yellow, Green, Cyan, Blue, Violet);

Suit = (Club, Diamond, Heart, Spade);



/CODE]كلّ قيمة في القائمة لها ما يصاحبها من ترتيب ordinalty، بدءاً من الصفر. عندما تطبق وظيفة ord على على قيمة من نوع سردي، تتحصّل على نفس هذه القيمة المبتدئة بصفر. مثلا، Ord (Diamond) ترجع 1.



مكتبة المكوّنات المرئية VCL (Visual Component Library) في دلفي تستخدم الأنواع السردية في عدّة أماكن. مثال ذلك، نمط الحدود لنموذج form معرّف كالتالي:



type

TFormBorderStyle = (bsNone, bsSingle, bsSizeable,

bsDialog, bsSizeToolWin, bsToolWindow);

عندما تكون السِمة property قيمتها سردية، عادة ما تختار من قائمة القيم المعروضة في معاين الكائنات Object Inspector في الدلفي ,
في المتال السابق كانت القائمة لا حد خواص الفورم وهي شكل الفورم . و هناك خواص اخرى ايضا هي عبارة عن قوائم سردية متل
خاصية ALign و WindowState و غيرها .



نوع فئة
أنواع الفئة set تشير إلى مجموعة من القيم. فهي صفّ من القيم المحتملة ذات نفس النوع التراتبي ordinal الذي للفئة. هذه الأنواع التراتبية عادة ما تكون محدودة، و غالبا ما يتم تمثيلها بسردية enumeration أو مدى فرعي subrange. إذا أخذنا المدى الفرعي 1..3، فإن القيم المحتملة للفئة التي ستبنى على هذا المدى سوف تتضمن إما: فقط 1، فقط 2، فقط 3، كلا 1 و 2، كلا 1 و 3، كلا 2 و 3، كل القيم الثلاث، أو لا واحدة منهم.

أي متغيّر عادة ما يضّم أحد هذه القيم المحتملة من المدى الذي يسمح به نوعه. أما المتغير الذي من نوع فئة، يمكنه أن يحوي أكثر من قيمة واحدة، فقد يحوي لا شيء، واحدة، إثنتان، ثلاثة، أو قيم أكثر ضمن المدى. بل يمكنه أن يتضمن كلّ القيم. ها هنا مثال عن فئة:


type

Letters = set of Uppercase;

الان يمكنني أت أعرف متغيرا من هذا النوع و أخصص له بعض القيم حسب النوع الأصلي. للإشارة إلى بعض القيم في فئة، تقوم بكتابة سردا مفصول بفاصلة comma-separated، و محصورا بين قوسين مربعين brackets. التوليف التالي يعرض تخصيصات لمتغير: بقيم متعددة، بقيمة واحدة، و بقيمة فارغة:


var

Letters1, Letters2, Letters3: Letters;

begin

Letters1 := ['A', 'B', 'C'];

Letters2 := ['K'];

Letters3 := [];


في دلفي، تستخدم الفئة عموما للإشارة إلى قيم غير حصرية. مثلا، سطرا التوليف التاليان (و هما جزء من مكتبة دلفي) يعرّفان سردا enumeration من الأيقونات المحتملة لإطار نافذة window ثم ما يوافق ذلك من نوع فئة:




type

TBorderIcon = (biSystemMenu, biMinimize, biMaximize, biHelp);

TBorderIcons = set of TBorderIcon;



في الواقع، عند التعامل مع معاين الكائنات Object Inspector ستجد
بعض منها وتميزه بوجود علامة + , ولكي تعرض عناصره تضغط بالماوس على علامة + , فتفتح لك قائة فرعية و تصبح علامة + علامة - ,


سِمة أخرى porperty مبنية على نوع فئة و هي نمط الخط font style. القيم المحتملة تشير لخط داكن bold، مائل italic، تحته خط underline، و خط مقطوع strikethrough. بالطبع نفس الخط قد يكون مائلا و داكنا معا، أو بلا أي نمط، أو أن يملك أنماط الخط كلّها. لهذا السبب تم تعريف نمط الخط كفئة. و يمكنك تخصيص قيم لهذه الفئة في توليف برنامج كالتالي:




Font.Style := []; // no style

Font.Style := [fsBold]; // bold style only

Font.Style := [fsBold, fsItalic]; // two styles

يمكنك اجراء عمليات على الفئة بطرق مختلفة، بما في ذلك جمع متغيرين من نفس نوع الفئة (لنكون أكثر دقّة، حساب اتحاد فئتين):
Font.Style := OldStyle + [fsUnderline]; // two setsأنواع مصفوفة
أنواع مصفوفة Array types تحدد قوائما بعدد ثابت من العناصر من نوع محدد. أنت ستستعمل عادة دليلا index بين قوسين مربعين للوصول إلى أحد عناصر المصفوفة. الأقواس المربعة تستعمل أيضا لتحديد القيم المحتملة لعدد العناصر عند تعريف المصفوفة. مثلا، يمكنك تحديد مجموعة من 24 صحيحا بالتوليف التالي:



type

DayTemperatures = array [1..24] of Integer;

عند تعريف المصفوفة، تحتاج إلى تمرير نوع مدى فرعي subrange بين قوسين مربعين، أو تحديد نوع مدى فرعي جديد خاص باستخدام ثابتين constant من نوع تراتبي. المدى الفرعي هذا يحدد الأدلة indexes المسموح بها في المصفوفة. و حيث انك ستحدد كل من الدليل الأعلى و الدليل الأدنى في المصفوفة، فإن الأدلة لا حاجة لها بأن تبدأ بصفر zero-based، عكس الحال في س، و س++، و جافا، و لغات برمجة أخرى.

و حيث أن أدلة المصفوفة مبنية على مدى فرعي subrange، يمكن لدلفي أن تتفحّص مداها كما رأينا سابقا. فأي ثابت خارج النطاق في مدى فرعي سينتج خطأ عند زمن التجميع؛ كما أن أي دليل خارج النطاق يستخدم في زمن التشغيل ينتج عنه خطأ زمن التشغيل، في حالة تمكين الخيار ذو العلاقة في المجّمع.

باستخدام تعريف المصفوفة أعلاه، يمكنك جعل قيمة المتغير DayTemp1 من نوع DayTemperatures كالتالي



type

DayTemperatures = array [1..24] of Integer;



var

DayTemp1: DayTemperatures;



procedure AssignTemp;

begin

DayTemp1 [1] := 54;

DayTemp1 [2] := 52;

...

DayTemp1 [24] := 66;

DayTemp1 [25] := 67; // compile-time error

قد يكون للمصفوفة أكثر من بعد واحد، كما في المثال التالي:



type

MonthTemps = array [1..24, 1..31] of Integer;

YearTemps = array [1..24, 1..31, Jan..Dec] of Integer;

نوعي المصفوفة بنيا على النوع الأساسي نفسه. يمكنك تعريفهما باستخدام أنواع البيانات السابقة، كما في التوليف التالي:
type

MonthTemps = array [1..31] of DayTemperatures;

YearTemps = array [Jan..Dec] of MonthTemps;هذا التعريف يقلب تريب الأدلّة كما هو أعلاه، لكنّه أيضا يسمح بتخصيص كُتل كاملة فيما بين المتغيرات. مثلا، التعليمة التالية تنسخ درجات حرارة temperatures شهر يناير إلى فبراير:


var

ThisYear: YearTemps;

begin

...

ThisYear[Feb] := ThisYear[Jan];

يمكنك أيضا تعريف مصفوفة تبدأ بصفر zero-based ، نوع مصفوفة حدّها الأدني يساوي صفر. عموما، استخدام حدّين منطقيين أكثر يعدّ ميزة، حيث لا تضطر إلى استخدام الدليل 2 للوصول إلى العنصر 3، و هكذا. إلا أن ويندوز وبصورة ثابتة تستخدم مصفوفات تبدأ بصفر (لأنها مؤسسة على لغة س)، و مكتبة مكونات دلفي تتجه لفعل نفس الشيء.

إذا احتجت إلى الاشتغال على مصفوفة، يمكنك دائما اختبار حدّيها باستخدام الوظيفتين النمطيتين Low و High، و اللتين ترجعان الحدّ الأدنى والحدّ الأعلى. يُنصح بشدّة باستخدام Low و High عند التعامل مع المصفوفة، خاصة في الحلقات loops، ما دامتا تجعلان من التوليف غير محتاج لمعرفة نطاق المصفوفة مقدما. لاحقا يمكنك تغيير النطاق المعرّف لأدلة المصفوفة، و يبقى التوليف الذي يستعمل Low و High بدون تغيير و مستمرا في عمله. أما إذا كتبت حلقة loop مع تحديد صريح لنطاق المصفوفة، فستجد نفسك مضطرا لتحديث التوليف الخاص بالحلقة كلما تغيّر حجم المصفوفة. Low و High تجعلان من توليفك أكثر سهولة عند الصيانة و أكثر اعتمادية.



Record Types

نوع تسجيلة record types تحدّد مجموعة ثابتة من عناصر ذات أنواع مختلفة. كل عنصر، أو حقل field ، له نوعا خاصا به. تعريف نوع تسجيلة تعرض قائمة بكل هذه الحقول، تعطي لكل منها اسما لتستخدمه لاحقا من أجل الوصول إليه.

هنا عرضا بسيطا لتعريف من نوع تسجيلة، ثم تعريف لمتغير من هذا النوع، و بعض التعليمات التي تستخدم هذا المتغيّر:





type

Date = record

Year: Integer;

Month: Byte;

Day: Byte;

end;



var

BirthDay: Date;



begin

BirthDay.Year := 1997;

BirthDay.Month := 2;

BirthDay.Day := 14;

Pointers


نوع مؤشّر pointer يحدّد متغيرا يحوي عنوان متغير آخر في الذاكرة ذو نوع بيانات محدد (أو نوع غير محدد). لذا فإن متغير المؤشر و بطريقة غير مباشرة يشير إلى قيمة. تعريف نوع مؤشّر لا يستلزم كلمة مفتاحية معينة، انه يستعمل حرفا خاصا بدلا من ذلك. الحرف أو الرمز الخاص هو علامة الادراج caret (^):


type

PointerToInt = ^Integer;

حالما عرّفت متغيرا مؤشرا، يمكنك أن تخصص له العنوان الخاص بمتغير آخر من نفس النوع، باستخدام العامل @: [



var

P: ^Integer;

X: Integer;

begin

P := @X;

// change the value in two different ways

X := 10;

P^ := 20;

/CODE]عندما يكون لديك المؤشّر P، فإنه بواسطة التعبير P أنت تشير إلى موقع في الذاكرة يشير إليه المؤشر، و بواسطة التعبير P^ أنت تشير إلى المحتويات الفعلية في موقع الذاكرة هذا. لهذا السبب في التوليف السابق فإن P^ تطابق X .

بدلا من الإشارة إلى موقع ذاكرة موجود، يمكن للمؤشر أن يشير إلى مساحة جديدة في الذاكرة يتم تخصيصها بصورة حيّة (في منطقة من محيط الذاكرة) بواسطة الإجرائية New. في هذه الحالة، و عند إنتهاء حاجتك للمؤشر، عليك أيضا أن تتخلص من الذاكرة التي قمت بحجزها، بإستدعاء الوظيفة Dispose .





var

P: ^Integer;

begin

// initialization

New (P);

// operations

P^ := 20;

ShowMessage (IntToStr (P^));

// termination

Dispose (P);

end;

إذا كان المؤشر خاليا من أية قيمة، يمكنك تخصيص قيمة nil لا شيء له، بعدها تستطيع إختبار خلوّ المؤشر لمعرفة إذا ما هو حاليا يشير إلى قيمة. و هذا يستعمل عادة، لأن التأشير الخاطئ بمؤشر فارغ يسبّب انتهاكا لحرمة الدخول access violation. (أيضا يعرف بخطأ حماية عام general protection fault ، أو GPF) , فكتيرا ما تواجهك رسالة الحطاء

access violation at Address 055544888 in model


في نفس البرنامج يمكن أن تجد مثالا لكيفية الوصول الآمن للبيانات. في هذه الحالة الثانية تمّ تخصيص المؤشر لمتغير محلي موجود، و يمكن استخدامه بأمان، لكني أضفت إليه فحص أمان للتأكيد:


procedure TFormGPF.BtnSafeClick(Sender: TObject);

var

P: ^Integer;

X: Integer;

begin

P := @X;

X := 100;

if P <> nil then

ShowMessage (IntToStr (P^));

end;



تعرّف دلفي أيضا نوع بيانات مؤشر تدلّ على مؤشرات بلانوع untyped (مثل void* في لغة س). إذا استخدمت مؤشرات بلا نوع يجب أن تستخدم GetMem بدلا من New. إجرائية GetMem مطلوبة في كل مرة يكون فيها حجم متغير الذاكرة المطلوب حجزه غير محدد.
.




procedure TFormGPF.BtnGpfClick(Sender: TObject);

var

P: ^Integer;

begin

P := nil;

ShowMessage (IntToStr (P^));

end;

التعليمات البسيطة والمركبة


باسكال تكون بسيطة عندما لا تحتوي على أية تعليمات أخرى. كأمثلة على التعليمات البسيطة نجد تعليمات التخصيص assignment و استدعاءات الاجرائيات procedure calls. التعليمات البسيطة يتم الفصل بينها بفاصلة منقوطة semicolon :

[



X := Y + Z; // assignment

Randomize; // procedure call

/CODE]عادة، تكون التعليمات جزءا من تعليمات مركبة، مؤمرة بعلامات البداية begin و النهاية end. التعليمة المركبة يمكن أن تظهر في مكان تعليمة باسكال عامة. ها هنا مثال:
[CODE]



begin

A := B;

C := A * 2;

end;

الفاصلة المنقوطة بعد اخر تعليمة قبل end ليست ضرورية. مثل التالي:




begin

A := B;

C := A * 2

end;

كلا النسختين صحيحتين. النسخة الأولى لها فاصلة منقوطة غير مجدية (لكنها لاتؤذي). هذه الفاصلة المنقوطة، في الواقع، هي تعليمة فارغة؛ تعليمة بدون توليف code . لا حظ هذا، أحيانا، التعليمات الفارغة يمكن استخدامها داخل الحلقات loops أو في حالات خاصة.


تعليمات التخصيص

التخصيصات assignments في باسكال تستخدم رمزي شارحة يساوي، ترميز غريب بالنسبة للمبرمجين الذين اعتادوا لغات اخرى. الرمز = و الذي يستعمل للتخصيص في بعض اللغات الأخرى، يستعمل في باسكال لاختبار المساواة equality.

التعليمات الشرطية

التعليمة الشرطية conditional statement تستعمل لتنفيذ إحدى التعليمات التي تتضمنها أو عدم تنفيذ و لا واحدة منها. بالاعتماد على شيء من الاختبار. يوجد شكلين من التعليمات الشرطية: تعليمات if و تعليمات case.
تعليمات If
تعليمة if يمكن استخدامها لتنفيذ تعليمة أخرى فقط إذا تحقق شرط معين (if-then)، أو للإختيار بين بديلين (if-then-else). يتم وصف الشرط بتعبير بولي boolean. مثال دلفي بسيط سيوضح كيفية كتابة تعليمات شرطية. أولا قم بإنشاء تطبيق application جديد، ثم ضع على النموذج form خانتي فحص check box و أربعة أزرار buttons . لا تغيّر أسماء الأزرار و خانات الفحص، قم بضغط مزدوج على كل زرّ لإضافة مناول handler للحدث OnClick الخاص بكل زرّ، ها هنا تعليمة if بسيطة للزر الأول:

CODE
procedure TForm1.Button1Click(Sender: TObject);

begin

// simple if statement

if CheckBox1.Checked then

ShowMessage ('CheckBox1 is checked')

end;
عندما تضغط على الزر، إذا كانت خانة الفحص الأول لديها علامة فحص، سيقوم البرنامج بعرض رسالة بسيطة. لقد استعملت وظيفة ShowMessage لأنها أسهل وظيفة في دلفي يمكن استعمالها لإظهار رسالة قصيرة للمستخدم .

إذا ضغطت على الزر و لم يحدث شيء، فهذا معناه أن خانة الفحص غير معلّمة. في مثل هذه الحالة، قد يكون من المستحسن جعل الأمر أكثر صراحة، كما هو في التوليف الخاص بالزرّ الثاني، و الذي يستعمل تعليمة if-then-else.


procedure TForm1.Button2Click(Sender: TObject);

begin

// if-then-else statement



if CheckBox2.Checked then

ShowMessage ('CheckBox2 is checked')

else

ShowMessage ('CheckBox2 is NOT checked');

end;

لاحظ أنه لايمكنك وضع فاصلة منقوطة بعد التعليمة الأولى و قبل مصطلح else، و إلا فإن المحوّل سيصدر خطأ جملة syntax error. إن تعليمة if-then-else في الواقع هي تعليمة واحدة، لذا لا يمكنك وضع فاصلة منقوطة في وسطها.

تعليمة if يمكن لها أن تكون أكثر تعقيدا. فالشرط يمكن تحويله إلى سلسلة من الشروط (باستخدام and و or و not)، أو ان تعليمة if تتفرع عنها تعليمة if أخرى. الزرّين الأخيرين في مثال IfTest يعرضان هاتين الحالتين:



procedure TForm1.Button3Click(Sender: TObject);

begin



// statement with a double condition



if CheckBox1.Checked and CheckBox2.Checked then

ShowMessage ('Both check boxes are checked')

end;





procedure TForm1.Button4Click(Sender: TObject);

begin

// compound if statement

if CheckBox1.Checked then

if CheckBox2.Checked then

ShowMessage ('CheckBox1 and 2 are checked')

else

ShowMessage ('Only CheckBox1 is checked')

else

ShowMessage (

'Checkbox1 is not checked, who cares for Checkbox2?')

end;

أنظر إلى التوليف جيدا و شغل البرنامج لترى ما إذا فهمت كل ما سبق. عندما يكون لديك شك حول بناء برمجي، فإن كتابة برنامج بسيط جدا مثل هذا يمكن أن يساعدك تلتعلم الكثير. بإمكانك اضافة المزيد من خانات التفحص و زيادة تعقيد هذا البرنامج البسيط، و إجراء أي اختبار ترغب به.


الآن لحض الثلات طرق التالية التي تعطي نفس النتيجة , ولكن بطرق مختلفة , افرض أن لديك رقم صحيح و تريد أن تختبر ادا كان أحد تلاث قيم , كالتالي

1-

variable in [21, 24, 29] then

begin

.. do whatever

end;


2-



if variable = 21 then

begin

.. do whatever

end

else if variable = 24 then

begin

.. do whatever

end

else if variable = 29 then

begin

.. do whatever

end;



3




if ((variable = 21) or

(variable = 24) or

(variable = 29)) then

begin

.. do whatever

end;

تعليمات Case

إذا ما أضحت تعليمات if لديك أكثر تعقيدا، يمكنك استبدالها في أية لحظة بتعليمات case. تعليمة case عبارة عن تعبير يستخدم لاختيار قيمة، قائمة بقيم محتملة، أو مدى من القيم. هذه القيم هي ثوابت constants، و يجب أن تكون فريدة ومن نوع تراتبي ordinal. أحيانا، قد يوجد بها تعليمة else و التي يتم تنفيذها إذا لم تتوافق أي من الاحتمالات مع القيمة المعطاة. فيما يلي مثالين بسيطين:





case Number of

1: Text := 'One';

2: Text := 'Two';

3: Text := 'Three';

end;



المتال التاني


case MyChar of

'+' : Text := 'Plus sign';

'-' : Text := 'Minus sign';

'*', '/': Text := 'Multiplication or division';

'0'..'9': Text := 'Number';

'a'..'z': Text := 'Lowercase character';

'A'..'Z': Text := 'Uppercase character';

else

Text := 'Unknown character';

end;

[/mover]ملاحظة:
لا تملك الدلفي تعليمات مثل endif أو endcase. إذا كان لتعليمة if حيز begin-end، فإن نهاية هذا الحيز يحدد نهاية التعليمة. بالمقابل، تعليمة case تنتهي دائما بكلمة end. كل تعليمات end هذه، التي غالبا ما تكون واحدة فوق الأخرى، يمكن أن تجعل من التوليف صعب التتبع. فقط من خلال تتبع الهوامش يمكن معرفة تبعية كل end و لأية تعليمة. الطريقة العامة المتّبعة لحل هذه المشكلة و لجعل التوليف مفهوما أكثر هو في اضافة ملاحظة بعد تعليمة end تشير إلى تبعيتها، كما في:
الحلقات في دلفي

للغة دلفي التعليمات التكرارية النمطية التي لمعظم لغات البرمجة، يتضمن هذا تعليمات for، و while، و repeat .

حلقة For

حلقة for في دلفي مبنية بصورة مقيدة على عداد counter، و الذي يمكن زيادته أو تخفيضه في كل مرة يتم تنفيذ الحلقة. فيما يلي مثال بسيط لحلقة for مستخدمة لإضافة أول عشرة أرقام.
var

K: Integer;

begin

K := 0;

for I := 1 to 10 do

K := K + I;
نفس المثال كان يمكن كتابته باستخدام عداد معكوس:begin

K := 0;

for I := 10 downto 1 do

K := K + I;

حلقة for في دلفي أقل مرونة مقارنة بلغات أخرى (ليس بالإمكان تحديد معدّل زيادة إلا بواحد)، لكنها بسيطة و سهلة الفهم. إذا اردت اختبار شرط بتشعب أكبر، أو أردت ايجاد عداد بمواصفات خاصة، فأنت بحاجة إلى استخدام تعليمات while أو repeat ، عوضا عن حلقة for.



تعليمات While و Repeat

الفرق بين حلقة while-do و حلقة repeat-until هو أن التوليف code داخل تعليمة repeat ينفّذ دائما، مرة واحدة على الأقل. تستطيع بسهولة فهم السبب بالإطّلاع على المثال البسيط:
while (I < 100) and (J < 100) do

begin

// use I and J to compute something...

I := I + 1;

J := J + 1;

end;






repeat

// use I and J to compute something...

I := I + 1;

J := J + 1;

until (I > 100) or (J > 100);

إذا كانت القيمة الإبتدائية في I أو J أكبر من 100، فإن التعليمات داخل حلقة repeat-until سيتم تنفيذها مرة على كل حال.


الفرق الرئيسي الاخر بين هذين الحلقتين هو أن حلقة repeat-until لديها شرط محجوز reserved . الحلقة سيتم تنفيذها حتى اللحظة التي لا يتم فيها تحقيق الشرط. عندما يتحقق الشرط، تتوقف الحلقة. هذا عكس حلقة while-do ، التي تنفذ ما دام الشرط موجبا. لهذا السبب عليّ أن أعكس الشرط في التوليف أعلاه للحصول على تعليمة مشابهة.



مثال عن الحلقات


لإستكشاف تفاصيل الحلقات، دعنا نستعرض مثال دلفي بسيط. برنامج Loops يبرز الفرق بين حلقة بعداد ثابت و حلقة بعدّاد عشوائي تقريبا. إبدأ بمشروع project جديد، ضع مربع قائمة list box و زرّيّن على النموذج form الرئيسي، قم بإعطاء الزرين إسمين مناسبين (BtnFor و BtnWhile) و ذلك بتوصيف سِمة Name فيهما بواسطة معاين الكائنات Object Inspector.


object Form1: TForm1

Caption = 'Loops'

object ListBox1: TListBox ...

object BtnFor: TButton

Caption = '&For'

OnClick = BtnForClick

end

object BtnWhile: TButton

Caption = '&While'

OnClick = BtnWhileClick

end

end



الآن يمكنا اضافة بعض التوليف لحدثي OnClick في الزرين. الزر الأول به حلقة for بسيطة لعرض قائمة من الأرقام، قبل تنفيذ هذه الحلقة، التي تضيف عددا من الجمل إلى سِمة Items في مرّبع القائمة، تحتاج لتصفية محتويات القائمة نفسها Clear.

procedure TForm1.BtnForClick(Sender: TObject);
var
I: Integer;
begin
ListBox1.Items.Clear;
for I := 1 to 20 do
Listbox1.Items.Add ('String ' + IntToStr (I));
end;

التوليف المربوط بالزر الثاني أكثر تعقيدا نوعا ما. ففي هذه الحالة، توجد حلقة while قائمة على عدّاد، يتم زيادته عشوائيا. لإنجاز ذلك، قمت باستدعاء الإجرائية Randomize، والتي تقوم بإعادة تهيئة مولد الرقم العشوائي، و وظيفة Random بنطاق مداه 100. نتيجة هذه الوظيفة هو رقم بين 0 و 99، يتم إختيارها عشوائيا. سلسلة الأرقام العشوائية تتحكم في عدد مرّات تنفيذ حلقة while.

procedure TForm1.BtnWhileClick(Sender: TObject);
var
I: Integer;
begin
ListBox1.Items.Clear;
Randomize;
I := 0;
while I < 1000 do
begin
I := I + Random (100);
Listbox1.Items.Add ('Random Number: ' + IntToStr (I));
end;
end;

كل مرة تضغط على زر while، تختلف الأرقام، لأنها تعتمد على مولد لرقم عشوائي.
لاحظ أنه ليس فقط الأرقام التي تم توليدها مختلفة، بل أيضا عدد العناصر مختلف. حلقة while هذه تُنتج عددا عشوائيا من العناصر. إذا ضغطت على زرّ while عدة مرّات، سوف ترى أن القائمة لديها عدد أسطر مختلف.


ملاحضة
يمكنك تحويل التدفق المعتاد لتنفيذ الحلقة باستخدام اجرائيات النظام Break و Continue. الأول يستخدم لعرقلة الحلقة؛ أما الثاني فيُستخدم للقفز مباشرة إلى اختبار الحلقة أو إلى مزيد العدّاد، بحيث يعيد الاستمرار مع الدورة التالية للحلقة (ما لم يكن الشرط صفرا أو أن العدّاد قد بلغ حدّه الأعلى). أيضا توجد الإجرائيتان Exit و Halt، تسمح لك الأولى بالخروج حالا من الوظيفة أو الإجرائية التي فيها، والثانية تنهي عمل البرنامج.تعليمة With


أخر نوع من تعليمات دلفي سنقوم بالتركيز عليه هي تعليمة with ، و التي تعد مميزة في هذه اللغة البرمجية (و تم إدخالها مؤخّرا في فيجوال بيسك) و مفيدة جدا في البرمجة بدلفي.

تعليمة with ليس إلا اختصار shorthand. عندما تحتاج إلى الاشارة الى متغير نوع تسجيلة record (أو كائن object)، فبدلا من تكرار اسمه في كل مرّة، يمكنك استخدام تعليمة with . مثال ذلك، التوليف التالي:




type

Date = record

Year: Integer;

Month: Byte;

Day: Byte;

end;



var

BirthDay: Date;



begin

BirthDay.Year := 1997;

BirthDay.Month := 2;

BirthDay.Day := 14;



باستعمال تعليمة with، بامكاني تحسين الجزء الأخير من التوليف، كالتالي:




begin

with BirthDay do

begin

Year := 1995;

Month := 2;

Day := 14;

end;




هذا الاسلوب يمكن استخدامه في برامج دلفي للإشارة الى المكونات components و أنواع الطبقات class الأخرى. مثلا، يمكننا إعادة كتابة الجزء الأخير من آخر مثال، مثال Loops، باستخدام تعليمة with لمناولة العناصر items في القائمة:




procedure TForm1.WhileButtonClick(Sender: TObject);

var

I: Integer;

begin

with ListBox1.Items do

begin

Clear; // shortcut

Randomize;

I := 0;

while I < 1000 do

begin

I := I + Random (100);

// shortcut:

Add ('Random Number: ' + IntToStr (I));

end;

end;

end;





عندما تتعامل مع المكونات components أو الطبقات classes في باسكال عموما، تسمح لك تعليمة with بالاستغناءعن كتابة بعض التوليف، خاصة بالنسبة للحقول المتفرعة. مثلا، لنفترض انك تريد تغيير حجم و لون قلم الرسم لنموذج form. يمكنك كتابة التوليف التالي:



Form1.Canvas.Pen.Width := 2;

Form1.Canvas.Pen.Color := clRed;



و لكنه بالتأكيد سيكون الأمر أسهل لو كتبت التوليف التالي:









with Form1.Canvas.Pen do

begin

Width := 2;

Color := clRed;

end;





عندما تقوم بكتابة توليفا متشعبا، يمكن لتعليمة with أن تكون فعالة و تعفيك من تعريف بعض المتغيرات المؤقتة، و لكنها لا تخلو من العيوب. فبامكانها أن تجعل من التوليف أقل مقروئية، خاصة عندما تتعامل مع كائنات مختلفة لكن لديها سمات متشابه أو متطابقة.

يوجد أيضا عيب آخر، و هو ان استعمال تعليمة with قد تسمح بأخطاء منطقية شفافة في التوليف يصعب على المجمع تحسسها. مثال ذلك:




with Button1 do

begin

Width := 200;

Caption := 'New Caption';

Color := clRed;

end;



[CODE]



هذا التوليف يغير من عنوان Caption و عرض With الزر، و لكنه يؤتر في سِمة اللون Color للشكل Form ، و ليس في الزر! سبب هذا أن المكوّن TButton ليس لديه سِمة Color، و حيث أن التوليف يتم تنفيذه داخل كائن form نموذج الذي لديه مثل هذه السِمة فإن الافتراض الأول يتجه له مباشرة. بدلا من ذلك إذا كتبنا:



[CODE]

Button1.Width := 200;

Button1.Caption := 'New Caption';

Button1.Color := clRed; // error!

فإن المجمعCompiler الخاص بدلفي سيصدر خطأ.

يجب أن تتجنب الاستخدام المتعدد لتعليمات with ، مثل:

with ListBox1, Button1 do...

فالتوليف الذي سيتبعه سيكون غالبا غير مقروء و صعب التتبع، لأنه مع كل سِمة يتم تحديدها في هذا الحيّز تحتاج إلى استنتاج و معرفة المكون المقصود الذي تتبعه هذه السِمة، بالاعتماد على السِمات ذات العلاقة و ترتيب المكونات في تعليمة with.

veto_44
12-08-2006, 03:17 PM
اللهم صلي على يسد الخلق سيدنا محمد ما شاء الله عليك اخي احمد
تبارك الرحمن على الموضوع الرائع والمميز ابدعت يا غالي وحلقت
بعيدا بسماء التميز والابداع بالفعل هذه هي ام المفاجئات بارك الله
فيك مشرفنا الغالي كالعادة بارع بتقديم كل جديد وحصري جزاك
الله عنا خيرا ولك خالص التقدير والاحترام

الفرعون المحترف
12-08-2006, 03:38 PM
الف الف شكر اخي محمود مشرفنا الكبير
والله رد تشجيعي ووالله مشكور من كل قلبي
شكرا لك جزاك الله الف خير

Ahmed_ghanam
12-08-2006, 03:57 PM
مشكور مشرفنا الغالى احمد على الدورة تعودنا منك دائما على الابداع مشكور مليون مرة

alae001
12-08-2006, 05:57 PM
ماشاء الله تبارك الله موضوع في غاية الروعة. بارك الله فيك أخي

الفرعون المحترف
12-08-2006, 06:17 PM
مشكورين جزاكم الله الف خير
شكرا لكم بارك الله فيكم

zakimoulayabdellah
12-08-2006, 06:28 PM
الله عليك احمد استااااااااااد

:smailes21: :smailes70: :smailes70: :smailes70: :smailes70: :smailes70:

yougrtin
12-08-2006, 06:37 PM
ماشاء الله روعة
بارك الله فيك أخي احمد....
very very nice

الفرعون المحترف
12-08-2006, 06:53 PM
مشكورين جزاكم الله الف خير

el-zemam
12-08-2006, 06:59 PM
بارك الله فيك أخي

الفرعون المحترف
12-08-2006, 07:36 PM
اهلا بك اخي الحبيب

imadin
12-09-2006, 05:57 AM
مشكور على الدروس المفيدة

^الفجر^
12-09-2006, 02:16 PM
شكرا على الموضوع ..:smailes37:

الفرعون المحترف
12-09-2006, 02:48 PM
اهلا بكي اختي الكريمه

هوي كمبيوتر
12-12-2006, 05:55 AM
مشكور اخي على الموضوع والدورة ولكن اين البرنامج

الفرعون المحترف
12-12-2006, 09:43 AM
البرنامج اخي هداك الله
اذهب لموضوع الاخ المشرف الكبير فيتو في قسم طلبات
وله موضوع مثبت جزاك الله خير
واطلب منه البرنامج وهو بأذن الله لا يتأخر عليك
ولكن امهله فرصه حتى يبحثلك عنه

fouad 23
12-12-2006, 04:52 PM
شكرا على هدا الموضوع الممتاز :smailes35: :smailes35: :smailes35: :smailes91:

الفرعون المحترف
12-12-2006, 04:55 PM
ال الف الف شكرا اخي الحبيب
على الرد الجميل

raja-am
12-19-2006, 12:53 PM
مشكور على الدرس أستاذ وأنا أحضرت البرنامج ونصبته ومنتتظر الدروس

الفرعون المحترف
12-20-2006, 10:56 AM
الدرس اخي في اول صفحه