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

مؤقت

مغلق
بدأه *net* في 28 ديسمبر 2006 · 15 رد · 1,275 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

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

لدي مشروع - جامعي - مطلوب عمله بواجهة رسومية ولا أعرف سوى MFC بشكل بدائي نوعا ما ..

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

هل يوجد" فنكشن " timer مثلا ؟؟ تفي بالغرض؟؟؟

هل من يد عون ؟؟؟؟

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

أختكم *net *

#3

شكرا لمرورك أخ

b.m.s

فعلا وجدت مواضيع كثيييرة مشابهة ,, لكن لا أعرف كيفية الاستفادة منها لأن خلفيتي بسيطة في MFC

أتمنى ممن يعرف شيء أن لا يبخل عليّ به ,,

تم تعديل هذه المشاركة بواسطة *net* في 28 ديسمبر 2006 في 19:04

#4

سلام عليكم

ساحاول التوضيح ببساطة و ارجو إلتماس العذر

كل نافذة(Window) لها القدرة على التعامل مع اكثر من مؤقت(Timer) كل منهم يميز برقم(ID) و لنقل 1 و 2 هما ID مؤقتان فى صندوق حوار.

يجب تحديد زمن كل Timer و كذلك ماذا يفعل. فى خطوة ماذا يفعل المفروض يستدعى دالة ما.

و يتم تحديد التعامل لكل Timers فى نفس الدالة التى تعالج WM_TIMER و لعمل ذلك فى MFC اضغط يمين على اسم الكلاس فى workspace. و اختار Add Window Message Handler و من الداخل اختر WM_TIMER.

ستنتج دالة اسمها( OnTimer( UINT nIDEvent و المعطى الوحيد هو رقم Timer.

و هذا مثال للمعالجة

void CTestMFCDlg::OnTimer( UINT nIDEvent ) 
{
	switch (nIDEvent){
	case 1:// Timer 1 is fired
		SetText(); 
		break;
	case 2: // Timer 2 is fired
		AfxMessageBox("r u tired");
		break;
	}

	CDialog::OnTimer(nIDEvent);
}

يعنى Timer1 سيستدعى دالة و الثانى سيظهر رسالة. تحتاج الان لتشغيل و ايقاف Timer. انا حافترض ان ذلك سيتم من خلال زرارين للبداية و النهاية.

و هذا مثال للمعالجة

void CTestMFCDlg::OnStart() 
{
	SetTimer(1, 2000, 0);
}

void CTestMFCDlg::OnEnd() 
{
	KillTimer(1);
}

و بالتالى فاضل الدالةSetText و هذه يجب ان تؤدى بشكل مختلف كل مرة. يعنى كل مرة صورة و اى رسال. انا هنا اخترت تغير خمس رسائل بشكل دورى.

و هذا مثال للمعالجة

void CTestMFCDlg::SetText()
{
	static int i=0;
	CString msgs[5];
	msgs[0] = "Hi Msg 1";
	msgs[1] = "It is me Msg2";
	msgs[2] = "The middel Msg";
	msgs[3] = "Befor lass Mg ??";
	msgs[4] = "Good bye";

	strmsg = msgs[i++];
	i = i>4? 0:i;

	UpdateData(FALSE);	
}

ستجد نسجة من هذا الكلام فى المرفقات.

ارجو ان اكون اوضحت شئ.

TestMFC.zip

#5

حقيقة عاااااااااااااااااجزة عن شكرك أخ PointerVC

ولا أقول إلا جزااااك الله ألف ألف ألف خير ,,

أتمنى أن تتحمّلني , في حال احتجت لمزيد من التوضيح..

أكرر شكري وامتناني لك ,,

#6

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

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

البرنامج مرفق وسأعرض هنا فكرة مبسطة لعمله ,,

في البداية يجب أن أقوم بتعبئة الأرري ب 3 عناصر فقط من الملف - كل سطر في الملف يمثل معلومات عنصر واحد فقط..

الرقم الأول في الملف يمثل عدد مرات طباعة جملة معينة ولتكن مثلا " Hi, Im MSG1"

أما الأرقام التي تلي هذا الرقم فتعني الوقت الذي تقضيه الجملة السابقة ثم تمسح

بين كل جملتين من Hi, Im MSG1" يجب أن تطبع جملة أخرى ولتكن " Hi ,Im MSG2" لمدة 10 ثوان دائما

بالتالي عدد مرات طباعة الجملة الثانية دائما يساوي عدد مرات طباعة الجملة الأولى - 1

هذه المعالجة ( الطباعة ) ستكون فقط على أول عنصر في الأرري بالتالي سأقوم بعمل shift للأرري ومن ثم قراء معلومات عنصر آخر من الملف وتخزين معلومات في الخانة الأخيرة من الأرري والتي تحمل الإندكس رقم 2 إذا كان هناك مزيدا من السطور لم تعالج..

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

فرضا لو كان الملف يحتوي القيم التالية :

3 4 5 3

2 7 4

5 2 5 3 6 4

2 9 3

3 5 6 9

فالسطر الأول مثلا يحوي 3 4 5 3

سيطبع "Hi I'm in MSG1 " ثلاث مرات أما " Hi I'm in MSG 2 مرتين

" Hi, I'm IN MSG1" ------> لمدة 4 ثوانِ

" Hi, I'm in MSG2" ------> لمدة 10 ثوان

" Hi, I'm IN MSG1 ------> لمدة 5 ثوان

" Hi, I'm in MSG2" ------> لمدة 10 ثوان

" Hi, I'm IN MSG1------> لمدة 3 ثوان

وهكذا لبقية السطور ...

استخدمت ال Timer ,, لكني أجزم أني لم أتقن استخدامه ,, مع أني حاولت وحاولت وحاولت لكن للأسف كل محاولتي بااااءت بالفشل

الناتج الذي كان يظهر لي

هو أن الرسالة MSG1 تطبع لمدة 9 ثوانٍ وهو آخر عدد في آخر سطر .. بالتزامن مع طباعة الرسالة MSG2 !!!

أما العناصر الأولى كلها والتي تستلزم طباعة MSG 1 لوقت محدد تهمل جيمعها !!

مدوا لي يد العون لا حرمكم الله الأجر ...

MyTimer.rar

#7

للرفع ..

#8

سلام عليكم

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

اى اسئلة نفكر معاً و السلام

ArabTeam.zip

#9

جزيت خيرا يا أخي الكريم

PointerVC

على تفاعلك .. لا حرمك الله الأجر.. وشكرااا جزيلا على المثال التوضيحي سأحاول فهمه لعلي استطيع الاستفادة منه ويبدو أن له من اسمك نصيب :)

سأوضح عمل المتغيرات و الدوال أكثر :

أولا المتغيرات

***********************************

Itemcounter

هو عبارة عن عدّاد للعناصر

بحيث يُزاد إذا قرأت عنصر من الملف ويُنقص إذا انتهيت من معالجة عنصر ما

مع ملاحظة أن عملية المعالجة هذه هي عبارة عن عمليات الطباعة المتناوبة للرسالتينHi I'm MSG 1

و

Hi I'm MSG 2 بالأوقات المعطاة في الملف

************************************

Array

هو أرري يحمل معلومات العناصر وهذا الأرري هو من نوع

info

والذي يشمل

NumOfMSG1 ----> وأعني بها عدد المرات التي ستطبع فيها الرسالة MSG1

TimesForMSG1---->وأعني بها الوقت بالثواني الذي ستطبع في الرسالة MSG1 كل مرة

أما الرسالة 2 فدائما عدد مرات طباعتها هو عدد مرات طباعة رسالةMSG1 -1

ووقتها ثابت دائما هو 10 ثوان

مع ملاحظة أن الأرري لا يمكن أن يحمل أكثر من 3 عناصر

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

ولذلك فإني أعالج فقط العنصر في الخانة 0 وأعمل

Shift

لعناصر الأرري وأنقص

ItemCounter

ثم إن كان الملف يحوي مزيدا من العناصر أقرأه وأخزن معلوماته في الخانة الأخيرة (رقم 2 ) وأزيد

Itemcounter

*************************************************ثانيا الدوال

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

الدالة OnRun()تستدعي في بدايتها

FillArray()

والتي تقوم بتعبئة الأرري بأول ثلاث عناصر من الملف

مع ملاحظة أنها تقوم بزيادة العداد

Itemcounter

في كل مرة تقرأ من الملف

أكمل الآن عمل

OnRun

بعد تعبئة الأرري ,, يوجد تكرار

(LOOP)

شرطه أن

Itemcounter !=0

بمعنى أن هناك عناصر في الأرري لم يتم معالجتها

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

DisplayMSG()

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

عمل الدالة

DisplayMSG()

تقوم بعملية الطباعة لأول عنصر في الأرري فقط

فمثلا لو كانت معلومات العنصر الأول هي

3 4 5 3

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

وهنا إعادة لما ذكرت - للسهولة في القراءة :)

سيطبع "Hi I'm in MSG1 " ثلاث مرات أما " Hi I'm in MSG 2 مرتين

" Hi, I'm IN MSG1" ------> لمدة 4 ثوانِ

" Hi, I'm in MSG2" ------> لمدة 10 ثوان

" Hi, I'm IN MSG1 ------> لمدة 5 ثوان

" Hi, I'm in MSG2" ------> لمدة 10 ثوان

" Hi, I'm IN MSG1 ------> لمدة 3 ثوان

وهنا قمت باستدعاء

SetTimer(1...) لطباعة الجملة الأولى

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

و SetTimer (2...)

لطباعة الجملة الثانية

السبب في أني أعالج فقط أول عنصر هو أني في البرنامج الأصلي أحتاج لذلك،،

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

هنا تأتي فائدة دالة أخرى تستدعى في نهاية الدالة

DislpayMSG

هي

DeletInsert()

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

عمل DleteInsert()

تنقص

Itemcounter ----> بمعنى أنه عولج

تقوم بعملية

shift أقصد بذلك تقديم عناصر الأرري

أي العنصر 1 يحل مكان 0

و العنصر 2 يحل مكان 1

تقوم بالقراءة من الملف لعنصر واحد فقط وتخزينه في

الخانة الأخيرة للأرري

وطبعا عند القراءة من الملف يُزاد المتغير

Itemcounter

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

أما الدالتان

PrintMSG1(),PrintMSG2()

يتم فيها الطباعة للرسالتين

بحيث أنه يتم "قتل" المؤقت فيهما

حيث أني عرفت متغيرين ستاتيك static في بداية البرنامج global

واحد خاص بالدالة الأولى ويسمىTimerForMSG1

والآخر خاص بالدالة الثانية ويسمى TimerForMSG2

كل مرة تستدعى الدالة

printMSG1()

ينقص هذا المتغير الستاتيك TimerForMSG1

وعندما يصل إلى الصفر يقتل المؤقت!!

مع العلم أنه أعطيه قيمة ابتدائية في قبل استدعاء

SetTimer(1...)

أتمنى أن أكون قد أوضحت ما أقصده ,, و آآآآسفة جدا على الإطالة ,,

تم تعديل هذه المشاركة بواسطة *net* في 1 يناير 2007 في 19:03

#10

أخ PointerVC ,, تتبعت برنامجك , ووجدت فيه الاحتراف - ماشاء الله - في استخدام المؤقتات والمؤشرات ..

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

و بقي الاختلاف في Timer

بالنسبة لي ,, كنت أضع المؤقت داخل التكرار بحيث يطلق كل ثانية , وأعطي المتغير TimerForMSG1 - قبل إطلاق المؤقت - القيمة التي أريد أن تبقى فيه طباعة ال MSG1 بحيث أنه يتم تنقيصه إلى أن يصل إلى الصفر ,, وإذا وصل إلى الصفر " يقتل"!!

والسبب أني جعلته كل ثانية حتى أضرب عصفورين بحجر - لكن يبدو أني لم أفلح وللأسف الشديد فهذه المرة الأولى التي أتعامل فيها مع المؤقتات - حتى أبقي الرسالة الأولى للمدة المعينة , إضافة إلى ذلك أطبع (شبيه) بالساعة تتناقص كل ثانية ....

أعتقد أنه منطقي نوعاً ما لكن لا أدري لماذا التكرار يمر مرّ السحاب ,, فقد وضعت MessageBox()

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

وMessageBox() آخر في نهاية التكرار الموجود في الدالة() DisplayMSG.. أي بعد الانتهاء من معالجة كل رقم في السطر الواحد

فوجدت أنه فعلا تعمل المؤقتات بشكل صحيح لكنها تمرّ بسررررررررررعة ...بدليل أن هذه الmessagebox كانت تنتظر انتهاء العد ومن ثم تكمل بينما بدونها ينجز التكرار بشكل سريع .. لكن حتى باستخدام الmessageBox ظلت مشكلة التزامن للمؤقتين موجودة ..

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

بمعنى هل المؤقتات لا يمكن أن تعمل داخل التكراربشكل صحيح كما فعلت أنا ؟؟؟

و لك خالص الشكر والامتنان...

تم تعديل هذه المشاركة بواسطة *net* في 1 يناير 2007 في 23:51

#11

سلام عليكم

اشكرك على التوضيح و الكلمات الطيبة.

طبعاً استخدام الحلقات ممكن جداً. و إن كنت لم ادرك العصفورين. بعدد مراجعة سريعة. البرنامج يبدو سليم لكن اظن التكرارينن داخل DisplayMSG() محتاجين اقواس. لان SetTimer(1,1000,0); تعمل مرة واحدة. يعنى كل رسالة ستستمر 1 ثانية بغض النظر عن الزمن المطلوب.

الشكل العام للدالة سيكون

void CMyTimerDlg::DisplayMSG()
{
	int counter = 0;

	while(counter<Array[0].NumOfMSG1)
	{
		for ( int i =0; i< Array[0].TimesForMSG1[counter]; i++ ) { //-> added {
		// print message1 for  TimesForMSG1 sec then erase it..



			SetTimer(1,1000,0);

			if ( counter != Array[0].NumOfMSG1 - 1 ) { 
				for ( int i =0; i<10; i++ ) {  //-> added{
				 // print message 2 for 10 sec then erase it..
					TimerForMSG2 = 10;
					SetTimer(2,1000,0);
				} //-> Added}
			}
		counter ++;		
		}	//-> added}
	}

طبعاً اظهار الرسائل سيكون محتاج تعديل.

اتمنى ان يكون ذلك مفيداً

#12
PointerVC كتب:
سلام عليكم

اشكرك على التوضيح و الكلمات الطيبة.

طبعاً استخدام الحلقات ممكن جداً. و إن كنت لم ادرك العصفورين. بعدد مراجعة سريعة. البرنامج يبدو سليم لكن اظن التكرارينن داخل DisplayMSG() محتاجين اقواس. لان SetTimer(1,1000,0); تعمل مرة واحدة. يعنى كل رسالة ستستمر 1 ثانية بغض النظر عن الزمن المطلوب.

الشكل العام للدالة سيكون

void CMyTimerDlg::DisplayMSG()
{
	int counter = 0;

	while(counter<Array[0].NumOfMSG1)
	{
		for ( int i =0; i< Array[0].TimesForMSG1[counter]; i++ ) { //-> added {
		// print message1 for  TimesForMSG1 sec then erase it..
			SetTimer(1,1000,0);

			if ( counter != Array[0].NumOfMSG1 - 1 ) { 
				for ( int i =0; i<10; i++ ) {  //-> added{
				 // print message 2 for 10 sec then erase it..
					TimerForMSG2 = 10;
					SetTimer(2,1000,0);
				} //-> Added}
			}
		counter ++;		
		}	//-> added}
	}

طبعاً اظهار الرسائل سيكون محتاج تعديل.

اتمنى ان يكون ذلك مفيداً

اعتذر عن هذا الرد فقد اسئت الفهم. ساضيف رد آخر فيما بعد

سلام عليكم

#13

سلام عليكم

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

هذه الدالة تستهلك وقت لمدة معينة بالثوان.

void CMyTimerDlg::wait(time_t t)
{
	time_t start_time, cur_time;
	time(&start_time);
	do{
		time(&cur_time);
	}while((cur_time - start_time) < t);
}

انا ادمجتها فى لبرنامج و لغيت الطريقة السابقة.

و كده يكون هنا حل ب Timer و اخر بدونه.

اما فكرة الحلقات +Timer ارجو المعذرة

شكراً لتفهمك

void CMyTimerDlg::OnRun() 
{
	// TODO: Add your control notification handler code here

	FillArray();
	DisplayMSG();

}

void CMyTimerDlg::DisplayMSG( )
{
	int counter = 0;
	while(Itemcounter !=0){ // Array still have items, it has 3 items at most
		while(counter<Array[0].NumOfMSG1){
			TimerForMSG1 =Array[0].TimesForMSG1[counter];
			GetDlgItem(IDC_Timer1)->EnableWindow(TRUE);
			GetDlgItem(IDC_MSG1)->EnableWindow(TRUE);
			GetDlgItem(IDC_Timer2)->EnableWindow(FALSE);
			GetDlgItem(IDC_MSG2)->EnableWindow(FALSE);
			while (TimerForMSG1){
				PrintMSG1();
				wait(1);
				TimerForMSG1 --;
			}
			counter++;

			GetDlgItem(IDC_Timer1)->EnableWindow(FALSE);
			GetDlgItem(IDC_MSG1)->EnableWindow(FALSE);
			GetDlgItem(IDC_Timer2)->EnableWindow(TRUE);
			GetDlgItem(IDC_MSG2)->EnableWindow(TRUE);

			TimerForMSG2 = 1; // to be 10
			while (TimerForMSG2){
				PrintMSG2();
				wait(1);
				TimerForMSG2 --;
			}
		}
		DeleteInsert();
	}
	output<<"NumOfMSG1 :"<<Array[0].NumOfMSG1<<"is read..\n";

}

void CMyTimerDlg::PrintMSG1()
{
	m_Timer1 = itoa(TimerForMSG1,temp,10);
	m_MSG1 = "Hi,, I'm MSG1";
	UpdateData(FALSE);
}

void CMyTimerDlg::PrintMSG2()
{
	m_Timer2 = itoa(TimerForMSG2,temp,10);
	m_MSG2 = "Hi,, I'm MSG2!";
	UpdateData(FALSE);
}

void CMyTimerDlg::wait(time_t t)
{
	time_t start_time, cur_time;
	time(&start_time);
	do{
		time(&cur_time);
	}while((cur_time - start_time) < t);
}

و يبدو ان DeleteInsert لا تعمل بشكل كامل(غير واثق)

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

#14

مرحبا..

أعتذر عن التأخر في الرد فيما يتعلق ب

wait

نظرا لظروف الدراسة,,

جربتها وكانت نتائجها غريبة , ففي كل مرة يتم تشغيل البرنامج يتوقف في لحظة ما تختلف عن سابقتها !!

وبما أن الوقت المتاح لنا مدد لفترة قصيرة , حاولت جاهدة اقتباس الفكرة التي عملت أنت بها المؤقتات وكانت ناجحة الحمدلله

إلا أني انتبهت مؤخرا في كلا البرنامجين أن الرسالة 2 تطبع بعد كل رسالة 1

والمفروض أنها تطبع بين كل رسالتين من 1 بمعنى لو كان عدد رسائل 1 هي 1 فإن الرسالة 2 لا تطبع

ولو كان عدد مرات طباعة الرسالة 1 هي 2 فإن الرسالة 2 تطبع ولمرة واحدة فقط بين الرسالتين 1

بشكل عام

عدد مرات طباعة الرسالة 2= عدد مرات طباعة 1 -1

حاولت لكن المشكلة كان يظهر لي

garbage !!

مرفق البرنامج مع المؤقت الجديد,,فمن حق الاستاذ أن يرى واجب طالبه ويصححه إذا لزم الأمر :)

Copy_of_MyTimer.rar

تم تعديل هذه المشاركة بواسطة *net* في 8 يناير 2007 في 01:08

#15

UP

#16

السلام عليكم

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

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

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