تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
[سلسلة تعليمية] مقدمة عن الدوال والإجراءات ... نحو تطوير فئات خاصة لقواعد بيانات خاصة
#1
Video 
مقدمة عن الدوال والإجراءات ... نحو تطوير فئات خاصة لقواعد بيانات خاصة.

بلغة فيجوال بيسك دوت نت
Visual Basic .Net

( موضوع خارج الصندوق )


أخوكم / عبدالله خضر عبدالله الهوساوي.
prog909@gmail.com
+2348107596166
واتساب.
.
.
هذه المقدمة والأمثلة فيها تمهيد قوي ومهم للآتي :

- معرفة أهمية الدوال والإجراءات في البرمجة وتطويرها وتحسينها .

- غرس مفهوم قواعد البيانات الشخصية ( الخاصة ) التي لاترتبط مطلقا بقواعد البيانات المعروفة مثل : الأكسيس او الإس كيو إل وغيرها...

- معرفة كيفية تصميم ( فئة أو فئات ) Class من مجموعة دوال وإجراءات لهدف إنشاء قواعد بيانات خاصة من الصفر واجراء جميع التعاملات مع الملفات والسجلات والحقول في وقت وجير ومرونة عالية .

- الخروج من دوامة الاستعلامات في الحصول على بيانات معينة من قاعدة البيانات الخاصة المُدخلة .

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

فأحد أسباب شغفي بالبرمجة بلغة الـ VB.Net هو تصميم الدوال والإجراءات والفئات والكائنات ، وفكرتها الأساسية أنها عبارة عن مجموعة أكواد قصيرة أو طويلة يتكرر إستخدامها في سطور البرنامج ، وبدلا من تكرار كتابتها أو نسخها ، تختصر العملية في إستدعاء كل تلك الأكواد والأوامر بكلمة واحدة ، تطلب منك محددات معينة لعمل المطلوب ..

وفي مستوى متقدم تطبق عليها أسلوب ( البرمجة الكائنية التوجه ) OOP في فئات واضحة مبسطة ( وربما مطولة ) تجعلك في آخر المطاف تصنع بها مكتبات DLL تستخدمها أو يستخدهما غيرك في أعمال برمجية ذات العلاقة ..

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

في هذا الموضوع سأذكر الدوال والإجراءات تباعاً وشرح مبسط عنها وعن أهميتها ونتيجتها ، وأنصح المبرمج بتجميعها وحفظها في ملف ( ميديول ) للإستفادة منها أثناء البرمجة على شكلها الحالي ، وفيما بعد يمكن تجميعها في فئة لتؤلف كائنا يمكن التعامل بها بواسطته ، والله المستعان :

.
.

1 - إجراء حفط نص أو مجموعة نصوص في ملف :

إسمها ( كما سميتها طبعا ) : SaveDocToFile

كود ونص الإجراء :

   Sub SaveDocToFile(ByVal FileNamePath As String, ByVal DocString As String, Optional ByVal IsAppend As Boolean = True)

       Dim A, B As String, C As Boolean

       FileClose()

       A = Trim(FileNamePath) : B = Trim(DocString)
       C = IsAppend

       If A <> "" And B <> "" Then

           Select Case C

               Case True
                   FileOpen(1, A, OpenMode.Append)

               Case False
                   FileOpen(1, A, OpenMode.Output)

           End Select

           PrintLine(1, B)
           FileClose()

       End If

   End Sub

شرح عمل الإجراء :

قد تحتاج في أحد برامجك الجدية أمراً سريعا ومختصراً ومرناً أيضاً لحفظ معلومة أو نص أو مجموعة نصوص ( مهما كان حجمها ) ؛ حفظها في ملف ما في أمر واحد ، فهذا الإجراء صممته لهذا السبب وأضفت له خاصيتين مهمتين أيضاً ، وسآتي لذكرهما لاحقا .

فعند كتابتك إسم الإجراء ، وهو كما سميته أنا : SaveDocToFile ، سيطلب منك أولا كتابة إسم مسار الملف ( سواءا كان موجودا أو لا ) ، هكذا مثلا :

C:\Test.txt

أو بواسطة متغير معرف نصيا مثلا :
S as String
S="C:\Test.txt"

أو إختصاراً :

S as String="C:\Test.txt"


وبعدها سيطلب منك جملة النص أيا كان ( وهو كالسابق متغير نصي ) ، وبعد إثباته يكون الإجراء مستعداً للتنفيذ ..

ستلاحظ وجود خيار إفتراضي ( منطقي ) في الإجراء وهو : Optional ByVal IsAppend As Boolean = True

ومعناه أنه في حال لم يضع المستخدم للإجراء فاصلة بعد جملة النص فسيكون الخيار IsAppend في حالة منطقية إفتراضية دائما هي True أي بمعنى نعم ( حقيقي )
والمقصود بالكلمة IsAppend هو متغير الغرض منه التوضيح للمستخدم كأنه يساله : هل يضاف النص هذا بعد اي نص قد يحتمل وجوده في الملف ؟ .. أي خاصية الإلحاق والإضافة ... فإذا تجاهلته فسيفهم الإجراء أنك تقصد أن يحفظ النص بشكل تراكمي في كل مرة تعطيه نفس المسار للملف ..

أما في حالة أنك تريد أن يكون النص لوحده فقط في الملف بدون إضافة أي نص فما عليك إلا أن تضع فاصلة بعد النص ( أو متغير النص ) ، ثم تكتب False ، أي بمعنى لا ( مزيف ) ...

ستفهم ما أقصده إذا لاحظت خيارات السطور البرمجية في نص الإجراء ...

====================================

2 - دالة السؤال للتأكد  :

إسمها ( كما سميتها طبعا ) : Confirm

كود ونص الدالة :

Function Confirm(ByVal Title As String, ByVal QuestionOfMessage As String, Optional ByVal RightToLeftStyle As Boolean = False) As Boolean

       Dim A, B, Q As String

       Q = ""
       A = Title.Trim + " : "
       B = QuestionOfMessage.Trim

       Dim Stl As MsgBoxStyle, Rs As MsgBoxResult, R As Boolean = False

       Select Case RightToLeftStyle

           Case True
               Stl = MsgBoxStyle.Question + MsgBoxStyle.YesNo + MsgBoxStyle.MsgBoxRight
               Q = "؟"

           Case False
               Stl = MsgBoxStyle.Question + MsgBoxStyle.YesNo
               Q = "?"

       End Select

     
       Rs = MsgBox(B + " " + Q, Stl, A)
   
       If Rs = MsgBoxResult.Yes Then R = True

       Return R

   End Function


شرح عمل الدالة :

بالتأكيد كل برنامج قوي أو ذكي التصميم يخضع لبوابات قبل الوصول للوجهة النهائية ، أقصد بها مثلا قد تٌدخل بيانات ولكن تريد التأكد قبل حفظها أو تعديلها أو حذفها نهائياً ، ولابد أنك كمبرمج تعرف الدالة  MsgBox ، وهي لسؤال مستخدم البرنامج قبل عمل شيء ما كما ذكرت ...

الفكرة هنا في الدالة Confirm هي نفس عمل الدالة MsgBox ، ولكن بشكل أبسط بخصوص اللغتين : عربية أو إنجليزية ، وأنت تعرف الفرق في إتجاه النص ( العربي ) عنه في إتجاه النص ( الإنجليزي ) ، فالأول من اليمين نحو اليسار ، والثاني بالعكس ، وكذلك علامتي الإستفهام ( ؟ أو ? ) .. فهذه الدالة مرنة باللغتين وبدون إضافة علامة الإستفهام ، ومخرجاتها منطقية ( نعم أو لا ) True أو False ..

للدالة ثلاث متغيرات ( بوابات ) :

الأولى :  Title As String
وهي نص ( التعليق ) في مربع رسالة التأكد .

الثانية : QuestionOfMessage As String
وهي نص ( محتوى الرسالة ) في مربع رسالة التأكد .

الثالثة : إفتراضية منطقية : RightToLeftStyle As Boolean = False
وهي إختيارية محددة مسبقا على المنطق ( لا False ) بخصوص إتجاه الكتابة ( من اليمين إلى اليسار = لا ) أي تخص النص الإنجليزي ..
أما في حال أردت العكس ( نص عربي ) فما عليك إلا أن تحدد المنطق ( نعم True ) ليكون مخرجات الدالة باللغة العربية وإتجاه نصها ..

كمثال نضع الكود الآتي في زر Button :

Dim W as Boolean = Confirm ( "للتأكد" , "هل أنت متأكد للخروج نهائيا من البرنامج" , True ) ' Example
If W = True then End

أو

If W then End

فهذه الدالة توفر عليك إختيار وتحديد المعاملات بخصوص السؤال باللغتين ..

========================================

3 - دالة إختيار أحد عناصر حزمة نصية برقم ترتيبها بواسطة فاصلة معينة بين العناصر  :
( وهي أحد مجموعة من الدوال طورتها بلاحقة Item )

إسميتها : ItemSN

كود ونص الدالة :

Function ItemSN(ByVal SN As Integer, ByVal ItemsString As String, ByVal Comma As String) As String

       If Comma = "" Then Comma = " "

       Dim M(), T As String

       T = Trim(ItemsString)

       If T <> "" Then

           M = Split(T, Comma)

           Return M(SN - 1).Trim

       Else

           Return Nothing

       End If

   End Function



شرح عمل الدالة :

هذه الدالة وقريباتها الآتيات من نوع ( Item ) مصممة خصيصا للتعامل مع النصوص والكلمات والجمل أيا كانت ، وعمودها الفقري هي دالة فصل العناصر النصية Split بفاصلة محددة موجودة مسبقا في سلسلة النص ، وهي - كما يعرف المبرمج - تحول العناصر النصية المفصولة إلى مصفوقة أحادية ، تبدأ بالرقم 0 ..

مجموعة دوال وإجراءات النوع ( Item ) التي طورتها كانت نتاج إستفادة قصوى للدالة Split هذه ، حيث سيتبين لك مدى فائدتها الكبيرة في معالجات النصوص وسهولة ومرونة عملياتها في الأمثلة التي ستوضح لك كل شيء عن هذه العائلة البرمجية ..

وظيفة هذه الدالة بسيط ، وكمثال :

الجملة : Welcome to VB.Net World My Dear

أسندناها لمتغير نصي ( حرفي String )

مثلا :

A as String = "Welcome to VB.Net World My Dear" ' Example

وإذا أردت الحصول على الكلمة الثالثة مثلا من النص ، حسنا فكيف العمل - بدون هذه الدالة - ؟؟

لابد من الشرح الآتي لتعرف السبب وراء تطوير هذه الدالة وأخواتها :

1 - طبعا في البداية لزاما عليك أن تعرّف متغير نصي مصفوفي ديناميكي مرن ( على شكل مصفوفة ديناميكية لا محدودة ) ، ليكن مثلا B() as String مع القوسين الفارغين ..

2 - ثم الخطوة الثانية ، إسناد المتغير A و B إلى دالة الفصل Split :

B = Split(A)

في حال كانت الفاصلة فراغ واحد ( مسافة واحدة ) ، أما غير ذلك مثلا الفاصلة بين المقاطع غير الفراغ الواحد فستصبح الصيغة هكذا :

B = Split(A,",")

هنا إخترت نوع الفاصلة ( , )
ويمكنني إختيار أي حزمة أو علامة على أساس أنها فاصلة في المقطع النصي..

3 - ثم نأتي للخطوة الثالثة ، وهي تحديد العنصر المراد أخذه من المقطع الأم :

Dim C as String = B(2)

لماذا 2 وليس 3 ؟؟ ... لأن المصفوفة تبدأ بالرقم صفر ، أي العنصر الأول في الخانة 0 ، والثاني في الخانة 1 ، والثالث في الخانة 2 ... إلخ ...

هنا أكون قد أوضحت لك السبب .. وهو الإختصار والمرونة ، فعندما نعود للمثال السابق :

A as String = "Welcome to VB.Net World My Dear" ' Example

فما علي إلا أن أستدعي الدالة ItemSN بهذه الصيغة وأسند ناتجها إلى متغير حرفي :

Dim Word As String
Word = ItemSN(3,A,"")

فقط ...

أنا هنا أريد الكلمة الثالثة في المقطع A ..
أما الفاصل إذا كان للفراغ فتستطيع كتابته "" أو " " كلاهما سيان .. شيء واحد في الدالة..

هنا ستكون القيمة للمتغير Word = VB.Net ..

الآن ربما فهمت عمل هذه الدالة ، بسيطة ...

وأعذرني لتطويل الشرح !! ، فلقد كان ضروريا ومهما ، لأن ما سيأتي بعدها من أخواتها يكون أساس فهمه من هنا ..

وهذا الشرح ياصديقي يقصد به إلقاء الضوء حول كيفيات وأسباب تصميم الدوال وجدواها ...


=========================================================

4 - دالة تحديد عدد العناصر النصية بواسطة فاصلة معينة بين العناصر  :
( وهي أحد مجموعة من الدوال طورتها بلاحقة Item )

إسميتها : ItemsCount

كود ونص الدالة :

   Function ItemsCount(ByVal ItemsString As String, ByVal Comma As String) As Integer

       Dim M() As String

       If Comma = "" Then Comma = " "

       M = Split(Trim(ItemsString), Comma)

       Return UBound(M) + 1

   End Function



شرح عمل الدالة :

تعطي عدد العناصر النصية في المقطع النصي ، وبواسطة تحديد الفاصل الذي يفصلها .

وفي المثال الآتي :

A as String = "Welcome to VB.Net World My Dear" ' Example

فعدد كلماتها يكون :

Dim C As Integer = ItemsCount( A , "" )

سنكون قيمة C هي العدد 7

ومثال آخر :

A as String = "Pen-Pen and Paper-Ink-Book with pen" ' Example

كم هو عدد العبارات في هذا المقطع ؟ .. الجواب هو :

Dim C  As Integer = ItemsCount( A , "-" )

لاحظ أن العبارات مفصولة بالفاصل ( - )

سنكون قيمة C إذن هي العدد 3 ... أي يوجد في المقطع 3 مقاطع أو عبارات يفصلها الفاصل شرطة ( - )

وستفيدنا هذه الدالة في تحديد حلقة For ... Next في الأمثلة والشروحات القادمة ..

ملاحظة :
هذه الدالة وقريباتها الآتيات من نوع ( Item ) مصممة خصيصا للتعامل مع النصوص والكلمات والجمل أيا كانت ، وعمودها الفقري هي دالة فصل العناصر النصية Split بفاصلة محددة موجودة مسبقا في سلسلة النص ، وهي - كما يعرف المبرمج - تحول العناصر النصية المفصولة إلى مصفوقة أحادية ، تبدأ بالرقم 0 ..


=========================================================

5 - دالة إختيار عدد من مجموعة أعداد محزومة على شكل متغير نصي بواسطة فاصلة معينة بين العناصر  :
( وهي أحد مجموعة من الدوال طورتها بلاحقة Item )

إسميتها : ItemSNval

كود ونص الدالة :

   Function ItemSNval(ByVal SN As Integer, ByVal ItemsString As String, ByVal Comma As String) As Integer

       If Comma = "" Then Comma = " "

       Dim M(), T As String, U As Integer

       U = Val(SN) : T = Trim(ItemsString) : M = Split(T, Comma)

       Return Val(M(U - 1))

   End Function

شرح عمل الدالة :

تخيل وجود سلسة اعداد على شكل حزمة نصية String يفصلها فاصل معين ...

فأريد إختيار عدد منها ولكن الناتج بصيغة عددية ..

الجواب بسيط :

هو إضافة ( دالة القيمة العددية Val ) في كود ناتج الدالة السابقة ItemSN .. إذن نحن إستنسخنا منها أخت لها وسميناها ItemSNval .. هذا كل مافي الأمر !!

وفي المثال الآتي سلسلة أعداد في حزمة نصية :

E As String = "3 54 98 120 6 777" ' Example

وأريد العدد الرابع من الحزمة المفصولة بفراغ واحد ، سيكون الجواب هو :

Dim N as Inetger = ItemSNval(4, E , "" )

والناتج طبعا بصيغة عددية وليست نصية ...

================================

6 - دالة تحديد عدد عناصر الليست بوكس ListBox

إسميتها : ListBoxCount

كود ونص الدالة :

 Function ListBoxCount(ByVal ListBoxName As ListBox) As Integer

       ListBoxName.Refresh()
       Return ListBoxName.Items.Count

   End Function

سبب إنشاء الدالة :
غالبا ماتحتاج إنعاش صندوق الليست بالأمر Refresh ، وبعدها تحصيل عدد عناصر الليست ..

يعني خطوتين تتكرر كل مرة إذا أردت معرفة عدد العناصر الموجودة في الليست - ياللملل -
فللإختصار نجعلها دالة ونستدعيها بإسم الدالة ونكتب إسم الليست فقط ...

===============================

7 - دالة إقتطاع إسم الملف فقط من نص مساره الكامل

إسميتها : FileNameOfPathFile

كود ونص الدالة :

Function FileNameOfPathFile(ByVal FilePath As String, Optional ByVal WithExtension As Boolean = True) As String

       Dim C As Integer, K, K2 As String

       Dim Cm As String = "\", P As String = FilePath.Trim

       C = ItemsCount(P, Cm)
       K = ItemSN(C, P, Cm) : K2 = K

       If WithExtension = False Then

           If InStr(1, K, ".") <> 0 Then

               K2 = ItemSN(1, K, ".")

           End If

       End If

       Return K2

   End Function

شرح عمل الإجراء :

في حال أردت إظهار إسم الملف فقط بدون نص مساره كله . كمثال إسم المسار الكامل للملف يكون :
C:\Test Folder\test.txt

أما إسم الملف فقط ، فسيظهر : test.txt
مع إمتداده txt

أما في حال غيرت الإختيار الإفتراضي WithExtension ليصبح False ، فسيظهر إسم الملف فقط بدون إمتداده ..

ستلاحظ أن عمليات هذه الدالة تعتمد كليا على دوال المجموعة ( Item ) التي ذكرتها سابقا ، وهذا هو مفهوم ( التكامل الوظيفي ) بين الدوال.

=================================================


8 - إجراء نسخ أسماء جميع الملفات الموجود في مجلد محدد إلى صندوق اللائحة ( الليست بوكس ) ListBox

إسميتها : CopyFilesNameInDirToListBox

كود ونص الإجراء  :

   Sub CopyFilesNameInDirToListBox(ByVal DirName As String, ByVal ListBoxName As ListBox, _
                                   Optional ByVal WithExtension As Boolean = False, _
                                   Optional ByVal LabelNameForViewCountOfItems As Label = Nothing)

       Dim Nm, FN As String, Lbl As Label = LabelNameForViewCountOfItems

       Dim FLs As System.Collections.ObjectModel.ReadOnlyCollection(Of String) = _
       My.Computer.FileSystem.GetFiles(DirName.Trim)


       ListBoxName.Items.Clear()

       For Each Nm In FLs

           FN = FileNameOfPathFile(Nm, WithExtension)

           ListBoxName.Items.Add(FN)

       Next

       If Lbl IsNot Nothing Then

           Lbl.Text = ListBoxCount(ListBoxName)

       End If

   End Sub


شرح عمل الإجراء :

في أحد برامجك الجدية أردت قائمة أسماء الملفات الموجودة في مجلد ما ، قد يكون ذلك للإستطلاع أو تعديل أسماء منها أو حذف أو نقل أو فتح المحتوى أو أو ...

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

وذلك يكون عبر المدخلات المطلوبة ( الباراميترات ) الآتية مع وجود إختيارات مهمة مرنة :

DirName As String
متغير نصي : يطلب منك مسار المجلد المطلوب ، إلزامي .

ListBoxName As ListBox
إسم الليست المطلوب نسخ أسماء الملفات إليه ، إلزامي .
                                 
Optional  WithExtension As Boolean = False
متغير منطقي إختياري ( ليس إلزاميا ) ، محدد إفتراضيا بالقيمة المنطقية False أي لا .
وهو بمعنى : هل تريد عرض أسماء الملفات مع إسم إمتدادها ؟

Optional  LabelNameForViewCountOfItems As Label = Nothing
متغير إختياري ( ليس إلزاميا ) لتحديد إسم الليبل Label الذي سيطبع عليه عدد عناصر الليست ( عدد أسماء الملفات في المجلد المحدد ) ، محدد إفتراضيا بالقيمة Nothing أي أنه غير موجود في حال لم تكتب إسم الليبل ، أما إذا كتبت إسم ليبيل موجود في البرنامج لهذا الغرض ستصبح قيمة الباراميتر تلقائيا = IsNot Nothing ، أي عكس ( غير موجود ) ، يعني ( موجود )

ملاحظة :
ستلاحظ وجود دالة سابقة وهي ListBoxCount في هذا الإجراء ..
هذا معناه وجود ( تكامل وظيفي تلقائي ) بين الدوال والإجراءات المختلفة يهدف للفاعلية الإنتاجية في إختصار الوقت والجهد ، ولكن بشرط وجودها في ملف أو ملفات ميديول Module في برنامج واحد ..
لهذا السبب أوصي بتجميع دوال هذا الموضوع في ملف ميديول واحد ..

=================

(( ملاحظة مهمة جدا جدا جدا ))

أرجو من أي أحد أن لايكرر علي موضوع السهولة أو المقارنة بخصوص قواعد البيانات المتعارف عليها والشائعة جدا ..
ببساطة هو أني مللت منها .. وبعضها يسبب لي عقد نفسية برمجية ! .. وبعضها يقيد إبداعي كمبرمج ويفرض علي مستوى معين من الأدوات والتحميلات والتوافقات بين نسخ الأنظمة وإطارات العمل وووووووووو...
( دوامة لاتنتهي )

وليست مشكلة كبيرة مني أني حِدت عن المسار العام أو سلكت طريقا آخر يشعرني أنني مبرمِج ( بكسر الميم ) ولست مبرمَج ( بفتح الميم )...

=======

سأكمل ما بدأته ولن تهمني الإنتقادات ...

فقط أنا مؤمن أني سأفيد غيري يوما حتى وان إختلف أسلوبي أو لهجة كلامي في شرحي...
الرد }}}
تم الشكر بواسطة: asemshahen5 , سعود , ابو روضة


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
  [كود] نسخ بيانات جدول من ملف اكسس الى جدول في ملف اكسس مستقل justforit 0 343 22-11-23, 08:22 PM
آخر رد: justforit
  بعض الاكواد المفيدة في التعامل مع قاعدة بيانات اكسس ابو ليلى 3 9,484 15-10-22, 12:16 AM
آخر رد: kebboud
  [SQL] [ليس جديد]جملة استعلام جلب بيانات صف ما قبل الاخير سعود 0 1,243 27-05-22, 03:22 AM
آخر رد: سعود
  كود إضافة صورة في قاعدة بيانات أكسيس saffor 6 10,182 26-04-20, 11:08 PM
آخر رد: شوشه
  ابحث عن كود vb2008 للتنقل بين جداول قاعدة بيانات اكسس gharib 3 3,016 19-05-17, 11:50 PM
آخر رد: alma2
  طلب كود الاتصال بقاعدة بيانات موجودة في جهاز اخر thevirus 9 5,460 17-04-17, 02:45 AM
آخر رد: ABDSH
  طلب كود لظافة الصورة في قاعدة بيانات اكسس a.baomar 3 2,529 11-04-17, 10:37 PM
آخر رد: abdualla
  [VB.NET] قاعد بيانات اكسس mohamed fayez2017 1 1,980 31-03-17, 06:39 AM
آخر رد: حريف برمجة
  تحدي في ربط الفيجوال استوديو 2012 مع قاعدة بيانات اكسيس bassamreg 2 3,500 07-07-16, 12:47 AM
آخر رد: أبوبكر سويدان
  مساعدة ، كيف يمكن نقل بيانات من الداتاكريد الى اخرى بشروط معينة رعد الغبان 0 2,232 20-01-16, 09:17 AM
آخر رد: رعد الغبان

التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم