معهد دعم اتش فى اى بى اس لحلول الويب - Powered by vBulletin


 
 
النتائج 1 إلى 1 من 1

الموضوع: أسمبلي 32بت: نوافذ التحكم لنتعلم معا

  1. #1
    عضو جديد


    تاريخ التسجيل: Jun 2011
    رقم العضوية: 7
    المشاركات: 2,181
    HVIPS5 غير متواجد حالياً

    أسمبلي 32بت: نوافذ التحكم لنتعلم معا


    أسمبلي 32بت: نوافذ التحكم لنتعلم معا
    أسمبلي 32بت: نوافذ التحكم لنتعلم معا
    أسمبلي 32بت: نوافذ التحكم لنتعلم معا



    نوافذ التحكم
    Child Windows Control


    نوافذ التحكم:

    يوّفر لنا نظام التشغيل Windows نوافذ تحكم يمكننا إستخدامها كوسيط إدخال/إخراج المعلومات بين البرنامج و المستعمل. ضمن هذه النوافذ نجد: الزر (Button)، حقل نص (Edit Box)، شريط الحالة (Status Bar)، اللائحة (List Box)...
    يمكن إنشاء هذه النوافذ من دون الحاجة إلى تسجيل صنفها و ذلك لأنها مسجلة من قبل النظام، ما علينا فعله هو إنشائها فقط، ليست كنافذة البرنامج الرئيسية التي يجب علينا تسجيل صنفها قبل إنشائها . عندما نريد إنشاء نافذة تحكم يجب علينا إنشائها ضمن الإسم المسجّل في النظام. مثلا: لو أردنا إنشاء زر، يجب إنشاءه ضمن الصنف "Button".

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

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

    فكرة البرنامج:

    سنقوم في هذا الدرس بإنشاء مثل هذه النافذة:

    -1- شكل النافذة


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


    سننشأ نافذة تحتوي على زر و حقل نص، و ندرج فيها قائمة.

    1) الزر "جلب النص": عند الضغط عليه يقوم البرنامج بجلب محتوى حقل النص و إظهاره في رسالة
    2) "جلب نص": نفس ما يقوم به الزر "جلب النص"
    3) "وضع نص": عند الضغط على هذا العنصر سنضع النص "نحن لن نستسلم، ننتصر أو نموت" نقره لتكبير أو تصغير الصورة ونقرتين لعرض الصورة في صفحة مستقلة بحجمها الطبيعي في حقل النص
    4) "تفرغ حقل النص": بهذا العنصر نفرغ محتوى حقل النص
    5) في القائمة "مساعدة" سنجد عنصر وهو "عن البرنامج" يظهر لنا الرسالة "الفريق العربي للبرمجة – معا نرسم أحرف النجاح-
    6) "خروج": للخروج من البرنامج

    ملاحظة: رئينا في درس سابق كيف ننشأ قائمة، لذلك لن أحتاج لإدراج أكوادها هنا لكن ستجدها في الملف المرفق.

    الدوال المستعملة في البرنامج:

    CreateWindowEx: دالة تقوم بإنشاء نافذة من خلال إسم صنف، تأخذ 12 بارامتر.
    نحتاج منها إلا التالي:
    lpClassName: إسم الصنف الذي من خلاله نريد إنشاء نافذة
    الأصناف المسجلة من قبل النظام:STATIC" ،BUTTON"، "LISTBOX"،"COMBOBOX"، "EDIT"، "SCROLLBAR"، MDICLIENT
    lpWindowName: النص الذي نريد وضعه في النافذة
    dwStyle: أسلوب إنشاء النافذة، دائما نضع WS_CHILD و WS_VISIBLE مع إظافة بقية الأساليب اللازمة.
    WS_CHILD لإنشاء نافذة إبنة و WS_VISIBLE لإظهار النافذة مباشرة بعد إنشائها
    x-y: إحداثيات النافذة
    nWidth-nHeight: عرض و طول النافذة
    hWndParent: مقبض النافذة الأم التي نريد إنشاء نافذة على سطحها
    hMenu: معرّف النافذة -نختار أي رقم يشير إليه ليتم التمييز بينه و بين بقية النوافذ-

    GetWindowText: دالة تمّكننا من نسخ محتوى نافذة تحكم و وضعه في حجرة في الذاكرة -Buffer-
    تأخذ 3 بارامترات:
    hWnd: مقبض النافذة
    lpString: مؤشر إلى الحجرة
    nMaxCount: أقصى عدد للحروف التي يمكن نسخها

    SetWindowText: دالة تمكننا من وضع محتوى حجرة في نافذة تحكم
    تأخذ بارامترين:
    hWnd: مقبض النافذة
    lpString: مؤشر إلى الحجرة -لتفريع محتوى نافذة تحكم نضع هذا البارامتر NULL-

    DestroyWindow: تمكننا هذه الدالة من تدمير -غلق- نافذة و من ثم غلق البرنامج
    تأخذ بارامتر و احد:
    hWnd: مقبض النافذة التي نريد تدميرها

    SendMessage: لإرسالة رسالة إلى نافذة
    تأخذ 4 بارامترات:
    hWnd: مقبض النافذة
    Msg: الرسالة -يمكن أن تكون WM_COMMAND، WM_PAINT و غيرها من الرسائل-
    wParam: برامتر الأول الذي نريد إرساله مع الرسالة -مثال:معرّف زر مع WM_COMMAND-
    lParam: برامتر الثاني الذي نريد إرساله مع الرسالة

    شرح البرنامج:

    ملاحظة: ستجد البرنامج و ملف مصدر الكود في المرفق



    التغيير في قسم الثوابت:
    كود:
    .const
    BtnID               = 1000   ; (1)
    EdtID               = 1001   ; (2)
    IDM_GET             = 100    ; \
    IDM_SET             = 101    ; |
    IDM_CLEAR           = 102    ; | (3)
    IDM_EXIT            = 103    ; |
    IDM_ABOUT           = 104    ; /
    (1): معرّف الزر "جلب النص"
    (2): معرّف حقل النص
    (3): معرّفات عناصر القائمة

    التغيير في قسم البيانات:

    كود:
    .data              ; Initialized data
    WndClass           db "NewWndClass",0
    WndName            db "الفريق العربي للبرمجة",0
    MenuName           db "MyMenu",0   ; (1)
    BtnClass           db "Button",0   ; (2)
    BtnText      (3)   db "جلب النص",0 
    EdtClass           db "edit",0     ; (4)
    EditText           db "نحن لن نستسلم، ننتصر أو نموت",0
    AboutText          db "الفريق العربي للبرمجة - معا نرسم أحرف النجاح",0


    (1): إسم القائمة
    (2): إسم صنف الزر
    (3): النص الذي سنضعه على الزر
    (4): إسم صنف حقل النص

    كود:
    .data?             ; Uninitialized data
    hInstance          dd ?
    hMenu              dd ?         ;(1)
    hBtn               dd ?         ;(2)
    hEdt               dd ?         ;(3)
    Buffer             db 30 dup(?) ;(4)
    (1): مقبض القائمة (نحتاجه لتمريره كبارامتر لإدراج القائمة ضمن النافذة)
    (2): مقبض الزر
    (3): مقبض حقل النص (نحتاجه كبارامتر في الدالتين Get-SetWindowText و ذلك لجلب-وضع النص)
    (4): حجزنا حجرة في الذاكرة بحجم 30 بايت و ذلك لنضع فيها النص الموجود في حقل النص

    التغيير في قسم الكود:

    كود:
                 ......
    invoke LoadMenu,hInst,addr MenuName
    mov hMenu,eax
    invoke CreateWindowEx,WS_EX_LAYOUTRTL or WS_EX_CLIENTEDGE,addr WndClass,addr WndName,WS_OVERLAPPEDWINDOW-WS_SIZEBOX-WS_MAXIMIZEBOX,CW_USEDEFAULT,\
    CW_USEDEFAULT,300,200,NULL,hMenu,hInst,NULL
    إستعملنا الدالة LoadMenu لتحميل القائمة، بعد تنفيذ الدالة بنجاح نحفظ مقبض القائمة في المتغير hMenu لنمرره إلى الدالة CreateWindowEx. لاحظ أننا إستعملنا الستايل WS_OVERLAPPED و أنقصنا منه WS_SIZEBOX و WS_MAXIMIZEBOX و ذلك لعدم تمكين المستعمل من تغيير حجم النافذة أو تكبيرها و ذلك لنحافظ على المظهر الخارجي لنوافذ التحكم التي سننشأها.
    كود:
       .IF uMsg==WM_CREATE
     ;(1)
     invoke CreateWindowEx,NULL,addr BtnClass,addr BtnText,\
     WS_CHILD or WS_VISIBLE,75,75,140,25,hWnd,BtnID,0,NULL
     mov hBtn,eax  ; (2)
     ; (3)
     invoke CreateWindowEx,0,addr EdtClass,0,\
    WS_CHILD or WS_VISIBLE or WS_BORDER or ES_CENTER,50,40,200,25,hWnd,EdtID,0,NULL
     mov hEdt,eax ; (4)

    (1): نقوم بإنشاء الزر باستعمال الدالة CreateWindowEx مع تمرير البارامترات اللازمة -ذكرتها فوق-
    (2): بعد تنفيذ الدالة السابقة بنجاح، سترجع لنا مقبض النافذة المنشأءة، نحفظه للإستعمال المستقبلي
    (3): ننشأء حقل النص، لاحظ أننا إستعملنا الستايل WS_BORDER و ذلك ليتم إظهار حدود الحقل و الستايل ES_CENTER للكتابة في منتصف الحقل -لاحظ هذا عند إستعمال البرنامج نقره لتكبير أو تصغير الصورة ونقرتين لعرض الصورة في صفحة مستقلة بحجمها الطبيعي-
    (4): نحفظ مقبض حقل النص

    كود:
    .ELSEIF    uMsg==WM_COMMAND ; (1)
               mov eax,wParam   ; (2)
               .IF lParam==0  ; (3) IF the pressed item is from the Menu 
                   .IF ax==IDM_SET ; (4)
                       invoke SetWindowText,hEdt,addr EditText ; (5)
                   .ELSEIF ax==IDM_GET ; (6)
                       invoke GetWindowText,hEdt,addr Buffer,SIZEOF Buffer ;(7)
                       invoke MessageBox,hWnd,addr Buffer,addr WndName,MB_OK ;(8)
                   .ELSEIF ax==IDM_CLEAR ;(9)
                        invoke SetWindowText,hEdt,NULL ;(10)
                   .ELSEIF ax==IDM_EXIT ; (11)
                           invoke DestroyWindow,hWnd ; (12)
                    .ELSEIF  wParam==IDM_ABOUT ; (13)
                      invoke MessageBox,hWnd,addr AboutText,addr WndName,MB_OK ;(14)
                    .ENDIF
                .ELSE ; the pressed item is the button  ; (15)
                        shr eax,16 ; (16)
                        .IF ax==0    ; (17) IF Button is clicked
                            invoke SendMessage,hWnd,WM_COMMAND,IDM_GET,0 ;(18)
                        .ENDIF
                .ENDIF

    (1): إلتقاط الرسالة WM_COMMAND. عند إستلام هذه الرسالة يحتوي البارامتر wParam و lParam على التالي:
    *- إذا كان العنصر المضغوط هو من القائمة: سيحتوي lParam على القيمة 0، قيمة الكلمة السفلى من wParam ستحتوي على معرّف العنصر، و الكلمة العليا على 0
    *- إذا كان العنصر المضغوط هو زر: سيحتوي lParam على مقبض الزر، ستحتوي الكلمة السفلى من wParam على معرّف الزر، و الكلمة العليا على القيمة 0 و ذلك إذا تم الضغط على الزر.
    (2): نضع قيمة البارامتر wParam في المسجل EAX
    (3): إذا كانت قيمة lParam هي 0 ذلك يعني أنّ المستعمل قد ضغط على عنصر من القائمة
    (4)-(5): نقارن مع معرّف العنصر -الموجود في القائمة- "وضع نص"، إذا صحّ نقوم بوضع النص في حقل النصوص
    (6)-(7)-(8): نقارن مع معرّف العنصر "جلب نص"، إذا صحّ نجلب النص الموجود في حقل النص ثم نظهره في رسالة
    (9)-(10): نقارن مع معرّف العنصر "تفريغ حقل النص"، إذا صحّ نضع فراغ في حقل النص -لاحظ أننا مرّرنا NULL-
    (11)-(12): إذا كان العنصر "خروج" هو المضغوظ، نقوم بغلق النافذة و من ثّم غلق البرنامج
    (13)-(14): إذا ضغط على الزر "عن البرنامج"، نظهر رسالة
    (15)-(16): إن لم العنصر المضغوط ليس من القائمة، ذلك يعني أن المستعمل ضغط على الزر. نقوم إزاحة المسجل EAX بمقدار 16بت -و ذلك لأنّ الكلمة تتكون من 16بت- لنحصل على الكلمة العليا من EAX- wParam-
    (17)-(18): إذا ضغط على الزر، نرسل رسالة إلى البرنامج نقول فيها أن ينّفذ نفس ما يفعله مع العنصر "جلب نص" -من القائمة-. لاحظ أننا أرسلنا lParam=0 و ذلك لكي يعتبر البرنامج أن العنصر المضغوط هو من القائمة، و يدخل في مقارنة مع عناصر القائمة.

    ملاحظة: لو أرسلنا أي قيمة ل lParam مخالفة للصفر فلن يدخل في مقارنة مع عناصر القائمة.


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

 

ضوابط المشاركة

  • لا تستطيع إضافة مواضيع جديدة
  • لا تستطيع الرد على المواضيع
  • لا تستطيع إرفاق ملفات
  • لا تستطيع تعديل مشاركاتك
  •