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

كود API و مجموعة اسئلة عليه

مغلق
بدأه الاخير زمانه في 13 يوليو 2006 · 2 رد · 563 مشاهدة · في لغة C و ++C
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ..

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

الكود التالي (ولو شوي طويل ) مأخوذ من كتاب PETZOLDI في الفصل 20

(الاسئلة ضمن الكود)

MULTI2.C
/*---------------------------------------
   MULTI2.C -- Multitasking Demo
			   (c) Charles Petzold, 1998
  ---------------------------------------*/

#include <windows.h>
#include <math.h>
#include <process.h>

typedef struct
{
	 HWND hwnd;
	 int  cxClient;
	 int  cyClient;
	 int  cyChar; // ما الفائدة منه .. قراته بس ما فهمت ، في الكتاب يقول 
////   the height of a character


	 BOOL bKill; // وهذا ايضا ، في الكتاب يقول

//allows the creating thread to inform the created thread when it's //time to terminate itself.
}
PARAMS, *PPARAMS;

LRESULT APIENTRY WndProc (HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
					PSTR szCmdLine, int iCmdShow)
{

 /// هنا عملية تكوين النافذة و ما الى ذلك .. ماكو مشكلة

}

int CheckBottom (HWND hwnd, int cyClient, int cyChar, int iLine)
{
	 if (iLine * cyChar + cyChar > cyClient)
	 {
		  InvalidateRect (hwnd, NULL, TRUE);
		  UpdateWindow (hwnd);
		  iLine = 0;
	 }
	 return iLine;
}

// ------------------------------------------------
// Window 1: Display increasing sequence of numbers
// ------------------------------------------------

void Thread1 (PVOID pvoid)
{
	 HDC	 hdc;
	 int	 iNum = 0, iLine = 0;
	 PPARAMS pparams;
	 TCHAR   szBuffer[16];

	 pparams = (PPARAMS) pvoid; // ما الفائدة ؟؟

	 while (!pparams->bKill)
	 {
		  if (iNum < 0)
			   iNum = 0;

		  iLine = CheckBottom (pparams->hwnd,   pparams->cyClient,
							   pparams->cyChar, iLine);

		  hdc = GetDC (pparams->hwnd);

		  TextOut (hdc, 0, iLine * pparams->cyChar, szBuffer, 
				   wsprintf (szBuffer, TEXT ("%d"), iNum++));			   

		  ReleaseDC (pparams->hwnd, hdc);
		  iLine++;
	 }
	 _endthread ();
}

LRESULT APIENTRY WndProc1 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	 static PARAMS params;

	 switch (message)
	 {
	 case WM_CREATE:
		  params.hwnd = hwnd;
		  params.cyChar = HIWORD (GetDialogBaseUnits ());
		  _beginthread (Thread1, 0, ¶ms); //ما فائدة المتغير 
الثالث في دالة الثريد  ، ال msdn يقول 
  //  Argument list to be passed to new thread or NULL

		  return 0;

	 case WM_SIZE:
		  params.cyClient = HIWORD (lParam); // لماذا فقط  y ?
		  return 0;

	 case WM_DESTROY:
		  params.bKill = TRUE;
		  return 0;
	 }
	 return DefWindowProc (hwnd, message, wParam, lParam);
}

// ------------------------------------------------------
// Window 2: Display increasing sequence of prime numbers
// ------------------------------------------------------

void Thread2 (PVOID pvoid)
{
	 HDC	 hdc;
	 int	 iNum = 1, iLine = 0, i, iSqrt;
	 PPARAMS pparams;
	 TCHAR   szBuffer[16];

	 pparams = (PPARAMS) pvoid;

	 while (!pparams->bKill)
	 {
		  do
		  {
			   if (++iNum < 0)
					iNum = 0;

			   iSqrt = (int) sqrt (iNum);

			   for (i = 2; i <= iSqrt; i++)
					if (iNum % i == 0)
						 break;
		  }
		  while (i <= iSqrt);
		  iLine = CheckBottom (pparams->hwnd,   pparams->cyClient,
							   pparams->cyChar, iLine);

		  hdc = GetDC (pparams->hwnd);

		  TextOut (hdc, 0, iLine * pparams->cyChar, szBuffer, 
				   wsprintf (szBuffer, TEXT ("%d"), iNum));

		  ReleaseDC (pparams->hwnd, hdc);
		  iLine++;
	 }
	 _endthread ();
}

LRESULT APIENTRY WndProc2 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	 static PARAMS params;

	 switch (message)
	 {
	 case WM_CREATE:
		  params.hwnd = hwnd;
		  params.cyChar = HIWORD (GetDialogBaseUnits ());
		  _beginthread (Thread2, 0, ¶ms);
		  return 0;

	 case WM_SIZE:
		  params.cyClient = HIWORD (lParam); // فقط   y
		  return 0;

	 case WM_DESTROY:
		  params.bKill = TRUE;
		  return 0;
	 }
	 return DefWindowProc (hwnd, message, wParam, lParam);
}

// Window 3: Display increasing sequence of Fibonacci numbers
// ----------------------------------------------------------

void Thread3 (PVOID pvoid)
{
	 HDC	 hdc;
	 int	 iNum = 0, iNext = 1, iLine = 0, iTemp;
	 PPARAMS pparams;
	 TCHAR   szBuffer[16];

	 pparams = (PPARAMS) pvoid;

	 while (!pparams->bKill)
	 {
		  if (iNum < 0)
		  {
			   iNum  = 0;
			   iNext = 1;
		  }
		  iLine = CheckBottom (pparams->hwnd,   pparams->cyClient,
							   pparams->cyChar, iLine);

		  hdc = GetDC (pparams->hwnd);

		  TextOut (hdc, 0, iLine * pparams->cyChar, szBuffer, 
				   wsprintf (szBuffer, TEXT ("%d"), iNum));

		  ReleaseDC (pparams->hwnd, hdc);
		  iTemp  = iNum;
		  iNum   = iNext;
		  iNext += iTemp;
		  iLine++;
	 }
	 _endthread ();
}

LRESULT APIENTRY WndProc3 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	 static PARAMS params;

	 switch (message)
	 {
	 case WM_CREATE:
		  params.hwnd = hwnd;
		  params.cyChar = HIWORD (GetDialogBaseUnits ());
		  _beginthread (Thread3, 0, ¶ms);
		  return 0;
	 case WM_SIZE:
		  params.cyClient = HIWORD (lParam);	 //  فقط   y

		  return 0;

	 case WM_DESTROY:
		  params.bKill = TRUE;
		  return 0;
	 }
	 return DefWindowProc (hwnd, message, wParam, lParam);
}

// -----------------------------------------
// Window 4: Display circles of random radii
// -----------------------------------------

void Thread4 (PVOID pvoid)
{
	 HDC	 hdc;
	 int	 iDiameter;
	 PPARAMS pparams;

	 pparams = (PPARAMS) pvoid;

	 while (!pparams->bKill)
	 {
		  InvalidateRect (pparams->hwnd, NULL, TRUE);
		  UpdateWindow (pparams->hwnd);

		  iDiameter = rand() % (max (1,
								min (pparams->cxClient, pparams->cyClient)));

		  hdc = GetDC (pparams->hwnd);

		  Ellipse (hdc, (pparams->cxClient - iDiameter) / 2,
						(pparams->cyClient - iDiameter) / 2,
						(pparams->cxClient + iDiameter) / 2,
						(pparams->cyClient + iDiameter) / 2);

		  ReleaseDC (pparams->hwnd, hdc);
	 }
	 _endthread ();
}
LRESULT APIENTRY WndProc4 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	 static PARAMS params;

	 switch (message)
	 {
	 case WM_CREATE:
		  params.hwnd = hwnd;
		  params.cyChar = HIWORD (GetDialogBaseUnits ());
		  _beginthread (Thread4, 0, ¶ms);
		  return 0;

	 case WM_SIZE:
		  params.cxClient = LOWORD (lParam); //   لماذا هنا  y , x 
		  params.cyClient = HIWORD (lParam);  // 
		  return 0;

	 case WM_DESTROY:
		  params.bKill = TRUE;
		  return 0;
	 }
	 return DefWindowProc (hwnd, message, wParam, lParam);
}

// -----------------------------------
// Main window to create child windows
// -----------------------------------

LRESULT APIENTRY WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	 static HWND	hwndChild[4];
	 static TCHAR * szChildClass[] = { TEXT ("Child1"), TEXT ("Child2"),
									   TEXT ("Child3"), TEXT ("Child4") };
	 static WNDPROC ChildProc[] = { WndProc1, WndProc2, WndProc3, WndProc4 };
	 HINSTANCE	  hInstance;
	 int			i, cxClient, cyClient;
	 WNDCLASS	   wndclass;

	 switch (message)
	 {
	 case WM_CREATE:
		  hInstance = (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE);
		  wndclass.style		 = CS_HREDRAW | CS_VREDRAW;
		  wndclass.cbClsExtra	= 0;
		  wndclass.cbWndExtra	= 0;
		  wndclass.hInstance	 = hInstance;
		  wndclass.hIcon		 = NULL;
		  wndclass.hCursor	   = LoadCursor (NULL, IDC_ARROW);
		  wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
		  wndclass.lpszMenuName  = NULL;

		  for (i = 0; i < 4; i++)
		  {
			   wndclass.lpfnWndProc   = ChildProc;
			   wndclass.lpszClassName = szChildClass;

			   RegisterClass (&wndclass);

			   hwndChild = CreateWindow (szChildClass, NULL,
								   WS_CHILDWINDOW | WS_BORDER | WS_VISIBLE,
								   0, 0, 0, 0, 
								   hwnd, (HMENU) i, hInstance, NULL);
		  }

		  return 0;

	 case WM_SIZE:
		  cxClient = LOWORD (lParam);
		  cyClient = HIWORD (lParam);

		  for (i = 0; i < 4; i++)
			   MoveWindow (hwndChild, (i % 2) * cxClient / 2,
										 (i > 1) * cyClient / 2,
						   cxClient / 2, cyClient / 2, TRUE);
لماذا عند حذف هذه الدالة (اقصد movewindow) لا يظهر شيء ؟؟؟

		  return 0;

	 case WM_CHAR:
		  if (wParam == `\x1B')
			   DestroyWindow (hwnd);

		  return 0;

	 case WM_DESTROY:
		  PostQuitMessage (0);
		  return 0;
	 }
	 return DefWindowProc (hwnd, message, wParam, lParam);
}

و في الثريد ما الفرق بين الدالة المستخدمة في البرنامج السابق وهي _beginthread و بين CreateThread ؟؟

اخيرا ...

ما المقصود ب

_beginthread returns –1 on an error, in which case errno is set to EAGAIN if there are too many threads, or to EINVAL if the argument is invalid or the stack size is incorrect.

/index.php/topic/264448-%D8%A7%D9%84%D8%A8%D8%AF%D8%A7%D9%8A%D8%A9-%D9%85%D8%B9-%D8%A7%D9%84%D8%A7%D9%86%D8%AF%D8%B1%D9%88%D9%8A%D8%AF/

 

اني وان كنت الاخير زمانه ---- لأتِ بما لم تستطعه الاوائلُ

#2

السلام عليكم

اسئلة ممتازة وتستاهل عليها إجابات وافية

السؤال الاول:

ما فائدة cyChar

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

TextOut (hdc, 0, iLine * cyChar, szBuffer, 
				   wsprintf (szBuffer, TEXT ("%d"), iNum++));

الدالة الثانية والثالثة هى المكان الذى سيتم فى كتابة السطر الجديد... وهذه التقنية تسمى scrolling text::

السؤال الثاني:

ما فائدة bKill

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

إليك الشفرة التى تتحقق من ذلك..

while (!pparams->bKill)

إذا كان الthread مازال يعمل افعل كذا وكذا الخ,, اما إذا انتهت صلاحيته فعليك بإستدعاء الدالة _endthread:

السؤال الثالث

الدالة pvoid هى التى نحصل عليها عندما نقوم بتاسيس النافذة وهى التى تحتوى على معلومات عن الThread.

هناك 4 عناصر فى pvoid وهى الطول والعرض, اخر سطر فى النافذة , وحالة الthread ما إذا كان مازال يعمل ام تم القضاء عليه..

السؤال الرابع:

الthread ما هو إلا دالة مثلها مثل اى دالة, لنفرض انك قمت بعمل thread يقوم بعملية حسابية معقدة ولكنك تريد ان ترسل له القيمة الابتدائية لهذه العملية, الطريقة الوحيدة هى ان ترسل المتغير عبر param, وإذا كانت تريد إرسال اكثر من متغير فإنك ترسل عنوان الذاكرة الذى تحفظ فية المتغيرات..

السؤال الخامس:

لماذا فقط y ؟ لان المؤالف يريد ان يغير حجم النافذة فى الطول فقط واعتقد لو انك حاولت تغير عرض النافذة فلن تستطيع لان البرنامج يتجاهلها تماماً

السؤال السادس:

لماذا x و y ؟ لان المؤالف الظاهر انه قرر ان احد هذه الthreads يمكنها تغير حجمها بالطول والعرض فى حين البقية مسموح لهم فقط تغير الطول..

السؤال السابع:

لماذا لا يظهر شئ عند حذف الدالة؟ الظاهر ان هذه الطالة هى التى تضع اشياء فى النافذة الرئيسية, حذفها لا يعنى ان كل شئ اختفى ولكن جميع الthreads التى تم إنشائها تعمل فى الخلفية كل ما هنالك هو انك لا ترى الناتج فى النافذة الام..

السؤال الثامن:

الفرق بين الدالتين هو ان الدالة _beginthread اسهل فى الاستخدام لانها لا تحتوى على جميع المتغيرات التى تحتوية الدالة CreatThread ولكن إذا اردت استخدام إمكانيات اضافية فى هذه الحالة يفضل ان تستخدم الثانية..

السؤال الاخير:

كل دالة فى الوندوز إذا فشلت فهى تعيد رقم معين لتخبر المستخدم سبب الفشل, فى هذه الحالة EAGAIN ما هى إلى constant يحمل الرقم 11 وتعني ان هناك عدد كبير جداً من الThreads لذلك لم يتمكن نظام التشغيل من إنشاء thread جديد.. اما الدالة EINVAL فهى constant يعبر عن الرقم 22 ويعني ان هناك خلل فى المتغيرات المرسلة للدالة التى تقوم بإنشاء الThread:::

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

لا إله إلا الله محمد رسول الله

busbar : يجب ان تدرك انه هناك حد ادنى للمعرفة المطلوبة قبل البدء في عمل أي شئ.

#3

السلام عليكم ..

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

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

ولو في شي راح ارجع مرة اخرى ..

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

/index.php/topic/264448-%D8%A7%D9%84%D8%A8%D8%AF%D8%A7%D9%8A%D8%A9-%D9%85%D8%B9-%D8%A7%D9%84%D8%A7%D9%86%D8%AF%D8%B1%D9%88%D9%8A%D8%AF/

 

اني وان كنت الاخير زمانه ---- لأتِ بما لم تستطعه الاوائلُ

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

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