انشاء نافذة من نوع SDI
الجزء الثاني:الان انشئ مشروع جديد كما فعلنا في الدرس الاول ...
اضف هذا الكود :
#include <windows.h>
وهذا تم شرحه ..
اضف هذه الدالة ..
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
هنا نعلن عن الدالة التي نريد ان نستخدمها لاحقا ..
كما تعلم حتى نستخدم الدالة بشكل صحيح يجب الاعلان عن الدالة اولا اذا كنت تريد ان تكتب محتوياتها بعد الدالة الرئيسية WinMain
حتى لا يتشوش ذهنك تذكر مثلا
Int func();
Main()
{
}
Int func()
{
Cout<<"hello";
}
ما فعلناه مع السي العادية نفعله مع دوال الويندوز لاننا في عالم السي
-----
نعود لدالتنا .. هذه الدالة سأشرحها بعد قليل ...
الان الصق الكود التالي :
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
لاتخاف ...
اولا انشأنا تركيب جديد من نوع WNDCLASS ، واسميناه wc وتستطيع تسميته كما تريد ..
هذا التركيب هو القاعدة الاساسية للنافذة التي سننشئها بعد قليل ان شاء الله .
نستفيد من هذا التركيب في تحميل الايقونة الخاصة بنافذتنا .. التحكم بلون خلفية النافذة وغير ذلك .. ونحدد الخصائص كالتالي ..
wc.style = 0;
الستايل العام... وضعه صفر الان ..
wc.lpfnWndProc = WndProc;
مهم...وهواسم دالة الرسائل..الدالة التي تتحكم بالرسائل ... طبعا تسميها كما تريد
wc.cbClsExtra = 0;
غالبا صفر
wc.cbWndExtra = 0;
غالبا صفر
ماسبق غير مهم حاليا .. وهو خاص بذاكرة البرنامج .. هل تحجز له ذاكرة اضافية ... يعني حول هذا المعنى ..
wc.hInstance = hInstance
اسم مقبض الفئة ( او نقول برنامجنا ) وهو مهم للغاية; لاحظ ان hInstance هو نفسه الذي اعلنا عنه في الدالة الرئيسية
WinMain(HINSTANCE hInstance,......
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
ايقونة البرنامج ... لكن كيف نعين الايقونة ...
عن طريق الدالة LoadIcon...
IDI_APPLICATION :: هذا يدل على نوع الايقونة تستطيع تغير نوعهاو تختار مارتريد مثلا
IDI_QUESTIONقد تسأل سؤال وتقول كيف احمل ايقونتي الخاصة بدلا من هذه الثوابت ..
ستعرف الجواب في دروس قادمة بإذن الله .
لكن لاحظ بادئة الثابت
ID
ثم اول حرف من كلمة ICON
I
ثم
_
ثم
اسم الايقونة التي تريد .....
لاحظ ان الايقونة هي معرفة كرقم
#define IDI_APPLICATION 32512
ولكن بدل من حفظ الرقم .. قام مبرمجي الويندوز بوضع ثوابت للتسهيل .
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
مؤشر الفأرة ونحصل عليه باستخدام الدالة
LoadCursorنضع اسم المؤشر وليكن
IDC_ARROWوتستطيع استخدام مؤشرات اخرى مثلا
IDC_WAITوتستطيع وضع مؤشر خاص بك ترسمه بنفسك او تستورده ... ستعرف كيف ذلك بالدروس القادمة ان شاء الله .
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
لون خلفية النافذة .. غير الرقم واحد باي رقم من واحد الى 26 على ما اعتقد .. جرب وستخرج لك الوان جديدة لكن لاتتعدى 26 ... والا ..
وهناك طريقة اخرى لتعيين لون للخلفية هكذا .
wc.hbrBackground = (HBRUSH) GetStockObject( WHITE_BRUSH );
وهي باستخدام الدالة
GetStockObject.. وغير الثابت الداخلي .. بثوابت اخرى مثلا
BLACK_BRUSH
GRAY_BRUSH
DKGRAY_BRUSHاعرف ان هناك بعض الاشياء التي لم تفهمها مثلا HBRUSH،،،، GetStockObject ونحوها لكن ان شاء الله بالدروس الجاية رح تفهمها لانها متقدمة نوع ما ..
wc.lpszMenuName = NULL;
هل تريد قائمة ... لان لانريد اذن وضعنا NULL
wc.lpszClassName = " arab team ";
مهم .. اسم الفئة وهو نص .. اكتب ماتريد .
خلاص .. الان انتهينا عينا الخصائص ... وبقي شي واحد وهو تسجيل الفئة لكن كيف ؟
هكذا ..
RegisterClass(&wc);
ولاحظ الدالة .. فهي تسجل الفئة وتطلب بارمتر واحد وهو الفئة ... طبعا تمرر العنوان .. لان البارمتر مؤشر .اذا نمرر له عنوان
------
هل توجد صعوبة ؟؟؟
قد يكون الكود كثير لكن مع كثرة الكتابة ستسهل ان شاء لله ..
الان خلصنا من الفئة ...
ننتقل الى النافذة ..
الصق هذا الكود
HWND hwnd;
hwnd = CreateWindow(
" arab team ",
"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
الامر يحتاج الى تركيز ...
اولا انشأنا مقبض نافذة جديد وهو مهم لاننا نريد انشاء نافذة , وكما قلنا لكل نافذة مقبض .. حتى يميز النظام بين النوافذ.. لانشاء مقبض نافذة نكتب
HWND hwnd;
لاحظ حرف H
في
HWNDوهو يعني مقبض أي HANDLE
وهناك انواع اخرى من المقابض مثلا ، مقبض الفرشاة .. ومقبض الصورة وغيرها ،،،،
اما WND فهي اختصار وتعني نافذة WINDOW
...
الان ننشئ النافذة عن طريق الدالة الشهيرة ..
CreateWindow ولكن لاننسى اسناد مقبض النافذة بالدالة CreateWindow
حيث ان الدالة CreateWindow تنشئ النافذة وتعيد قيمة النافذة .. هذا القيمة نسندها للمقبض الذي انشأناه hwnd
هكذا
hwnd = CreateWindow(
الان ندخل الى تفاصيل الدالة :
البارمتر الاول : هو اسم التركيب الذي انشأته
wc.lpszClassName = " arab team ";
االثاني : هو اسم النافذة وهو الذي يظهر على شريط العنوان العلوي
الثالث : الستايل العام للنافذة.. الحدود زر التكبير والتصغير وغيرها .. اخترنا
WS_OVERLAPPEDWINDOWCW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
هذه تعين موقع النافذة واخترنا الموقع الافتراضي "" السيني والصادي"" CW_USEDEFAULT, CW_USEDEFAULT
و 240 و 120 هي طول وعرض النافذة
بعد ذلك وضعنا NULL حيث يطلب هذا البارمتر ما يسمى بـ
hWndParentويعني هل النافذة اب او ابنة.. وهنا نافذتنا الاب وبالتالي نضع NULL
التاسع: بم ان برنامجنا لايحتوي على قائمة وضعنا NULL
والبارمتر قبل الاخير وضعنا اسم مقبض البرنامج hInstance
والاخير NULL غالبا ..
------
الان نظهر النافذة عن طريق الدالة
ShowWindow(hwnd, nCmdShow);
لاحظ الدالة .. تريد منك بارمترين .. الاول .. مقبض النافذة التي تريد اظهارها .. الثاني تستخدم البارمتر الذي وضعته في الدالة الرئيسية ...
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
ثم نحدث النافذة
UpdateWindow(hwnd);
الان انتهينا .... انشأنا الفئة ( سجلنا الفئة) ثم صنعنا نافذة .. أظهرناها وحدثناها ..
الخطوة القادمة
الخطوة الثالثة دوامة الرسائل
ماهي الرسائل
نقرة الماوس او تحريكها
ضغطة الكيبورد
تحريك النافذة او تصغيرها ونحو ذلك
وغيرها من الرسائل
---
فنحن ننتظر اي رسالة ترد الى النافذة لذا نضعها في دوامة التكرار ..
ولكن قبل ذلك نحن ننشئ فئة(او structure)
للرسائل هكذا
MSG Msg;
وسمها ماتريد..
الصق هذا الكود ..
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
اولا نقول ..
مادام برنامجنا يستقبل الرسائل (( ونعرف ذلك عن طريق الدالة
GetMessage)) فقم بما يأتي :
TranslateMessage(&Msg);
تعرف يا ويندوز على الرسالة ..
ثم
DispatchMessage(&Msg);
ارسلها الى من يهمه الامر(( الى دوال تفسير الرسائل ))
تلك الصيغة تكاد تكون ثابتة الا نادرا .. وهي طريقة مفهومة على ما اعتقد ولا تحتاج المزيد من التفصيل ..
باخر الدالة الرئيسية البرنامج يعيد
return Msg.wParam;
الا نالخطوة الرابعة والاخيرة .. وهي تفسير الرسائل ..
الان ندخل بدالة فرعية وهي دالة الرسائل
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
الشرح
LRESULT CALLBACK WndProc(HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
صيغة كتابة الدالة ولاحظ ان اسمها
WndProcوهو نفس الذي كتبناه عند تسجيل النافذة
wc.lpfnWndProc = [COLOR=red]WndProc[/COLOR];
وتتطلب اربع بارامترات .. لاتهتم كثيرا بتفاصيل الدالة كل ما عليك التركيز على اسمها فقط..
ولاننسى البارمترات.. من اهم البارامترات الثاني UINT msg وهو يعني نوع الرسالة
الحاضرة... ومعنى UINT يعني عدد من نوع unsigned int وهو عدد يبين نوع الرسالة ..
وكما قلت لاتخشى هذه الدالة..
switch(msg)
نقول له اختبر الرسالة الواردة
ولاحظ msg وهي التي في البارمترات
هل هي رسالة اغلاق النافذة
case WM_CLOSE:
اذا اعدم النافذة
DestroyWindow(hwnd);
وننهي النافذة عن طريق الدالة DestroyWindow التي نمرر لها النافذة المطلوبة وهي هنا hwnd وهي نفسها التي كتبناها في البرارامتر الاول
WndProc(HWND hwnd, UINT msg,.....
case WM_DESTROY:
PostQuitMessage(0);
اذا تم انهاء البرنامج
والا اذا كانت اي رسالة اخرى تعامل معها على كيفك ياويندوز
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
لاحظ الرسائل فهي تبدأ بـ WM_
خلاص كذا انشأت نافذة
صحيح قد تكون طويلة ولك مع الوقت ستجد انها (( سهلة جدا )) لكن
اكتبها مرة مرتين ثالث وحاول تحفظها لانها الاساس .. طبعا لاتحفظ جميع الدوال لكن على الاقل دالتين او ثلاث حتى تتذكر صيغة كتابة الدوال .. واجلس عليها يومين او ثلاث لانك اذا فهمت هذا الدرس فهمت دوال api كلها واذا حاولت تجاهل.. فانت في موقف صعب ..
قد تكون هناك جزئيات غير مفهومة .. ما عليك .. سأشرحها في الجزء الثالث من هذا الدرس ..
الجزء القادم سنتحدث عن نفس هذا الدرس لكن .. فقط كتعليقات وتلميحات ... وتوسع اكثر ... ان شاء الله ..
لاتنسونا من دعائكم ..
قبل ما اخلص ... (( وش رايكم بالوان الموضوع .. احمر وازرق واخضر
كأنه كورنيش ))
ولاتنسون تصحيح الاخطاء واضافات من هنا وهناك السلام عليكم ..
الملف في المرفقات ..
Edited by الشـمري, 2005-05-18 - 11:24 PM.