الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

دروس في البرمجه بلغة C#2005, تعلم خطوة بخطوة , مع الإجابة عن أي سؤال

مغلقرائج
بدأه حماة النهضة في 19 أبريل 2007 · 208 رد · 80,594 مشاهدة · في Microsoft Visual C#.NET
مشاركة: واتساب X فيسبوك تيليجرام
#51

لما اعرف ملف الاوديو في الصفحه الرابعه من الدرس ..

يطلع لي هالخطا لما اسوي فتح ملف ..

LoaderLock was detected

Message: DLL 'C:\Documents and Settings\Xp\My Documents\Visual Studio Codename Orcas\Projects\myVidio\myVidio\bin\Debug\Microsoft.DirectX.AudioVideoPlayback.dll' is attempting managed execution inside OS Loader lock. Do not attempt to run managed code inside a DllMain or image initialization function since doing so can cause the application to hang.

رحت لم الريجستري على الـ MDA لما رحت وقريت في موقع مايكروسوفت وشغلت الـ MDA زحطيت قيمتها بالريجستري واجدد زي ماقال ..

بس نفس المشكله ماتغير ..

مع اني استخدمه فيجوال ستديو اوسكار بيتا :)

#52

السلام عليكم

StUd_C

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

يطلع لي هالخطا لما اسوي فتح ملف ..

LoaderLock was detected

Message: DLL 'C:\Documents and Settings\Xp\My Documents\Visual Studio Codename Orcas\Projects\myVidio\myVidio\bin\Debug\Microsoft.DirectX.AudioVideoPlayback.dll' is attempting managed execution inside OS Loader lock. Do not attempt to run managed code inside a DllMain or image initialization function since doing so can cause the application to hang.

رحت لم الريجستري على الـ MDA لما رحت وقريت في موقع مايكروسوفت وشغلت الـ MDA زحطيت قيمتها بالريجستري واجدد زي ماقال ..

بس نفس المشكله ماتغير ..

مع اني استخدمه فيجوال ستديو اوسكار بيتا

هذا ليس خطأ , وإنما هو تحذير فقط , ولإزالته إذهب إلى قائمة Debug ثم Exceptions

debugexeption.JPG

ثم من النافذة الناتجة إختر :

Managed Debuggting Assistants

,وإبحث عن Loader Lock وقم بإزالة الإشارة من مربع الخيار أمامها ثم إختر OK

loaderlock.JPG

..

7oma

حماة النهضة

إعذرونا , سنضطر للغياب فترة كبيرة

الأمر ليس بيدنا ...... فسامحونا

#53

هلا اخي حماة النهضه ..

انا من مالتاعبني للدروس صح اني لا اضع مشاركاتي ولكن ان وجدت خطا استفسرت عنه فقط وبالنهايه مع اكتمال الشروح وانتهائي من العمل كاملا وضعته ..

لي نقطه مافهمتها اول شي هي يوم جينا نعرف الكائن

private Audio apAudio;
private Video apVideo;

لم نستخدم new

مع ان الكائنات على حسب مافهمت يجب تحميلها هكذا مثل الريل بلاير سوينا

private AxRealAudioObjects.AxRealAudio rpReal = new AxRealAudioObjects.AxRealAudio();

وش الفرق بينهم مع انهم كلهم كائنات (كلاس )

اما سؤالي الثاني وهو اني وصلت للدرس السابع وطبقته وشغلت الملف

وضبطت كل شي وكل شي تمام لما اشغل

ملف حقات الدايركت اكس يشتغل تمام والمقت والتسك بار يشتغل زين لكن لما اشغل ريل بلاير يطلع لي خطا ..

وهو يقول ان الفاليو يجب ان لاتكون اكبر من المكسيموم ولا اقل من المنيموم وهذا شي اكيد مع اني مطبق نفس الكود نصا ..

وهذا مسج الرساله

System.ArgumentOutOfRangeException was unhandled

Message="Value of '306' is not valid for 'Value'. 'Value' should be between 'Minimum' and 'Maximum'.\r\nParameter name: Value"

Source="System.Windows.Forms"

ParamName="Value"

StackTrace:

at System.Windows.Forms.TrackBar.set_Value(Int32 value)

at myVidio.MainForm.timer1_Tick(Object sender, EventArgs e) in C:\Documents and Settings\Xp\My Documents\Visual Studio Codename Orcas\Projects\myVidio\myVidio\MainForm.cs:line 206

at System.Windows.Forms.Timer.OnTick(EventArgs e)

at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)

at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)

at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)

at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)

at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)

at System.Windows.Forms.Application.Run(Form mainForm)

at myVidio.Program.Main() in C:\Documents and Settings\Xp\My Documents\Visual Studio Codename Orcas\Projects\myVidio\myVidio\Program.cs:line 21

at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)

at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)

at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()

at System.Threading.ThreadHelper.ThreadStart_Context(Object state)

at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)

at System.Threading.ThreadHelper.ThreadStart()

InnerException:

ومؤشر هو على السطر هذا

taimTrackBar.Value = Convert.ToInt32(rpReal.GetPosition());

Value of '306' is not valid for 'Value'. 'Value' should be between 'Minimum' and 'Maximum'.

Parameter name: Value

مادري ايش المشكله

#54

وعليكم السلام

Ben_Laiid

لا إعتذار أخي ^^

وفقك الله لما يحب ويرضى

StUd_C

اقتباس
انا من مالتاعبني للدروس صح اني لا اضع مشاركاتي ولكن ان وجدت خطا استفسرت عنه فقط وبالنهايه مع اكتمال الشروح وانتهائي من العمل كاملا وضعته ..

لي نقطه مافهمتها اول شي هي يوم جينا نعرف الكائن

كود:

private Audio apAudio;

private Video apVideo;

لم نستخدم new

مع ان الكائنات على حسب مافهمت يجب تحميلها هكذا مثل الريل بلاير سوينا

كود:

private AxRealAudioObjects.AxRealAudio rpReal = new AxRealAudioObjects.AxRealAudio();

وش الفرق بينهم مع انهم كلهم كائنات (كلاس )

اما سؤالي الثاني وهو اني وصلت للدرس السابع وطبقته وشغلت الملف

أولاً يجب ان أشرح ما فائدة الكلمة new

عند تعريف أي كائن كما عرفنا كائن الصوت مثلاً :

private Audio apAudio;

فمعنى هذا أن المتغير apAudio هو كائن من نوع مشغل صوت

ولكن لو جربنا إستخدام الكائن بعد تعريفه بهذه الطريقه :

apAudio.Play();

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

وتعليمة التعريف السابقة كأنها تحدد وعاء او قالب للكائن ولكن هذا الوعاء فارغ

وبالتالي لا يستطيع القيام بأي من وظائفة , ولملئ الوعاء يجب إستخدام الكلمة new حتى يتم إنشاء كائن جديد ووضعه في الوعاء

ويمكن أيضاً ملئ الوعاء بطرق أخرى غير إستخدام كلمة new مثلاً :


Audio a2;
a2=a1;
a2.Play();
   ِAudio a1=new Audio();

في الكود السابق كائنين من نوع مشغل الصوت , الأول عرفناه مع كلمة new والثاني بدونها

لاحظ أننا لم نستخدم الكائن a2 إلا بعد ان ملأنا مكانه بواسطة التعليمة :

a2=a1;

وبالتالي فلن يحدث أي خطأ إذا حاولنا إستخدام الكائن a2 بعد تعليمة الملئ "المساواه"

في البرنامج إستخدمنا نفس الطريقة , عرفنا متغيرات الصوت والفيديو بدون إستخدام new

ثم قمنا بملئ مكانهما من خلال تعليمة مساواه داخل البرنامج قبل أن نستخدم أي منهما :

ap = Audio.FromFile(OF.FileName);

المساواه هنا تعني ملئ مكان الكائن

كان من الممكن أن نعرفهما كما عرفنا كائن الريل , ولكن السبب أنه في مشغلات الصوت والفيديو

يتم تحميل الملف للكائن من خلال إنتاج كائن جديد يحمل الملف المطلوب من خلال التعليمة :

Audio.FromFile(OF.FileName);

وبالتالي لا داعي لأن نملاً مكان الكائن بإستخدام new ثم نملأه من جديد بإستخدام التعليمة السابقة

اقتباس
اما سؤالي الثاني وهو اني وصلت للدرس السابع وطبقته وشغلت الملف

وضبطت كل شي وكل شي تمام لما اشغل

ملف حقات الدايركت اكس يشتغل تمام والمقت والتسك بار يشتغل زين لكن لما اشغل ريل بلاير يطلع لي خطا ..

وهو يقول ان الفاليو يجب ان لاتكون اكبر من المكسيموم ولا اقل من المنيموم وهذا شي اكيد مع اني مطبق نفس الكود نصا ..

وهذا مسج الرساله

تأكد من إجراء SetTrackBar يجب أن يكون هكذا :


{
if (type=="V")
{
trackBar1.Maximum=Convert.ToInt32(vp.Duration);
}
else if (type=="A")
{
trackBar1.Maximum=Convert.ToInt32(ap.Duration);
}
else if (type=="R")
{
trackBar1.Maximum=Convert.ToInt32(rp.GetLength());
}
}
void SetTrackBar()

وتأكد أيضاً أنك تستدعي الإجراء قبل تشغيل الملف :


LoadFile(OF.FileName);
SetTrackBar();
PlayFile();
OF.ShowDialog();

موفق إن شاء الله

..

7oma

حماة النهضة

إعذرونا , سنضطر للغياب فترة كبيرة

الأمر ليس بيدنا ...... فسامحونا

#55

اشكرك على ردك مع اني اريد التعليق ولكن الوقت متاخر وشوي دايخ ..

فسؤالي الاول راح اعلق عليه الرد الجاي ..

لكن الكود اللي تقول لي تاكد منه هذا هو

private void SetTrackBar()
		{
			if (type == "V")
			{
				taimTrackBar.Maximum = Convert.ToInt32(apVideo.Duration);


			}
			else if (type == "A")
			{
				taimTrackBar.Maximum = Convert.ToInt32(apAudio.Duration);
			}
			else if (type == "R")
			{
				taimTrackBar.Maximum = Convert.ToInt32(rpReal.GetLength());

			}

		}

وللمعلوميه ترى لا شغلت ملف فديو يشتغل طبيعي وكل شي طبيعي ولا شغلت ملف امتداد ويف يشتغل طبيعي وحتى التايمنج طبيعي المشكله ماتصير الا مع ملفات الريل بلاير فقط ..

وهذا الاستدعاء قبل تشغيل الملف

private void openFileButton_Click(object sender, EventArgs e)
		{
			ofOpenFileDialog.ShowDialog();
			LoadFile(ofOpenFileDialog.FileName);
			SetTrackBar();
			PlayFile();


		}

وهذا الكود كامل

namespace myVidio
{
	public partial class MainForm : Form
	{

		private Audio apAudio;
		private Video apVideo;
		private AxRealAudioObjects.AxRealAudio rpReal = new AxRealAudioObjects.AxRealAudio();
		private string type;



		public MainForm()
		{


			InitializeComponent();
		}

		private void openFileButton_Click(object sender, EventArgs e)
		{
			ofOpenFileDialog.ShowDialog();
			LoadFile(ofOpenFileDialog.FileName);
			SetTrackBar();
			PlayFile();


		}

		private void runFileButton_Click(object sender, EventArgs e)
		{
			PlayFile();
		}

		private void bigScreenButton_Click(object sender, EventArgs e)
		{
			apVideo.Fullscreen = true;

		}

		private void MainForm_KeyPress(object sender, KeyPressEventArgs e)
		{
			apVideo.Fullscreen = false;
		}

		void LoadFile(string path)
		{
			StopFile();
			apVideo = null;
			apAudio = null;
			this.Controls.Add(rpReal);
			rpReal.Visible = false;
			try
			{
				apVideo = Video.FromFile(ofOpenFileDialog.FileName);
				apVideo.Owner = showPanel;
				showPanel.Width = 400;
				showPanel.Height = 300;
				type = "V";
			}
			catch
			{
				try
				{
					apAudio = Audio.FromFile(path);
					type = "A";
				}
				catch
				{
					try
					{
						rpReal.SetSource(path);
						type = "R";
					}
					catch
					{
						MessageBox.Show("الرجاء الملف غير صالح ");
					}

				}
			}
		}

		void PlayFile()
		{
			if (type == "V")
			{
				apVideo.Play();
			}
			else if (type == "A")
			{
				apAudio.Play();
			}
			else if (type == "R")
			{
				rpReal.DoPlay();

			}
		}
		void PauseFile()
		{
			if (type == "V")
			{
				apVideo.Pause();
			}
			else if (type == "A")
			{
				apAudio.Pause();
			}
			else if (type == "R")
			{
				rpReal.DoPause();

			}
		}
		void StopFile()
		{
			if (type == "V")
			{
				apVideo.Stop();
			}
			else if (type == "A")
			{
				apAudio.Stop();
			}
			else if (type == "R")
			{
				rpReal.DoStop();

			}
		}

		private void stopButton_Click(object sender, EventArgs e)
		{
			StopFile();
		}

		private void stopErButton_Click(object sender, EventArgs e)
		{
			PauseFile();

		}

		private void SetTrackBar()
		{
			if (type == "V")
			{
				taimTrackBar.Maximum = Convert.ToInt32(apVideo.Duration);


			}
			else if (type == "A")
			{
				taimTrackBar.Maximum = Convert.ToInt32(apAudio.Duration);
			}
			else if (type == "R")
			{
				taimTrackBar.Maximum = Convert.ToInt32(rpReal.GetLength());

			}

		}

		private void taimTrackBar_Scroll(object sender, EventArgs e)
		{
			if (type == "V")
			{
				apVideo.CurrentPosition = taimTrackBar.Value;
			}
			else if (type == "A")
			{
				apAudio.CurrentPosition = taimTrackBar.Value;
			}
			else if (type == "R")
			{
				rpReal.SetPosition(taimTrackBar.Value );

			}
		}

		private void timer1_Tick(object sender, EventArgs e)
		{
			if (type == "V")
			{
				taimTrackBar.Value =  Convert.ToInt32(apVideo.CurrentPosition);
			}
			else if (type == "A")
			{
				taimTrackBar.Value =  Convert.ToInt32(apAudio.CurrentPosition);
			}
			else if (type == "R")
			{
				taimTrackBar.Value = Convert.ToInt32(rpReal.GetPosition());

			}

		}


	}
}
#56

السلام عليكم

StUd_C

على الأغلب رقم إصدار البيئة هو السبب

عموماً الحل بسيط , أضف هذا الشرط قبل السطر الذي يظهر فيه الخطأ :

				if(Convert.ToInt32(rpReal.GetPosition())<taimTrackBar.Maximum)

..

7oma

حماة النهضة

إعذرونا , سنضطر للغياب فترة كبيرة

الأمر ليس بيدنا ...... فسامحونا

#57

الدرس العاشر

المتغيرات العامة public

إلى الآن ما زال برنامجنا يحتوي على نافذة واحدة فقط , لذلك لم نجد الفرصة لإستخدام المتغرات العامة

في درس اليوم سنقوم بإضافة نافذة جديدة إلى البرنامج لإدارة الألبومات "قوائم التشغيل"

حيث سنحتاج للوصول إلى متغيرات النافذة الأساسية من نافذة الالبومات

المتغير الأساسي الذي سنحتاج للوصول إليه من نافذة الالبومات هو قائمة التشغيل albume

حيث يجب تمريرها إلى نافذة الألبومات حتى يتم إجراء التعديلات عليها

وهنا يجب إستخدام كلمة public قبل تعريف albume حتى تستطيع النافذة الأخرى التعرف عليها كما سنرى في التطبيق

التطبيق:

إفتح تطبيق الدرس السابق وإذهب إلى نافذة Project وأنقر بزر الفارة الأيمن على إسم البرنامج MyMediaPlayer

ومن القائمة إختر Add ثم New Item

image10-1.jpg

ستظهر لك القائمة التالية :

image10-2.jpg

إختر C# ثم Windows Application ثم Form وأكتب في حقل إسم الفورم albumes.cs

ثم انقر على زر Create لكي يتم إنشاء نافذة جديدة في المشروع

يتم التنقل عبر نوافذ البرنامج من خلال النقر المزدوج على ملف النافذة في نافذة Projects

image10-3.jpg

أنتقل إلى تصميم النافذة الجديدة , ومن صندوق الأدوات قم بسحب كائن المستعرض List View إلى النافذة الجديدة

image10-4.jpg

قم بإختيار كائن المستعرض وإذهب إلى جدول الخصائص

غير الخاصية (Name) إلى lv

وغير الخاصية View إلى Details

إذهب إلى خاصية Columns وأنقر على زر التفاصيل :

image10-5.jpg

ستظهر نافذة التفاصيل فارغة

هذه هي النافذة التي يتم من خلالها إنشاء أعمده لكائن المستعرض

image10-6.jpg

حيث سنكون عمودين , عمود لإسم الملف فقط , وعمود آخر لمسار الملف كاملاً

أنقر على زر Add وغير خاصية Text إلى "إسم الملف"

ونقر مرة أخرى على زر Add لتنشئ العمود الثاني وغير خاصية Text فيه إلى "مسار الملف"

ثم انقر على زر الموافقة سيتكون في كائن المستعرض عمودين :

image10-7.jpg

من صندوق الأدوات إسحب أربعة أزرار إلى يمين كائن المستعرض , وغير خاصية Text إلى

إضافة

إلى الأعلى

إلى الأسفل

حذف

إسحب زرين آخرين من صندوق الأدوات إلى أسفل كائن المستعرض وغير خاصية Text إلى

موافق

إلغاء الأمر

بحيث يصبح شكل النافذة هكذا :

image10-8.jpg

إختر زر "موافق" وإذهب إلى جدول الخصائص وغير الخاصية DialogResult إلى OK

معنى هذا أنه عند النقر على هذا الزر فإن نتيجة النا فذة هي الموافق كما سنشرح لاحقاً

ثم إختر زر "إلغاء الأمر" وغير خاصية DialogResult إلى Cancel

وهذا يعني أنه عند النقر على هذا الزر فإن نتيجة النافذة هي إلغاء الأمر

من صندوق الأدوات إسحب كائن فتح الملفات و إختره وغير خاصية (Name) إلى OF

وغير خاصية MultiSelect إلى true

إنتقل إلى شفرة النافذة , نحتاج لتعريف متغير من نوع قائمة شبيهه بقائمة albume في النافذة الرئيسية

حتى يتم من خلالها التعامل مع الملف وإضافتها إلى كائن المتصفح و حذفها منه

وكما شرحنا سابقاً فإن كائن القائمة موجود في فضاء الأسماء System.Collections.Generic لذلك يجب إضافة عبارة using لتضمين كائنات ودوال الفضاء

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

 using System.Collections.Generic;

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

public List<string> albume=new List<string>();

image10-9.jpg

لاحظ أنا إستخدمنا الكلمة public وليس private وذلك حتى تتمكن النافذة الرئيسية من رؤية هذا المتغير كما سنرى لاحقاً

القائمة albume في نافذة الألبومات ستكون نسخة مطابقة للقائمة albume في النافذة الرئيسية

ويتم التعامل مع كائن المستعرض من خلال عناصر هذه القائمة .

إضافة ملفات

إنتقل إلى تصميم نافذة الالبومات وأنقر مزدوجا على زر "إضافة" للذهاب إلى شفرته

أكتب الكود التالي بين الحاصرتين :

			OF.ShowDialog();
			 albume.AddRange(OF.FileNames);
			 FillView();

يقوم هذا الكود بفتح نافذة إختيار الملفات ثم إضافة الملفات المختارة إلى القائمة albume

في السطر الثالث نستدعي إجراء إضافة الملفات إلى كائن المستعرض

الإجراء FillView

يقوم هذا الإجراء بنسخ جميع عناصر القائمة albume إلى كائن المستعرض lv

إنسخ الإجراء التالي إلى شفرة نافذة الالبومات وتأكد من أنه خارج إلى إجراء أخر :

		void FillView()
		 {
			 lv.Items.Clear();
			 for (int i = 0; i < albume.Count; i++)
			 {
				 string filename=System.IO.Path.GetFileName(albume);
				 ListViewItem file = new ListViewItem(filename);
				 file.SubItems.Add(albume);
				 lv.Items.Add(file);
			 }
		 }

فس السطر الثالث قمنا قمنا بإستدعاء دالة تنظيف كائن المستعرض lv.Items.Clear

حيث تقوم هذه الدالة بتنظيف كائن المستعرض من أي عناصر موجوده مسبقاً حتى يتم إضافة العناصر الجديدة

في السطر الرابع دوارة for من الصفر وحتى عدد عناصر القائمة albume التي تحمل مسارات الملفات المختارة

في السطر السادس قمنا بتعريف متغير من نوع نص يحمل ناتج دالة GetFileName والتي ترجع إسم الملف من المسار الموجود في قائمة albume في الترتيب i

في السطر السابع عرفنا كائن جديد إسمه file من نوع ListViewItem

حيث ان كائن المستعرض lv هو عبارة عن مجموعة كائنات ListViewItem حيث يمثل كل كائن منها سطر واحد من سطور كائن المستعرض

ولأن ListViewItem كائن وليس متغير فقد إستخدمنا الجملة new ومررنا له إسم الملف الناتج من السطر السابق

حيث أصبح المتغير يحمل قيمة filename من السطر السابق

وفي السطر الثامن , أضفنا كائن فرعي للكائن file من خلال الدالة file.SubItems.Add

ومررنا لها العنصر الذي ترتيبه i من قائمة albume

الآن المتغير file أصبح يحمل قيمتين الأولى هي إسم الملف والثانية الفرعية هي مسارة المخزن في قائمة albume

في السطر التاسع أضفنا الكائن file إلى lv حيث يعتبر سطر واحد من سطور كائن المستعرض lv

وبعد تكرار هذه العملية لكافة عناصر القائمة albume يصبح الكائن lv محتوياً على جدول يوضح جميع أسماء ومسارات الملفات المختارة

حذف ملف

إذهب إلى تصميم نافذة الألبومات وأنقر مزدوجاً على زر "حذف" لتنتقل إلى شفرته

أكتب الكود التالي بين الحاصرتين :

			albume.RemoveAt(lv.SelectedIndices[0]);
			 FillView();

الدالة RemoveAt تقوم بأخذ ترتيب العنصر كمدخل وتحذفة من القائمة

فمثلاً لو أردنا حذف العنصر الذي ترتيبة 4 سيكون الكود كالتالي :

albume.RemoveAt(4);

لاحظ أن العنصر الذي ترتيبه 4 هو العنصر الخامس

الدالة SelectedIndices من دوال الكائن lv تقوم بإرجاع مصفوفة تحتوي على ترتيبات الأسطر المختارة في الكائن

فمثلاً لو أخترنا السطر الثالث و الرابع من القائمة سترجع الداله مصفوفة تحتوي رقمي 2 و 3

لاحظ , أن السطر الثالثة ترتيبة 2 وليش 3 كما شرحنا مراراً.

لكنا نريد عند النقر على زر الحذف أن يقوم البرنامج بحذف سطر واحد, وهو أول سطر من السطور المختارة

lv.SelectedIndices[0]

وفي السطر الثاني نقوم بإستدعاء الإجراء FillView والذي يقوم بنسخ محتويات القائمة albume إلى الكائن lv

ماذا لو تم النقر على زر الحذف وليس هناك أسطر مختارة من قبل المستخدم ,

سيظهر خطأ عندها , ولحل هذا الخطأ يجب أولاً فحص عدد العناصر المختارة فإذا كان أكبر من صفر

فذلك يعني أن هناك ملفات مختارة و بالتالي ينفذ كود الحذف ,

عدل الكود السابق حتى يصبح هكذا :

			if(lv.SelectedIndices.Count>0)
			 {
			 albume.RemoveAt(lv.SelectedIndices[0]);
			 FillView();
			 }

يتم فحص عدد العناصر المختارة من خلال الخاصية lv.SelectedIndices.Count

تابع التطبيق في الرد التالي..

إعذرونا , سنضطر للغياب فترة كبيرة

الأمر ليس بيدنا ...... فسامحونا

#58

نقل ملف إلى الأعلى

وظيفة هذا الزر هو إعادة ترتيب الملفات بحيث ينقل الملف المختار في كائن المستعرض إلى أعلى خطوة واحدة

إذهب إلى تصميم نافذة الألبومات و أنقر مزدوجاً على زر "إلى الأعلى"

وأكتب الكود التالي بين الحاصرتين :

			int sel = lv.SelectedIndices[0];
			 string tmp = albume[sel];
			 albume[sel] = albume[sel-1];
			 albume[sel - 1] = tmp;
			 FillView();
			 lv.Items[sel-1].Selected = true;

في السطر الأول عرفنا متغير من نوع رقم يقوم بخزن ترتيب السطر المختار في كائن المستعرض lv

وفي السطر الثاني عرفنا متغير آخر من نوع نص يقوم بخزن قيمة العنصر الذي ترتيبة هو ترتيب السطر المختار

وفي السطر الثالث قمنا بتحميل العنصر الذي ترتيبه هو ترتيب السطر المختار بقيمة العنصر الذي قبله

وفي السطر الرابع قمنا بتحميل السطر السابق للسطر المختار بالقيمة التي كانت مخزنة في السطر المختار

وفي السطر الخامس قمنا بإستدعاء إجراء تعبئة الكائن lv

وفي السطر السادس قمنا بتحديد وإختيار السطر الحالي الذي تم نقله

لتوضيح الكود السابق لاحظ هذا الشكل التوضيحي :

image10-10.jpg

حيث إفترضنا أن القائمة albume تحتوي على ثلاثة عناصر تم إختيار العنصر الأوسط لنقله خطوة إلى الأعلى

ماذا لو إختار المستخدم أول عنصر سطر في المستعرض , كيف سيتم نقل أول عنصر في القائمة خطوة إلى أعلى

سيحدث خطأ إذا حاول المستخدم فعل ذلك ولتفادي هذا الخطأ يجب أن نفحص ترتيب السطر المختار sel فإذا كان يساوي صفر

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

عدل الكود السابق ليصبح هكذا :

			int sel = lv.SelectedIndices[0];
			 if(sel>0)
			 {
			 string tmp = albume[sel];
			 albume[sel] = albume[sel-1];
			 albume[sel - 1] = tmp;
			 FillView();
			 lv.Items[sel-1].Selected = true;
			 }

ماذا لو لم يختر المستخدم أي سطر وقام بالنقر على زر النقل .. سيحدث هنا أيضاً خطأ , ويجب معالجته كما فعلنا في زر الحذف

عدل الكود السابق ليصبح هكذا :

			if(lv.SelectedIndices.Count>0)
			 {
			 int sel = lv.SelectedIndices[0];
			 if(sel>0)
			 {
			 string tmp = albume[sel];
			 albume[sel] = albume[sel-1];
			 albume[sel - 1] = tmp;
			 FillView();
			 lv.Items[sel-1].Selected = true;
			 }
			 }

نقل ملف إلى أسف

يشبه كود نقل الملف لأعلى بإختلاف بسيط جداً فبدل من sel-1 نضع sel+1

وعند المقارنه sel>0 نضع sel<lv.Items.Count لأن النقل في هذه الحالة سيكون للأسفل

ويجب أن نفحص ما إذا كان ترتيب السطر المختار أقل من عدد سطور الكائن :

إفتح تصميم نافذة الألبومات وأنقر مزدوجاً على زر "إلى الأسف" وأنسخ الكود التالي بين الحاصرتين:

			if(lv.SelectedIndices.Count>0)
			 {
			 int sel = lv.SelectedIndices[0];
			 if(sel<lv.Items.Count-1)
			 {
			 string tmp = albume[sel];
			 albume[sel] = albume[sel+1];
			 albume[sel + 1] = tmp;
			 FillView();
			 lv.Items[sel+1].Selected = true;
			 }
			 }

بهذا نكون قد أنتهينا من نافذة الألبومات ...

أنتقل إلى النافذة الرئيسية و من صندوق الأدوات إسحب كائن الزر إلى النافذة الرئيسية وغير النص إلى "التحكم بالألبومات"

اضبط ترتيب الأدوات في النافذة حتى يصبح شكلها هكذا :

image10-11.jpg

إظهار نافذة الألبومات

إذهب إلى تصميم النافذة الرئيسية وأنقر مزدوجاً على زر "التحكم بالألبومات" لتنتقل إلى شفرته وانسخ الكود التالي بين الحاصرتين

			albumes frm = new albumes();
			 frm.albume = albume;
			 frm.ShowDialog();
			 albume = frm.albume;
			 FillList();

في السطر الأول عرفنا كائن إسمه frm من نوع albumes , لاحظ أن albumes هو إسم نافذة الألبومات

اي أنها الآن تعتبر كائن في النظام ويمكن تعريف متغريات من نوعها كما كنا نفعل مع القوائم أو الكائنات الأخرى

في السطر الثاني نقوم بتحميل القائمة albume من النافذة frm بقيم القائمة albume من النافذة الرئيسية

أي أن القائمة albume في النافذه الجديدة frm ستصبح نسخة مطابقة لقائمة albume الموجوده في النافذة الرئيسية

في السطر الثالث قمنا بإستدعاء الإجراء ShowDialog والذي يظهر النافذة frm للمستخدم

السطر الرابع يتم تنفيذة عند إغلاق النافذة frm , حيث يتم فيه نسخ قيمة albume من نافذة الألبومات لقائمة albume الموجوده في النافذة الرئيسية

أي ان الكود السابق يقوم بإنشاء نافذة جديدة وينسخ لها قيم albume حتى يعدل المستخدم فيها ويغلق النافذة

ثم يأخذ قيم albume من النافذة frm والتي تم تعديلها من قبل المستخدم وينسخ قيمها لقائمةalbume الموجوده في الصفحة الرئيسية

وفي السطر الخامس نستدعي إجراء FillList الذي يقوم بنسخ قيم albume إلى قائمة التشغيل كما شرحنا في الدروس السابقة

إذا شغلت البرنامج الآن وإخترت "التحكم بالألبومات" فلن تظهر لك عناصر قائمة albume لأنك لم تقم بإستدعاء إجراء تعبئة المستعرض FillView

حيث يحب إستدعاؤة بمجر تحميل نافذة الألبومات

إذهب إلى تصميم نافذة الألبومات وانقر مزدوجا على مكان خالي من الأدوات في النافذة ستنتقل إلى إجراة حدث Load :

		void AlbumesLoad(object sender, System.EventArgs e)
		 {

		 }

أكتب إستدعاء إجراء تعبئة المستعرض بين الحاصرتين حتى يصبح الإجراء هكذا :

		 void AlbumesLoad(object sender, System.EventArgs e)
		 {
			 FillView();
		 }

شغل البرنامج ومن النافذة الرئيسية إختر مجموعة ملفات ثم إختر "التحكم بالألبومات" وجرب كل الوظائف.

الواجب

أرسل التطبيق

.نهاية الدرس العاشر.

..

7oma

حماة النهضة

إعذرونا , سنضطر للغياب فترة كبيرة

الأمر ليس بيدنا ...... فسامحونا

#59

سلام عليكم حاولت بالبرنامج ومع ذالك اكتشفت ان الداله جيت لينث في البرنامج ترجع قيمه صفر وتسندها للمكسيموم عشان كذا يسوي هالمشكله

ليه يرجع قيمه صفر مادري عجزت اعرف طبعت سويت بعد امر الاسناد هذا

private void SetTrackBar()
		{
			if (type == "V")
			{
				taimTrackBar.Maximum = Convert.ToInt32(apVideo.Duration);


			}
			else if (type == "A")
			{
				taimTrackBar.Maximum = Convert.ToInt32(apAudio.Duration);
			}
			else if (type == "R")
			{

				{
					taimTrackBar.Maximum = Convert.ToInt32(rpReal.GetLength());
					MessageBox.Show(Convert.ToString(taimTrackBar.Maximum));
				}
			}

		}

حطيت مسج شو بوكش عشان اشوف كم الرقم وصار صفر يعني مايرجع قيمه طول الملف ليه مادري ..؟

وهو اللي يخلي التايم مايشتغل معه لان تبي تصير قيمه الفاليو اكبر من صفر اللي هو المكسيموم والمفروض يكون بين المكس والمينيموم

الحين لما اشغل البرنامج يحمل الملف الريل البلاير بعدين يعطيني مسج بقيمه المكسيموم بعدين يشغل الملف فلما يطلع المسج يكون فيه صفر لكن ان ضغطت اوكيه واشتغل الملغ طبيعي بس مايتحرك التايم اروح اوقف الملف بعدين اسوي اوبن للملف نفسه مره ثانيه يفتحه لي ويجيب لي طوله مضبوط ويشتغل التايم .. ؟؟! يعني لازم افتحه مرتين متتاليتين عشان يضبط ولو افتح ملف ثاني يصير نفس المشكله ..

تتوقع وش المشكله

#60

وعليكم السلام

StUd_C

أخي كما سبق وقلت لعل إصدار البيئة هو سبب المشكلة

هل لك أن ترسل لي مجلد المشروع بالكامل حتى أتأكد من ذلك

xsco2002

ربنا يجزيك الخير يا أخي

إن شاء الله تستفيد معنا ^^

7oma

حماة النهضة

إعذرونا , سنضطر للغياب فترة كبيرة

الأمر ليس بيدنا ...... فسامحونا

#61

وهذا الملف حق المشروق ارفقته بالكامل

myVidio.rar

#62

السلام عليكم

StUd_C

أخي كودك صحيح , وليس فيه أي خطأ

سبب هذا الخلل هو بطئ دوال الريل بلاير بالمقارنة بدوال DirectX في بعض أنظمة التشغيل

حيث يثم إستدعاء إجراء SetTrack قبل إكتمال تحميل الملف

وحل هذا الخلل موجود في الدرس الثامن

..

7oma

حماة النهضة

إعذرونا , سنضطر للغياب فترة كبيرة

الأمر ليس بيدنا ...... فسامحونا

#63

الدرس الحادي عشر

دوارة While

في الدرس الرابع تعرفنا على هيكل من هياكل التكرار في لغة C# وهو دوارة for

والحقيقة أن هناك هياكل أخرى من هياكل التكرار أهمها هي دوارة While

وهي تشبة إلى حد كبير دوارة for بإختلاف أنها لا تحتوي على عداد Counter كما كنا نعرف i في دوارة for

والهيكل الأساسي لدوارة While يشبة إلى حد كبير هيكل for بإختلاف أشياء بسيطة :

while (شرط التكرار)
 {
 كود الدوارة
 }

تقوم جملة while بتكرار كود الدوارة ما دام شرط التكرار متحققاً , مثلاً :

int n=0;
 while (n<5)
 {
 MessageBox.Show("من داخل الدوارة ");
 n++;
 }

الدوارة السابقة تقوم بإظهار الرسالة خمس مرات

حيث عرفنا متغير من نوع رقم n وأسندنا له قيمة إبتدائية 0

وشرط التكرار في الدوارة هو أن تكون قيمة المتغير n أصغر من 5

في المرة الأولى ستكون قيمة n هي صفر , وبالتالي فشرط التكرار متحقق , لأن الصفر أقل من 5

يتم تنفيذ كود إظهار الرسالة , والكود n++ يعني إضافة واحد إلى قيمة n أي أن n سيحمل الآن القيمة 1

يعود المعالج لبداية جملة while ويختبر شرط التكرار مرة أخرى ثم ينفذ كود إظهار الرسالة ويزيد واحد لقيمة n

وهكذا حتى تصبح قيمة n=5 عندها لن يتحقق شرط التكرار لأن 5 لسيت أقل من 5

وبالتالي يقفز المعالج إلى نهاية كود الدوارة ويواصل تنفيذ التعليمات بعدها

يستخدم هذا النوع من الدوارات حين لا نعرف كم بالضبط سنكرر كود الدوارة

وسنستخدمها في درس اليوم حيث لدينا معلومات الألبوم ولا نعرف عدد الملفات في الألبوم كما سنشرح بالتفصيل لا حقا

ملفات XML

من اهم أنظمة الحاسوب التي استفادة منها الإنسانية منذ ظهور الحاسوب هي أنظمة قواعد البيانات

وأنظمة قواعد البيانات هي برمجيات تستخدم مع لغات البرمجة بغرض خزن وإسترجاع أنواع متعددة من البيانات

ويتم خزن هذه البيانات بطرق مرتبة ومنهجية بحيث يسهل إسترجاع بيانات محددة مهما كبير كان حجم البيانات

حيث يتم ترتيب البيانات في وحدات متجانسة تسمى جداول Tables والتي تحتوي على حقول Fields لكل حقل نوع محدد من البيانات

ويمكن للجدول الواحد أن يحتوي على عدة حقول من أنواع بيانات مختلفة

قد ترتبط الجداول مع بعضها بواسطة علاقات Relationships حيث تعتمد بيانات من جدول على بيانات من جدول آخر

أنظمة قواعد البيانات تقسم إلى قسمين , نظام الخزن , ونظام المعالجة

أما نظام الخزن فهو المسئول عن خزن البيانات في ملفاتها المحددة بغض النظر عن ترتيبها أو أماكنها

ونظام المعالجة هو المسئول عن تحديد أماكن البيانات الصحيحة و إسترجاعها والقيام بالعمليات عليها

النظام الأول -نظام الخزن- يتكفل به نظام التشغيل ولا يحتاج لبرمجيات أو برامج خاصة

أما النظام الثاني فيتطلب برمجيات محددة لنظام قواعد البيانات

معظم أنظمة قواعد البيانات تستخدم النظام الثاني , مثل قواعد الأكسس و الأوراكل و غيرها

هناك أنواع أخرى لا تتطلب برمجيات مخصصة للتعامل معها ومنها نظام قواعد البيانات عبر ملفات XML

وهذا هو محور درسنا اليوم , حيث لا يحتاج هذا النظام لبرمجيات متخصصة للتعامل معه

وإنما ملفاته عبارة عن ملفات نصية يمكن فتحها وتعديلها بأي محرر نصوص

وسنستخدم ملفات XML في تطبيقنا لخزن بيانات الألبومات أو قوائم التشغيل

صيغة هذه الملفات النصية تشبة إلى حد كبير صيغة ملفات HTML

حيث يعتمد على وسوم Tags ترتب البيانات في هياكل مترابطة

وكل جزء من البيانات يحتوي على وسم بداية ووسم نهاية وله إسم محدد

فمثلاً هذا الكود :

<msg>رسالة</msg>

هذا جزء من كود ملف XML حيث يحتوي على جزء لخزن البيانات إسمه msg

يحتوي هذا الجزء على بيانات مخزنة هو كلمة "رسالة" لاحظ أن الجزء يحتوي على وسمين

وسم البداية حيث يحتوي على إسم الجزء بين علامتي أصغر وأكبر من

ووسم النهاية وهو مشابه تماما لوسم البداية بزيادة الشرطة المائلة / قبل إسم الجزء في وسم النهاية

وبين الوسمين توجد البيانات

وتسمى الأجزاء في ملفات XML بالعقد Nodes فالكود السابق يحتوي على عقدة إسمها msg

سميت بالعقد لأنه يمكن لأي جزء من البيانات أن يحتوي على أجزاء أخرى :

<albumes>
	<albume1>

	</albume1>
 </albumes>

الكود السابق يحتوي على عقدة رئيسية إسمها albumes تحتوي بدورها على عقدة فرعية إسمها albume1

يمكن أن تحتوي العقدة على عدة عقد فرعية :

<albumes>

	<albume1>
	</albume1>

	<albume2>
	</albume2>

 </albumes>

لعقدة الرئيسية albumes تحتوي على عقدتين فرعيتين albume1 و albume2

يمكن أيضاً للعقدة الفرعية أن تحتوي على عقد فرعية أخرى:

<albumes>

	<albume1>
	 <file>sound.mp3</file>
	 <file>wave.rm</file>
	</albume1>

	<albume2>
	 <file>real.wav</file>
	</albume2>

 </albumes>

العقدة الرئيسية albumes تحتوي على عقدتين فرعيتين albume1 و albume2

العقدة الفرعية albume1 تحتوي على عقدتين فرعيتين بنفس الإسم file

كل عقدة من عقدتي file بيانات نصية sound.mp3 و wave.rm

والعقدة الفرعية albume2 تحتوي على عقدة فرعية file

الكود السابق يمثل ملف XML يحتوي على بيانات مرتبة في عقد , ولكن ينقصة شيئ مهم

نوع التكويد في المف , ورقم إصدار كود XML , والتكويد هو أسلوب خزن البيانات النصية في الملف

عادة ما نستخدم تكويد UTF-8 , وسطر نوع التكويد يجب أن يكون في بداية الملف:

<?xml version="1.0" encoding="utf-8"?>
 <albumes>
	<albume1>
	 <file>sound.mp3</file>
	 <file>wave.rm</file>
	</albume1>
	<albume2>
	 <file>real.wav</file>
	</albume2>
 </albumes>

هذا السطر لا يتغير في معظم ملفات XML

هذا هو هيكل الملف الذي سيقوم بخزن بيانات الألبومات وقوائم التشغيل

يتم التعامل مع ملف XML في البرنامج من خلال كائن XmlDocument الموجود في فضاء الأسماء System.XML:

XmlDocument doc = new XmlDocument();

الكود السابق عرفنا من خلالة كائن إسمه doc من نوع XmlDocument

الكائن doc يقوم بتحميل المف عن طريق الإجراء Load

doc.Load("c://albumes.xml");

الكود السابق يقوم بتحميل الملف albumes.xml الموجود في القرص c إلى الكائن doc

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

أما إذا أردنا الوصول إلى العقد الرئيسية المسماه albumes فنكتب إسم الكائن doc متبوعاً بقوسين مربعين يحتويان إسم العقدة :

doc["albumes"];

ويتم الوصول إلى البيانات في العقدة بواسطة الخاصية InnerText :

MessageBox.Show(doc["albumes"].InnerText);

الكود السابق يقوم بإظهار رسالة تحتوي على البيانات المخزنة في العقدة albumes

ويتم الوصول لإسم العقدة عن طريق الخاصية :Name

MessageBox.Show(doc["albumes"].Name);

الكود السابق يظهر رسالة تحتوي على إسم العقدة albumes

ويتم الوصول إلى العقد الفرعية بإضافة قوسين مربعين يحتويان إسم العقدة

فمثلاً للوصول إلى العقدة الفرعية albume1 الموجود في العقدة albumes :

doc["albumes"]["albume1"]

وللوصول إلى العقدة الأعمق file :

 doc["albumes"]["albume1"]["file"]

التطبيق في الرد التالي ..

إعذرونا , سنضطر للغياب فترة كبيرة

الأمر ليس بيدنا ...... فسامحونا

#64

التطبيق

افتح تطبيق الدرس السابق , من نافذة مستعرض المشروع, أنقر بالزر الأيمن على إسم المشروع

ومن القائمة الناتجة إختر Add ثم New Item :

image11-1.jpg

ستظهر نافذة إضافة ملف جديدة للمشروع , من القائمة في اليسار إختر misc

ثم إختر Empty XML file , وفي صندوق إسم الملف أكتب الإسم التالي albumes.xml , وإختر OK

image11-2.jpg

إذهب إلى مجلد المشروع وأنسخ الملف albumes.xml إلى مجلد Debug الموجود داخل مجلد bin

حيث يصبح الملف موجود بجانب ملفات المشروع الأخرى

الآن قم بفتح تصميم نافذة الألبومات وسحب ثلاثة أزرار إلى النافذة وغير الأسماء فيها إلى

ألبوم جديد

حفظ الألبوم

حذف الألبوم

ومن صندوق الأدوات إسحب كائن القائمة المنسدلة إلى نافذة الالبومات :

image11-3.jpg

إختر كائن القائمة المنسدلة و من جدول الخصائص , غير الخاصية (Name) , إلى ac

وغير الخاصية Text إلى "إختر الألبوم"

قم بترتيب الأدوات في النافذة حتى تصبح هكذا :

image11-4.jpg

جميع الدوال التي سنستخدمها للتعامل مع ملف XML موجوده في فضاء الأسماء XML الموجود داخل الفضاء System

لذلك يجب إضافة عبارة using لتعريف جميع دوال وكائنات التعامل مع ملفات XML

إذهب إلى شفرة نافذة الألبومات و أكتب السطر التالي , تحت جمل using في رأس الملف:

image11-5.jpg

يتم تحميل ملف XML إلى البرنامج والتعامل معه من خلال كائن XmlDocument

حيث سنعرف كائن عام من هذا النوع ليتم التعامل معه في جميع أنحاء نافذة الألبومات

إنسخ كود التعريف تحت تعريف قائمة albume من الدرس السابق :

image11-6.jpg

قمنا هنا بتعريف كائن إسمه doc من نوع XmlDocument , ولأنه كائن إستخدمنا الكلمة new

إجراء تحميل الألبومات للقائمة المنسدلة FillCombo

يقوم هذا الإجراء بتحميل أسماء الألبومات الموجوده في ملف XML إلى القائمة المنسدلة ac

قم بنسخ الكود التالي إلى شفرة نافذة الألبومات وتأكد أنه خارج أي إجراء آخر :

		void FillCombo()
		 {
			 doc.Load(Application.StartupPath + "//albumes.xml");
			 XmlNode alnd = doc["albumes"].FirstChild;
			 while (alnd != null)
			 {
				 ac.Items.Add(alnd.Name);
				 alnd = alnd.NextSibling;
			 }
		 }

السطر الأول يقوم بتحميل الملف إلى الكائن doc

والتعليمة Application.StartupPath تعيد قيمة نصية تمثل مسار ملف exe للتطبيق

حيث إستفدنا من هذه التعليمة لمعرفة مسار ملف XML وأضفنا إسم الملف للمسار

في السطر الثاني قمنا بتعريف كائن من نوع عقدة XmlNode إسمه alnd

ثم حملنا هذا الكائن أول عقدة فرعية داخل العقدة الرئيسية albumes من خلال الخاصية FirstChild

السطر الثالث يمثل جملة while تنفذ كود الدوارة ما دامت العقدة alnd تحمل قيمة

الشرط alnd!=null يختبر الكائن alnd فإذا كان يحمل قيمة غير القيمة الفارغة null فسيتم تنفيذ كود الدوارة

أما إذا كان الكائن alnd لا يحمل قيمة أي أنه يحمل null فعندها لن يتم تنفيذ كود الدوارة

السطر الخامس يقوم بإضافة إسم العقدة alnd إلى القائمة المنسدلة ac

السطر السادس يقوم بإختيار العقدة التالية للعقدة alnd حيث يحمل الكائن alnd العقد التالية لما كان يحمله

يتم تكرار السطرين السابقين حتى الوصول إلى آخر عقدة عندها سيحمل الكائن alnd القيمة null لأنه لا يوجد عقدة تالية للعقدة الأخيرة

وبالتالي ينتهي تكرار جملة while

لكن ماذا لو لم يكن هناك إي عقد في ملف XML , عندها سينتج خطأ من تنفيذ هذا الإجراء ولحل ذلك نستخدم عبارة try:

قم بتعديل الكود السابق حتى يصبح هكذا :

		void FillCombo()
		 {
			 try
			 {
				  doc.Load(Application.StartupPath + "//albumes.xml");
				 XmlNode alnd = doc["albumes"].FirstChild;
				 while (alnd != null)
				 {
				 ac.Items.Add(alnd.Name);
				 alnd = alnd.NextSibling;
				 }
			 }
			 catch
			 {
				 MessageBox.Show("حدث خطأ أثناء إسترجاع بيانات الألبومات");
			 }
		 }

بعد شرح إجراء FillCombo بقي أن نحدد مكانا مناسباً لإستدعاءه , وأفضل مكان لذلك هو عند تحميل النافذة

إذا إلى تصميم نافذة الألبومات وانقر مزدوجاً على مكان فارغ في النافذة لتذهب إلى كود تحميل النافذة albumes_Load

أضف إستدعاء إجراء FillCombo تحت إجراء FillView من الدرس السابق , حيث يصبح كود تحميل النافذة هكذا :

		void AlbumesLoad(object sender, System.EventArgs e)
		 {
			 FillView();
			 FillCombo();
		 }

إجراء قراءة محتويات الألبوم ReadAlbume

سيقوم هذا الإجراء بقراءة محتويات ألبوم محدد من ملف XML وتخزينها في قائمة albume

ثم إستدعاء إجراء FillView لنسخ محتويات القائمة إلى كائن المستعرض lv

يحتوي هذا الإجراء على مدخل من نوع نص يمثل الألبوم المختار المراد تحميل ملفاته إلى كائن المستعرض

إنسخ الكود التالي إلى شفرة نافذة الألبومات وتأكد أنه خارج أي إجراء آخر:

		void ReadAlbume(string albumename)
		 {
			 try
			 {
			 doc.Load(Application.StartupPath + "//albumes.xml");
			 XmlNode filend = doc["albumes"][albumename].FirstChild;
			 albume.Clear();
			 while (filend != null)
			 {
				 albume.Add(filend.InnerText);
				 filend = filend.NextSibling;
			 }
			 FillView();
			 }
			 catch
			 {
				 MessageBox.Show("حدث خطأ أثناء محاولة إسترجاع بيانات الألبومات");
			 }
		 }

السطر الأول من الكود يحتوي على إسم الإجراء وإسم المدخل ونوعة string

السطر الخامس لتحميل ملف XML إلى الكائن doc

السطر السادس عرفنا كائن من نوع عقدة يحمل أول عقدة من العقدة الفرعية التي إسمها هو المدخل والموجوده داخل العقدة الرئيسية albumes

لاحظ أنا وضعنا إسم المدخل في العقدة الفرعية فعند تشغيل البرنامج سيتم إستبدالة بقيمة المدخل كما سنرى لاحقاً

السطر السابق يقوم بتحديد عقدة الألبوم المدخل , مثلاً albume1 ثم أخذ أول عقدة منه file وتحميلها على الكائن filend

السطر السابع قمنا بتنظيف القائمة albume من أي عناصر موجودة فيها حتى ندخل إليها العناصر الجديدة من الملف

جملة while في السطر الثامن , تنفذ كود الدوارة ما دام filend لا يحمل القيمة null

السطر العاشر نقوم بإضافة بيانات العقدة إلى القائمة عن طريق الخاصية InnerText في العقدة

في السطر الحادي عشر نقوم بإختيار وتحميل العقدة التالية للعقدة الحالية , وهكذا حتى نصل لآخر عقدة ويتوقف تنفيذ كود الدوارة

في السطر الثالث عشر نقوم بإستدعاء إجراء نسخ القائمة albume إلى كائن المستعرض lv

بعد شرح هذا الإجراء بقي أن نختار المكان المناسب لإستدعائة

وأفضل مكان لذلك هو عندما يختار المستخدم إسم الألبوم من القائمة المنسدلة

إذهب إلى تصميم نافذة الألبومات وأنقر مزدوجاً على كائن القائمة المنسدلة

ستذهي إلى الشفرة , أكتب هناك إستدعاء الأجراء ReadAlbume

لا تنسى أن هذا الإجراء يتطلب مدخل من نوع نص يمثل الألبوم المختار

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

لذلك فإستدعاء الإجراء سيكون هكذا :

			ReadAlbume(ac.Text);

ويصبح كود الإجراء كاملاً - إختيار إسم الألبوم من القائمة - هكذا :

		void AcSelectedIndexChanged(object sender, System.EventArgs e)
		 {
			 ReadAlbume(ac.Text);
		 }

حيث أنه عند تشغيل البرنامج وإستدعاء الإجرء سيتم تغيير albumename في الإجراء إلى قيمة ac.Text

تابع التطبيق...

إعذرونا , سنضطر للغياب فترة كبيرة

الأمر ليس بيدنا ...... فسامحونا

#65

إجراء حذف الألبوم DeleteAlbume

يقوم هذا الإجراء بحذف بيانات الألبوم المختار من ملف XML

حيث يتطلب مدخل واحد من نوع نص , يمثل إسم الألبوم المراد حذفة

انسخ الكود التالي إلى شفرة نافذة الألبومات وتأكد من أنه خارج أي إجراء آخر :

		void DeleteAlbume(string albumename)
		 {
			 try
			 {
				 if (MessageBox.Show("هل أنت متأكد من حذف / تعديل الألبوم ؟", "هل أنت متأكد", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
				 {
					 doc.Load(Application.StartupPath + "//albumes.xml");
					 doc["albumes"].RemoveChild(doc["albumes"][albumename]);
					 doc.Save(Application.StartupPath + "//albumes.xml");
					 ac.Items.RemoveAt(ac.SelectedIndex);
					 lv.Items.Clear();
				 }
			 }
			 catch
			 {
			 }
		 }

السطر الأول يحتوي على إسم الإجراء وإسم المدخل ونوعه string

السطر الخامس جملة if تقوم بإظهار رسالة تحذير للمستخدم بحيث يتم تأكيد الحذف , لاحظ عبارة إستدعاء الدالة :

MessageBox.Show("هل أنت متأكد من حذف / تعديل الألبوم ؟", "هل أنت متأكد", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2)

العبارة إختلفة عن ما كنا نعرفه من قبل , ورغم أنها نفس التعليمة إلا أنها هذه المرة إستقبلت مدخلات أكثر

لذلك وظيفتها هذه المرة مختلفة قليلاً , المدخل الأول هو نص الرسالة كما عرفنا سابقاً

المدخل الثاني هو عنوان الرسالة الذي سيظهر في شريط العنوان

المدخل الثالث MessageBoxButtons.YesNo هو الأزرار المطلوب إظهارها في الرسالة حيث إخترنا YesNo

وهناك أيضاً OkCancel و هناك مجموعات أخرى من الأزرار

المدخل الرابع MessageBoxIcon.Question يمثل الأيقونه المراد إظهارها في الرسالة حيث إخترنا أيقونة السؤال Question

المدخل الخامس MessageBoxDefaultButton.Button2 يمثل الزر الإفتراضي , أي الزر الذي يكون التركيز عليه عند ظهور الرسالة

وقد إخترنا Button2 والذي سيكون في هذه الحالة زر No حيث سيكون الجواب الإفتراضي للرسالة هو No

وقد إخترنا No بدلا من Yes حتى يتأكد المستخدم من إختيارة قبل أن نحذف بيانات الألبوم

وإذا كانت نتيجة هذه الرسالة هي الموافقة DialogResult.Yes سيتم تنفيذ كود الحذف وإلا فلا

في السطر السابع تعليمة تحميل الملف لكائن doc

وفي السطر الثامن تعلمية إزالة عقدة الألبوم , حيث يتم إزالة عقدة بتحديد عقدتها الرئيسية ثم إستدعاء الإجراء RemoveChild

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

داخل قوسي إجراء الحذف العقدة المراد حذفها , وهي العقدة الذي إسمها هو المدخل albumename

الموجودة داخل العقدة الرئيسية albumes

في السطر التاسع تعليمة حفظ التغييرات على ملف XML بإستدعاء الإجراء Save من كائن doc

في السطر العاشر تعليمة حذف إسم الألبوم المحذوف من القائمة المنسدلة

وفي السطر الحادي عشر تعليمة تنظيف كائن المستعرض lv من ملفات الألبوم المحذوف

المكان المناسب لإستدعاء هذا الإجراء هو كود الزر "حذف الألبوم"

إذهب إلى تصميم نافذة الألبومات وانقر مزدوجاً على زر "حذف الألبوم" وأكتب إستدعاء إجراء الحذف هناك :

				  DeleteAlbume(ac.Text);

إجراء حفظ الألبوم WriteAlbume

هذا الإجراء سيقوم بتخزين محتويات كائن المستعرض lv إلى ملف XML

حيث يقوم الإجراء أولاً بإنشاء عقدة الألبوم , وتسميتها بالنص المكتوب على القائمة المنسدلة

ثم يقوم بإنشاء العقد الفرعية file والتي تحتوي على مسارات الملفات الموجودة في كائن المستعرض

وأيضاً يقوم الإجراء بحفظ التغيرات على ألبوم موجود أساساً , بحيث يقوم بحذفة أولاً من الملف ثم تخزين ألبوم جديد بنفس الإسم وبالبيانات المعدلة

إنسخ الكود التالي إلى شفرة نافذة الألبومات وتأكد من أنه خراج إلى إجراء آخر :

		void WriteAlbume(string albumename)
		 {
			 try
			 {
			 doc.Load(Application.StartupPath + "//albumes.xml");
			 if (doc["albumes"][albumename]!=null)
			 {
				 doc["albumes"].RemoveChild(doc["albumes"][albumename]);
			 }
			 else
			 {
				 ac.Items.Add(ac.Text);
			 }
			 XmlNode albumend = doc.CreateElement(albumename);
			 for (int i = 0; i < albume.Count; i++)
			 {
				 XmlNode filend = doc.CreateElement("file");
				 XmlNode path = doc.CreateTextNode(albume);
				 filend.AppendChild(path);
				 albumend.AppendChild(filend);
			 }
			 doc["albumes"].AppendChild(albumend);
			 doc.Save(Application.StartupPath + "//albumes.xml");
			 }
			 catch
			 {
				 MessageBox.Show("حدث خطأ أثناء محاولة حفظ بيانات الألبومات");
			 }
		 }

السطر الأول يحتوي على إسم الإجراء وإسم المدخل و نوعة string

السطر الخامس تعليمة تحميل الملف إلى كائن doc

السطر السادس عبارة if تختبر هل هناك عقدة للألبوم المحدد في ملف XML

فإذا كانت العقدة موجودة فالسطر الثامن يقوم بحذفها , حتى توضع بدلاً منها العقدة بالبيانات المعدلة

والحذف هنا هو للبيانات القديمة وخزن البيانات الجديدة كأنها إلبوم جديد بنفس الإسم

أما اذا لم يكن الألبوم موجود في الملف فإن كود الحذف لن يفعل شيئاً

لأنه ألوم جديد وبالتالي يضاف إسم هذا الألبوم إلى القائمة المنسدلة في السطر الثاني عشر

السطر الرابع عشر عرفنا متغير من نوع عقدة إسمه albumend وأسندنا له عقدة جديدة بعد إستدعاء تعليمة إنشاء العقدة

doc.CreateElement(albumename);

حيث يقوم الكود السابق بإنشاء عقدة جديدة في الملف إسمها هو المدخل albumename وهو إسم الألبوم المراد حفظه

السطر الخامس عشر عبارة for من الصفر إلى عدد عناصر القائمة albume لإنشاء عقد جديدة لكافة عناصرها

السطر السابع عشر عرفنا متغير من نوع عقدة إسمه filend حيث سيقوم بحمل عقدة جديدة إسمها file بعد إستدعاء تعليمة إنشاء العقدة

doc.CreateElement("file");

لاحظ لحد الآن أن لدينا عقدتين , العقدة albumend التي تحمل إسم الألبوم , والعقدة filend التي تحمل إسم file

بقي أن ندخل البيانات إلى العقدة file

السطر الثامن عشر عرفنا متغير من نوع عقدة وحملناه قيمة نصية من خلال إستدعاء إجراء إنشاء عقدة نصية

doc.CreateTextNode(albume);

حيث يستقبل هذه الإجراء مدخل من نوع نص وهو البيانات المراد خزنها في العقدة , وهي العنصر الذي ترتيبة i من القائمة albume

الآن أصبح لدينا ثلاث عقد عقدة albumend التي تحمل إسم الألبوم , والعقدة filend التي تحمل إسم file وعقدة path التي تحمل مسار الملف من عنصر القائمة albume

إلى الآن لم يتم ربط العقد ببعضها البعض فهي إلى حد الآن عقد مستقلة ومنفصلة

يتم ربط عقدة فرعية بعقدة رئيسية من خلال إستدعاء الإجراء AppendChild من العقدة الرئيسية

وتمرير العقدة الفرعية كمدخل لهذا الإجراء , حيث في السطر التاسع عشر ربطنا العقدة path بعقدة filend

وأصبحت العقدة file تحتوي على بيانات , ثم في السطر العشرين ربطنا العقدة filend بما فيها بالعقدة albumend

وبتكرار العملية لكافة عناصر القائمة albume ستنتج لنا عقدة رئيسية إسمها بإسم المدخل albumename

تحتوي على عدة عقدة فرعية file تحتوي على مسارات الملفات في الألبوم

لاحظ أن عقدة الألبوم حتى الآن لم ترتبط بعقدة رئيسية , بل ربطناها بعقد فرعية فقط

في السطر التانب والعشرين ربطنا العقدة albumend بالعقدة الرئيسية في الملف albumes

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

بقي أن نحدد مكان إستدعاء هذا الإجراء , إذهب إلى تصميم نافذة الأبومات وأنقر مزدوجاً على زر "حفظ الألبوم"

ستنتقل إلى الشفرة , أكتب هذا :

			 WriteAlbume(ac.Text);

بقي لدينا زر واحد وهو زر "البوم جديد" , إذهب إلى تصميم نافذة الألبومات وانقر مزوجاً على الزر "ألبوم جديد"

وأكتب داخلة هذه التعليمات :

			 lv.Items.Clear();
			 albume.Clear();
			 ac.Text = "";

في السطر الأول قمنا بتنظيف كائن المستعرض من أي ملفات موجودة مسبقاً

وفي السطر الثاني قمنا بتنظيف القائمة albume من أي عناصر موجودة مسبقاً

وفي السطر الثالث قمنا بتصفير النص المكتوب على القائمة المنسدلة , بحيث اصبح كل شيئ جاهز لإنشاء ألبوم جديد

شغل البرنامج الآن وقم بتجريب حفظ ألبوم و إسترجاع بياناته

ملاحظة: عند أنشاء ألبوم جديد تأكد من أن إسم الألبوم لا يحتوي على فراغات أو رموز غريبة

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

الواجب

أرسل التطبيق

.نهاية الدرس الحادي عشر.

..

7oma

حماة النهضة

إعذرونا , سنضطر للغياب فترة كبيرة

الأمر ليس بيدنا ...... فسامحونا

#66

سلام عليكم ..

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

وهو لما اسوي اضافه البوم مايضيف او مافهمت بالضبط كيف الطريقه اخر درس ..

يعني الحين تصميم الاكس ام ال كيف جاي ياليت توضحه طريقته .. العقد ومكونات الملف نفسه ..

حقت التطبيق (يعني انسخ لنا ملف اكس ام ال عمل عليه البرنامج ..

لاشغلت البرنامج ودخلت على الالبوممات يطلع لي مسج حدث خطا في تحميل البيانات ( مع اني اصلن ماعبيت الاكس ام ال اي شي )

مو المفروض يقول خطا المفروض يقول مافيه البومات -لاجيت تنشي البوم جديد الاسم حق الالبوم وين تكتبه في مربع الكومبو بوكس .؟

ولا وين

الاكس ام ال المفروض تحطه بدرسين او اكثر لانه مهم جدا وراح نستفيد منه لو فهمناه زين ..

بس ماش راح اقرى الدرس مره ثانيه واحاول يمكن البلى مني <--

<-- الا اكيد منك خخ

#67

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

للاسف انى لسه مشتركه جديد فى المنتدى وقريت الموضوع ده دلوقتى بس

هو بصراحه موضوع جميل جدا وانا ان شاء الله هبدا فى تنفيذه خطوه خطوه من الاول

بس كان عندى سؤال :

انا لما نفذت اول تطبيق وبعدين سيفته و لما جيت افتحه تانى مش عارفه افتح انهى ملف عشان اكمل عليه

لان ملف الcs فيه الكود بس لكن مش فيه الform وفى ملف تانى فيه الform ومش فيه الكود

فياريت تقوللى افتح انهى ملف بالظبط عشان اكمل عليه

#68

وعليكم السلام

StUd_C

أخي تصميم ملفات XML يشبة كثيراً تصميم ملفات HTML

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

وعند إنشاء البوم جديد يتم كتابة إسمه في الكومبو بوكس

مع الـتأكد من أن الإسم لا يحتوي على فراغات أو رموز غريبة مثل $@%

أما عن الأخطاء التي تظهر فالمفروض أن تضيف جملة try catch وتكتب رسائل بالعربية للمستخدم تخبره بأن هناك خطأ

أيضاً يجب التأكد من أن ملف الـ XML موجود بجانب ملف exe للتطبيق داخل مجلد Debug

وتأكد أيضاً أن إسم الملف هو albumes.xml بالحروف الصغيرة

وهذا ملف XML جاهز - يجب تغيير مسارات الملفات فيه

Jordan

مرحبا بك أخي

منتظرين تطبيقاتك

وموفق في امتحاناتك بإذن الله

هند89

اقتباس
للاسف انى لسه مشتركه جديد فى المنتدى وقريت الموضوع ده دلوقتى بس

هو بصراحه موضوع جميل جدا وانا ان شاء الله هبدا فى تنفيذه خطوه خطوه من الاول

بس كان عندى سؤال :

انا لما نفذت اول تطبيق وبعدين سيفته و لما جيت افتحه تانى مش عارفه افتح انهى ملف عشان اكمل عليه

لان ملف الcs فيه الكود بس لكن مش فيه الform وفى ملف تانى فيه الform ومش فيه الكود

فياريت تقوللى افتح انهى ملف بالظبط عشان اكمل عليه

أهلاً بك أختي معنا

جواب السؤال موضح في الدرس الرابع

حيث أن ملف المشروع الأساسي هو الملف بإمتداد csproj

وهو الملف الذي يفتح بواسطة بيئة التطوير للتعديل على التطبيق كما هو موضح بالصورة :

image4-1.jpg

..

7oma

حماة النهضة

إعذرونا , سنضطر للغياب فترة كبيرة

الأمر ليس بيدنا ...... فسامحونا

#69
هند89 كتب:
السلام عليكم ورحمة الله وبركاته

للاسف انى لسه مشتركه جديد فى المنتدى وقريت الموضوع ده دلوقتى بس

هو بصراحه موضوع جميل جدا وانا ان شاء الله هبدا فى تنفيذه خطوه خطوه من الاول

بس كان عندى سؤال :

انا لما نفذت اول تطبيق وبعدين سيفته و لما جيت افتحه تانى مش عارفه افتح انهى ملف عشان اكمل عليه

لان ملف الcs فيه الكود بس لكن مش فيه الform وفى ملف تانى فيه الform ومش فيه الكود

فياريت تقوللى افتح انهى ملف بالظبط عشان اكمل عليه

صفحه الفورم اللي فتحتيها .. اضغطي دبل كليك بالماوس عليها

سينتقل لصفحه الكود ذات الامتداد .CS

او لما تفتحي البروجيكت اذهبي الي يمين الصفحه ستجدي

الـ Solution للمشروع

استعرضي الملفات الموجوده فيه و افتحيه لتعرفي كل منهم ماذا يحتوي

و بالتوفيق ان شالله

-----------

اخي حماه النهضه ... شكراً لك و تابع و نحن معك باذن الله

جزاك الله كل الخير

Success Is A Journey Not A Destination

#70

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

الدرس الثاني عشر

تحسين وظائف التطبيق

من البديهايات في البرمجة أن يحتوي أي تطبيق على شوائب bugs

تحد من إداء التطبيق مهامة على أكمل وجه

والشوائب هي الأخطاء البسيطة في البرنامج التي تنتج في ظروف محددة

والمبرمج عادة لا يكتشف هذه الأخطاء أثناء العمل في التطبيق , وإنما يكشفها إختبار التطبيق

وعملية إختبار التطبيق تعتبر من أهم مراحل تطوير البرمجيات وربما أكثر تعقيداً وإستهلاكاً للوقت والجهد

ولكن لحسن الحظ هذه العملية لا تحتاج إلى مبرمجين ليقوموا بها , وإنما دورهم هنا هو التعديل في كود التطبيق

الذي يقوم بهذه العملية هم المستخدمون أنفسهم , من خلال توزيع التطبيق بنسخ تجريبية Beta

وعادة ما تكون هذه النسخ مجانية , لأن مطور التطبيق هو المستفيد من إكتشاف الأخطاء

حيث يطلب من مستخدمي النسخ التجريبة أرسال أي أخطاء قد تواجههم إلى المطور

وبهذا يوفر المطور على نفسه الكثير من المجهود والوقت في إختبار التطبيق

والشوائب عادة ما تكون إحدى ثلاثة:

1-أخطاء الشوائب برمجية

وهي الشوائب التي تحدث بسبب خطأ في شفرة التطبيق , وتنتج هذه الأخطاء لأسباب كثيرة

وتسبب خلل في عمل البرنامج , كأن يتوقف البرنامج فجأة أو يقوم بعمليات غير منطقية

وكمثال على هذه الشوائب :

إفتح تطبيق الدرس السابق و أختر مجموعة ملفات من النافذة الأساسية

ثم إفتح نافذة الألبومات وأختر أحد الألبومات , ثم أختر إلغاء الأمر من نافذة الألبومات

المفروض بما أنك ألغيت الأمر أن لا يتغير شيئ في قائمة التشغيل في النافذة الرئيسية

ولكن القائمة تغيرة رغم أنك إخترت "إلغاء الأمر"

هذا الخطأ يعتبر من الشوائب البرمجية , وعلى المطور أن يبحث عن مكان الخطأ ويصححة

مكان الخطأ هنا هو إجراء النقر على زر "التحكم بالأبومات"

إفتح تصميم النافذة الرئيسية وانقر مزدوجاً على زر "التحكم بالألبومات" لتنتقل إلى الشفرة

ستجد هذا الكود :

						try
			   {
				   albumes frm = new albumes();
					  frm.albume = albume;
					  frm.ShowDialog();
					 albume = frm.albume;
					 FillList();
					 LoadFile(albume[0]);
						   SetTrackBar();
					 PlayFile();
			   }
			   catch
			   {
				   MessageBox.Show("حدث خطأ أثناء محاولة تشغيل الملف المحدد");
			   }

لاحظ السطر الخامس تعليمة إظهار نافذة الألبومات , بعدها تماما تعليمات التغيير في قائمة التشغيل

وهنا الخطأ , المفترض أن نختبر نتيجة نافذة الألبومات , فإذا كانت "موافق" ينفذ كود تغيير قائمة التشغير

وبالتالي يجب أن نضيف للكود السابق عبارة if لإختبار ناتج النافذة قبل تنفيذ تعليمات التغيير في قائمة التشغيل

هناك خطأ آخر هنا في السطر الرابع :

frm.albume = albume;

هذه التعليمة تساوي بين القائمة albume في كلا النافذتين , بحيث إذا تغير شيئ في قائمة albume في هذه النافذة

سيتغير نفس الشيئ في قائمة albume في النافذة الألبومات والعكس صحيح أيضاً

وهذا يعتبر خطأ لأنه من المفترض أن تكون كل قائمة مستقلة عن الأخرى , والمفروض أن لا نعمل مساواة بين القائمتين

وإنما نسخ عناصر القائمة في هذه النافذة إلى القائمة في النافذة الآخرى , والنسخ غير المساواة

المساواة تعني أن كلا النافذتين تحمل نفس القيمة دائماً

فإذا ساويت بين قائمتين ثم عدلت في أي منهما فإن الأخرى بالضرورة ستتعدل تلقائيا

أما النسخ فإذا نسخت قائمة من أخرى وعدلت في أي منها فإن الأخرى لا تتأثر لأنهما مستقلتان عن بعض

وهذا ما نحتاجه هنا , و النسخ في القوائم يتم عبر الإجراء AddRange كما شرحناه سابقاً

وبالتالي فالمفروض إستبدال السطر الرابع بهذا السطر :

frm.albume.AddRange(albume);

وبإضافة عبارة فحص نتيجة النافذة يصبح كود النقر على زر "التحكم بالألبومات" هكذا :

			try
			   {
				   albumes frm = new albumes();
				   frm.albume.AddRange(albume);
					  frm.ShowDialog();
				   if (frm.DialogResult == DialogResult.OK)
				   {
					   albume = frm.albume;
					   FillList();
					   LoadFile(albume[0]);
					   SetTrackBar();
					   PlayFile();
				   }
			   }
			   catch
			   {
				   MessageBox.Show("حدث خطأ أثناء محاولة تشغيل الملف المحدد");
			   }

لا حظ داخل حاصرتي if أنا ساوينا بين قائمتين , وهنا المساواة هي المطلوبة وليس النسخ

لأن ناتج النافذة هي الموافقة وبالتالي نريد مساواة بين قائمة نافذة الألبومات التي قمنا بالتعديلات عليها والقائمة في النافذة الرئيسية

وكمثال آخر على هذا النوع من الأخطاء شغل التطبيق وانقر على زر ملئ الشاشة دون تشغيل ملف صوتي

ستظهر رسالة خطأ ويتوقف البرنامج عنم العمل , لأنه لا يوجد فيديو حتى يجعله ملئ الشاشة

ولحل هذه المشكلة أذهب إلى كود زر ملئ الشاشة , وأضف جملة try :

			try
			   {
				   vp.Fullscreen = true;
			   }
			   catch
			   {
				   MessageBox.Show("لا يوجد ملف فيديو ");
			   }

2-إخطاء نقص في الوظائف

وهي الأخطاء التي لا تنتج عن خطأ في الكود وإنما تنتج عن نقص في وظائف التطبيق

أي أن التطبيق لا يحقق جميع الوظائف المطلوبة من المستخدم , ويتم حل هذه المشكلة بالتحديث Updating

وهذه التحديثات عادة ما تتكرر من إصدار لآخر في التطبيق

كمثال على هذه الأخطاء في تطبيقنا :

المستخدم عادة ما يفضل طريقة لإختيار سريع للألبوم الذي يريد تشغيلة

وفي تطبيقنا لا يمكن إختيار الألبوم إلى بفتح نافذة الألبومات , وهذا يعد نقصاً في متطلبات المستخدم

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

نحتاج لذلك إلى كائن من نوع XmlDocument ولذلك يجب إضافة عبارة using كما فعلنا في نافذة الألبومات

image11-5.jpg

ثم نعرف متغير عام إسمه doc من نوع XmlDocument تحت تعريف القائمة albume كما فعلنا في نافذة الألبومات

إفتح تصميم النافذة الرئيسية , ومن صندوق الأدوات إسحب كائن القائمة المنسدلة إلى النافذة الرئيسية فوق قائمة التشغيل

image11-3.jpg

وقم بتغيير الخاصية Name إلى ac و الخاصية Text إلى "إختر الألبوم"

يجب تحميل أسماء الألبومات بمجرد فتح البرنامج , لذلك سنكتب شفرة تحميل أسماء الألبومات في حدث تحميل النافذة كما فعلنا في نافذة الألبومات

افتح تصميم النافذة الرئيسية و انقر مزدوجاً على مكان فارغ في النافذة لتذهب إلى كو تحميل النافذة MainForm_Load أو Form1_Load

إنسخ هذا الكود بين الحاصرتين :

			doc.Load(Application.StartupPath + "//albumes.xml");
			   XmlNode albumesnd = doc["albumes"];
			   XmlNode alnd = albumesnd.FirstChild;
			   while (alnd != null)
			   {
				   ac.Items.Add(alnd.Name);
				   alnd = alnd.NextSibling;
			   }

الكود السابق هو نفسه الكود في إجراء تحميل نافذة الألبومات

نحتاج لقراءة ملفات الألبوم المحدد إلى إجراء ReadAlbume الموجود في نافذة الألبومات

إنسخ كود الإجراء ReadAlbume إلى شفرة النافذة الرئيسية وتأكد من أنه خارج أي إجراء آخر :

		void ReadAlbume(string albumename)
		   {
			   try
			   {
				   doc.Load(Application.StartupPath + "//albumes.xml");
				   XmlNode filend = doc["albumes"][albumename].FirstChild;
				   albume.Clear();
				   while (filend != null)
				   {
					   albume.Add(filend.InnerText);
					   filend = filend.NextSibling;
				   }
				   FillList();
			   }
			   catch
			   {
				   MessageBox.Show("حدث خطأ أثناء محاولة إسترجاع بيانات الألبومات");
			   }
		   }

كما نحتاج إيضاً لإضافة كود إستدعاء الإجراء ReadAlbume في حدث التغيير في القائمة المنسدلة

إذهب إلى تصميم النافذة الرئيسية وانقر مزدوجاً على كائن القائمة المنسدلة ac لتذهب إلى الشفرة

واكتب بين الحاصرتين كود إستدعاء إجراء قراة ملفات الألبوم :

			try
			   {
			   ReadAlbume(ac.Text);
			   FillList();
			   LoadFile(albume[0]);
			   SetTrackBar();
			   PlayFile();
			   }
			   catch
			   {
				   MessageBox.Show("حدث خطأ أثناء محاولة تشغيل الملف المحدد");
			   }

السطر الثالث يستدعي الإجراء ReadAlbume ليتم تحميل ملفات الملف المحدد إلى القائمة albume

والسطر الرابع يقوم بإستدعاء الإجراء FillList لتحميل عناصر albume إلى قائمة التشغيل

والسطر الخامس يقوم بتحميل أول عنصر من عناصر القائمة

والسادس يضبط شريك التنقل و السابع يشغل الملف ..

تابع الدرس في الرد التالي ..

إعذرونا , سنضطر للغياب فترة كبيرة

الأمر ليس بيدنا ...... فسامحونا

#71

3- أخطاء في الواجهات

وهي الأخطاء التي لا تؤثر على عمل البرنامج ولكن تؤثر على الواجهات الصورية للنوافذ

وهذه الأخطاء عادة ما يتم حلها بواسطة التحديثات Updating

كمثال على هذه الأخطاء من تطبيقنا :

إفتح التطبيق , وانقر على زر تكبير النافذة في شريط العنوان

ستلاحظ أن جميع كائنات النافذة محصورة في الزاوية العليا اليسرى من النافذة

حيث أن تكبير النافذة لم يقم بتعديل حجم و أماكن الكائنات

ولحل هذه المشكلة سنستخدم خاصية واحدة في جميع الكائنات : Anchor

معنى الكلمة "المرساه" ومن معناها يتبين لنا وظيفتها

حيث تقوم بربط الكائن بأحد جوانب النافذة أو بعدة جوانب

فمثلاً لو ربطت كائن قائمة التشغيل بيمين النافذة , وقمت بتكبير النافذة فستلاحظ أن مكانها تغير وإنزاح نحو يمين النافذة

أما إذا ربطت أي كائن بجانبين متعاكسين , كأن تربط شريط التنقل بيمين ويسار النافذة

وقمت بتكبير النافذة ستلاحظ أن حجم شريط التنقل قد تغير لأنه مرتبط بإتجاهين متعاكسين وهذا يؤدي إلى "مط" الكائن

إذهب إلى تصميم النافذة الرئيسية , وإختر الكائن الحاضن للفيديو "شاشة الفيديو"

وغير خاصية Anchor إلى Top, Bottom, Left, Right

image12-1.jpg

لاحظ أنا ربطنا كائن الشاشة بجميع جوانب النافذة وبالتالي فحجمها سيتمدد في جميع الجهات

ولكن المسافة بين نهاية الكائن وطرف النافذة من الأربع الجهات لن يتغير

إختر صندوق "طريقة التشغيل" وغير الخاصية anchor إلى : Bottom, Right

زر التحكم بالألبومات : Bottom, Right

القائمة المنسدلة لإختيار الألبوم : Top, Right

قائمة التشغيل : Top, Bottom, Right

شريط التنقل : Bottom, Left, Right

أزرار التشغيل : Bottom, Left

الآن شغل التطبيق , وجرب تغيير حجم النافذة ستلاحظ أن الكائنات تغير من حجمها و مكانها بحسب حجم النافذة

أيضاً كمثال على هذه الأخطاء , شكل شريط التنقل الكبير , والمشوه

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

وذلك بإستخدام كائن النص الثابت Label , إفتح تصميم النافذة الرئيسية ومن صندوق الأدوات إسحب كائن Label مرتين

وقم بتغيير الخاصية BackColor في كليهما إلى Transparent من تبويب Web وإحذف أي كلمة أمام خاصية Text

ثم قم بتغطية الأجزاء الزائدة من شريط التنقل ولا تنسى أن تغير الخاصية Anchor فيهما كما هي في شريط التنقل

أيضاً يمكن أن تغير أيقونه التطبيق بإختيار النافذة الرئيسية وتغيير الخاصية Icon

لتضيف لمسة إحترافية على التطبيق قم بتغيير الصور على الأزرار من خلال الخاصية Image

وتغيير خلفية النافذة من خلال الخاصية BackGroundImage

ملاحظة : هناك خطأ برمجي في بيئة تطوير ميكروسوفت وهو أن خلفية النافذة لا تظهر إذا كانت الخاصية RightToLeft تساوي True

سيبدو شكل التطبيق بعد هذه التعديلات هكذا :

image12-2.jpg

الواجب

إختبر التطبيق وصحح أي أخطاء برمجية أخرى

.نهاية الدرس الثاني عشر.

.نهاية الدروس.

تم بحمد الله

..

ختاماً :

نتمنى أن نكون قد وفقنا , في تقديم لغة C#2005 وشرح بعض مبادئها

آملين أن تكون هذه الدروس قد ساهمت في إزالة حاجز التعقيد بين المبتدئ واللغة

على أن هذه الدروس ماهي إلا بداية إنطلاقة في هذه اللغة الواسعة و الغنية عن التعريف

لا يسعنا في الأخير إلا أن نشكر لكم حسن متابعتنا , ونعتذر عن أي تقصير بدر منا

فإن أصبنا فمن الله , وإن أخطأنا فمن أنفسنا والشيطان

لا تنسونا من صالح دعائكم , وفقكم الله لما يحب ويرضى

وصلى الله على سيدنا محمد وعلى آله وصحبه أجمعين

..

جميع الحقوق غير محفوظة , يحق لك عزيزي القارئ أن تنشر هذه الدروس بأي طريقة غير ربحية

..

7oma

حماة النهضة

إعذرونا , سنضطر للغياب فترة كبيرة

الأمر ليس بيدنا ...... فسامحونا

#72

السلام عليكم

في نهاية دروس هذه الدورة المتواضعة , إليكم بعض المراجع التي قد تفيدكم في طريقكم إلى إحتراف السي شارب

_______________________________________

الدروس كاملة للتحميل في ملف واحد

http://www.7oma.com/csharp/Full.zip

_______________________________________

مراجع من ميكروسوفت :

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

هذه مجموعة من الدروس بالصوت والصورة

أمثلة لبرامج مفتوحة المصدر

بعض دروس How to

بعض المنتديات ومواقع المساعدة

_______________________________________

مواقع تعليمة مفيدة أخرى

http://www.csharpcorner.com/

http://www.codeproject.com/index.asp?cat=3

________________________________________

مجموعة كبيرة من دروس C#2005 بالفيديو

http://rapidshare.com/files/526446/AppDev....2005.part01.rar

http://rapidshare.com/files/526527/AppDev....2005.part02.rar

http://rapidshare.com/files/526604/AppDev....2005.part03.rar

http://rapidshare.com/files/526528/AppDev....2005.part04.rar

http://rapidshare.com/files/526551/AppDev....2005.part05.rar

http://rapidshare.com/files/526545/AppDev....2005.part06.rar

http://rapidshare.com/files/526564/AppDev....2005.part07.rar

http://rapidshare.com/files/526579/AppDev....2005.part08.rar

http://rapidshare.com/files/727775/AppDev....2005.part09.rar

http://rapidshare.com/files/526063/AppDev....2005.part10.rar

كلمة فك الضغط :

www.ebooksclan.org

________________________________________

مجموعة من الكتب في جميع مجالات البرمجة بالسي شارب

برمجة قواعد البيانات بالسي شارب

برمجة الويب بالسي شارب

برمجة الشبكات بإستخدام #C من CyBex

برمجة العميل/المخدم بالسي شارب

برمجة الألعاب بالسي شارب و XNA من ميكروسوفت

استخدام الADO.net مع ال #C باستخدام Oracle و SQL Server

هذه مجموعة قيمة جداً من الكتب من رفع الأخ supermario1980

http://rapidshare.com/files/30085111/C_Sharp_Books.rar.html

كلمة فك الضغط :

supermario1980

كتاب C# Tutorials و هو كتاب جيد يبدأ من Hello World حتى التعامل مع الUnmanaged و ال +COM

كتاب MCTS Self-Paced Training Kit - Microsoft .NET Framework 2.0 - Application Development Foundation

كلمة فك الضغط :

*4fjl%!75ds&

كتاب Programming Microsoft Visual C# 2005: The Language

كتاب مخصص لمبرمجين الـ Java والذين يودون الانتقال الى البرمجه بالـ #C.

________________________________________

بعض مراجع C#2003 - الرجاء الأخذ بالإعتبار بعض الإختلافات بينها وبين C#2005

مجموعة من الكتب العربية من رفع الأخ Black-Death

مجموعة من الدروس بالفيديو وبروابط مباشرة

http://www.gymnasiet.kungalv.se/programmer...o/2301/2301.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2302/2302.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2303/2303.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2304/2304.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2305/2305.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2306/2306.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2307/2307.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2308/2308.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2309/2309.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2310/2310.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2311/2311.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2312/2312.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2313/2313.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2314/2314.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2315/2315.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2320/2320.wmv

Codes

http://www.gymnasiet.kungalv.se/programmer...o/2321/2321.wmv

Codes

http://www.gymnasiet.kungalv.se/programmer...o/2330/2330.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2350/2350.wmv

http://www.gymnasiet.kungalv.se/programmer...o/2351/2351.wmv

Codes

http://www.gymnasiet.kungalv.se/programmer...o/2380/2380.wmv

________________________________________

7oma

حماة النهضة

إعذرونا , سنضطر للغياب فترة كبيرة

الأمر ليس بيدنا ...... فسامحونا

#73

السلام عليكم

الله يعطيك العافية أخ حماة النهضة على المشروع الجبار والله يجعله بصحيفة اعمالك

انا بديت هلأ بالمشروع وعندي سؤال بالدرس الخامس :

اقتباس
هناك مشكلة ستواجهنا هنا وهي في حالة إذا كان تركيز لوحة المفاتيح على زر محدد

فلن ينطلق حدث الضغط على النافذة , سينطلق الحدث على الزر المحدد فقط

والشفرة السابقة على النافذه الأساسية ,,,

الحل أن هناك صفة في النافذة تمكنها من إطلاق الحدث حتى ولو حصل في أي كائن من الكائنات

هذه الخاصية هي KeyPreview عدلها من False إلى True لتصبح كما في الصورة

انا ما فهمت شو يعني (هناك مشكلة ستواجهنا هنا وهي في حالة إذا كان تركيز لوحة المفاتيح على زر محدد

فلن ينطلق حدث الضغط على النافذة)؟؟

ولكم جزيل الشكر

#74
MHd.N.Nasser كتب:
السلام عليكم

الله يعطيك العافية أخ حماة النهضة على المشروع الجبار والله يجعله بصحيفة اعمالك

انا بديت هلأ بالمشروع وعندي سؤال بالدرس الخامس :

انا ما فهمت شو يعني (هناك مشكلة ستواجهنا هنا وهي في حالة إذا كان تركيز لوحة المفاتيح على زر محدد

فلن ينطلق حدث الضغط على النافذة)؟؟

ولكم جزيل الشكر

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

أهلاً بك أخي معنا

القصد في الجملة السابقة أن حدث الضغط على لوحة المفاتيح لن ينطلق

إذا كان تركيز لوحة المفاتيح على أي زر أو أداة أخرى في النافذة

بل سينطلق إلى الأداة المحددة وليس إلى النافذة , وكود الحدث مكتوب في حدث الضغط على النافذة وليس على الأداة

لذلك كان لا بد من تعديل الخاصية KeyPreview حتى يتم تمرير الحدث من الأداة إلى النافذة

ويتم تنفيذ كود إرجاع الشاشة إلى الحجم الطبيعي

وتركيز لوحة المفاتيح على أداة يعني أنها مهيئة لإستقبال أي مدخلات من لوحة المفاتيح

مثلاً مربع النص عند النقر عليه بزر الفارة , ينتقل التركيز إليه و يستقبل أي مدخلات من لوحة المفاتيح

والزر عند الإنتقال بزر TAB سيتحول محيطة إلى اللون الأزرق أو إلى مربع نقاط بمعنى أن التركيز إنتقل أليه

..

إعذرونا , سنضطر للغياب فترة كبيرة

الأمر ليس بيدنا ...... فسامحونا

#75

في الحقيقه اكتشفت الغلط ان الملف اكس ام ال كان فاضي وعشان كذا يعطيني مسج خطا ,,

لازم على الاقل يكون ملف الاكس ام ال يكون موجود بداخله الروت يوم حطيته ضبط واشتغل اوكيه

هذا الموضوع مغلق.

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…