مدير النوافذ المضمنة: 10 خطوات
مدير النوافذ المضمنة: 10 خطوات
Anonim
مدير النوافذ المضمنة
مدير النوافذ المضمنة
مدير النوافذ المضمنة
مدير النوافذ المضمنة
مدير النوافذ المضمنة
مدير النوافذ المضمنة
مدير النوافذ المضمنة
مدير النوافذ المضمنة

يوضح هذا المشروع كيفية تنفيذ مدير النوافذ بنوافذ متداخلة متحركة على وحدة تحكم دقيقة مضمنة مع لوحة LCD وشاشة تعمل باللمس. توجد حزم برامج متاحة تجاريًا للقيام بذلك ولكنها تكلف مالًا وهي مصدر مغلق. هذا ، المسمى MiniWin ، مجاني ومفتوح المصدر. إنه مكتوب بلغة C99 المتوافقة تمامًا ويمكن استخدامه في تطبيقات C أو C ++. تتمثل أهداف برنامج MiniWin في أن يكون سهل الاستخدام ، وسهل التعديل ، وقابل للتوسيع ، وقابل للنقل لمجموعة كبيرة من الأجهزة ، وألا يكون متعطشًا للموارد.

بالإضافة إلى توفير الكود لإدارة Windows ، يحتوي MiniWin على مجموعة من عناصر التحكم في واجهة المستخدم - الأزرار ، والمتزلجون ، وأشرطة التقدم ، والأشجار وما إلى ذلك. يمكن أن يكون لديك نوافذ متعددة من أنواع مختلفة أو مثيلات متعددة من نفس النوع. يمكن تحريك النوافذ أو تغيير حجمها أو تكبيرها أو تصغيرها أو إغلاقها - كل الأشياء المعتادة التي تقوم بها باستخدام النوافذ في مديري النوافذ الأكبر حجمًا. يتم أيضًا دعم خطوط TrueType مع تقنين الأحرف والصقل (يجعل النص يبدو سلسًا) لتقديم نص جذاب.

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

بالإضافة إلى إنشاء النوافذ الخاصة بك ، هناك أيضًا بعض الحوارات القياسية المضمنة التي يسهل إنشاء مثيل لها - على سبيل المثال مربعات حوار التأكيد (فقط أزرار موافق أو نعم / لا) ، محددات الوقت / التاريخ ، منتقي الملفات ، منتقي الألوان ، إلخ.

يستخدم MiniWin نظام قائمة انتظار رسائل تصميم مدير Windows القياسي. يمكن أن يتفاعل Windows مع بعضهم البعض ومع مدير النوافذ عبر الرسائل. لا يمكنك استدعاء وظائف للقيام بالأشياء بشكل مباشر ، فأنت تضيف رسالة إلى قائمة الانتظار وسيقوم مدير النوافذ بسنها لك.

تم نقل MiniWin إلى لوحات التطوير القياسية مع شاشات تعمل باللمس من بائعي وحدات التحكم الصغيرة ST و NXP و Renesas. هناك برامج تشغيل للأجهزة وأمثلة للمشاريع لجميع هذه الأجهزة. بالإضافة إلى ذلك ، يمكن تصميم برنامج MiniWin لنظام التشغيل Windows أو Linux بحيث يمكنك محاكاة رمز واجهة المستخدم الخاص بك قبل الحصول على الأجهزة المضمنة.

MiniWin لديه مولد كود. يمكنك تحديد النوافذ وعناصر التحكم الخاصة بك بطريقة بسيطة لإنشاء ملف JSON يمكن قراءته بواسطة الإنسان ويقوم منشئ الكود بتحليل الملف وإنشاء الكود نيابة عنك (هناك الكثير من الأمثلة التي يجب اتباعها). يقوم بإنشاء تطبيقات محاكاة Windows أو Linux كاملة يمكن بناؤها فقط وهناك شاشة LCD محاكاة تعمل بنظام MiniWin windows الخاص بك. يمكنك أن تأخذ نفس الكود الذي تم إنشاؤه بالضبط وإفلاته في مشروع مضمن وأن يكون لديك نفس الكود الذي يعرض نفس النوافذ وعناصر التحكم في وقت لاحق على أجهزتك المضمنة.

لا يتطلب MiniWin أي دعم تشغيلي على الجهاز المضمن. كل شيء يعمل في موضوع واحد. يمكن دمج MiniWin مع نظام RTOS يعمل على معالج مضمن وهناك أمثلة على دمج MiniWin مع FreeRTOS.

يوضح هذا التوجيه كيفية تشغيل MiniWin وتشغيله على معالج STM32 M4 باستخدام لوحة اكتشاف STM32F429 الرخيصة التي تأتي مع شاشة لمس QVGA مرفقة بالفعل. هذه متاحة بسهولة من مورد مكونات الإلكترونيات الخاص بك.

يعمل MiniWin على وحدات تحكم دقيقة متوسطة المدى وما فوق.

اللوازم

لوحة تطوير STM32F429I-DISC1 وكابل USB صغير

تحميل STM32CubeIDE وهو مجاني.

الخطوة الأولى: الحصول على الكود

الحصول على الكود
الحصول على الكود

بادئ ذي بدء ، تحتاج إلى تثبيت STM32CubeIDE. تحصل على ذلك من موقع ST على الويب. يجب عليك التسجيل ويستغرق تنزيله وتثبيته بعض الوقت. كل هذا مجانا.

أثناء التثبيت ، قم بتنزيل مصدر MiniWin وفك ضغطه. إنه كبير ، لكنك ستستخدم جزءًا صغيرًا منه فقط. انقر فوق الزر الأخضر "استنساخ أو تنزيل" هنا …

github.com/miniwinwm/miniwinwm

ثم اختر Download Zip. قم بفك ضغط المحتويات.

الخطوة الثانية: بناء مشروع نموذجي

بناء مشروع نموذجي
بناء مشروع نموذجي
بناء مشروع نموذجي
بناء مشروع نموذجي

لنبدأ أولاً ببناء أحد أمثلة المشاريع. واحد جيد يسمى MiniWinSimple. ابدأ تشغيل STM32CubeIDE ثم قم بما يلي:

  1. اختر ملف | استيراد …
  2. افتح عام واختر مشروع موجود في مساحة العمل. التالي.
  3. انقر فوق استعراض وانتقل إلى المكان الذي قمت بفك ضغط MiniWin. ثم انتقل إلى المجلد STM32CubeIDE / MiniWinSimple / STM32F429. انقر فوق تحديد مجلد.
  4. في المشروع: حدد MiniWinSimple_STM32F429 ثم انقر فوق إنهاء.
  5. سيظهر مشروع MiniWinSimple_STM32F429 في Project Explorer الخاص بك. حدده ثم قم ببنائه باستخدام Project | Build Project.
  6. الآن قم بتوصيل كبل USB باللوحة والكمبيوتر الخاص بك وقم بتشغيله باستخدام Run | Debug وعندما يتم تنزيله ، اختر Run | Resume. ستحصل على عرض معايرة للشاشة في المرة الأولى ، لذا المس مركز التقاطعات الثلاثة على شاشة LCD. يمكنك الآن التفاعل مع النافذة على الشاشة.

لتحريك نافذة ، اسحبها من شريط العنوان الخاص بها. لتغيير حجم نافذة ، استخدم أيقونة المثلث الأبيض على يسار شريط العنوان. لا يمكن تغيير حجم نوافذ MiniWin عن طريق سحب الحدود لأن شاشات العرض المستخدمة MiniWin صغيرة جدًا. لتصغير نافذة أو تكبيرها أو إغلاقها ، استخدم الرموز الموجودة في الطرف الأيمن من شريط العنوان (قد يتم تعطيل الإغلاق). عندما يتم تصغير النافذة ، لا يمكنك تحريك الرموز المصغرة. يتراكمون من أسفل اليسار إلى اليمين.

الخطوة 3: تشغيل مولد الأكواد

تشغيل منشئ الكود
تشغيل منشئ الكود

سنقوم الآن بتغيير مثال المشروع عن طريق إنشاء بعض النوافذ الخاصة بنا وإسقاط الكود الجديد. للقيام بذلك ، سنقوم بتشغيل منشئ الكود.

  1. افتح موجه الأوامر وانتقل إلى المجلد حيث قمت بفك ضغط MiniWin ثم إلى مجلد Tools / CodeGen.
  2. الملف التنفيذي لـ Windows CodeGen.exe متاح بالفعل. بالنسبة إلى Linux ، يجب عليك إنشاءه بكتابة make. (يمكنك أيضًا إنشائه من المصدر لنظام التشغيل Windows إذا كنت قلقًا من تشغيل ملف قابل للتنفيذ تم تنزيله ولكنك تحتاج إلى تثبيت برنامج التحويل البرمجي وبيئة التطوير. راجع وثائق MiniWin في مجلد المستندات للحصول على التفاصيل).
  3. يوجد في هذا المجلد بعض الأمثلة على ملفات JSON. سنستخدم example_empty.json. تحتاج إلى تحريره أولاً لإعداده لنظام التشغيل Windows أو Linux. افتحه في محرر وفي الجزء العلوي حيث ستجد "TargetType" ، قم بتغيير قيمة "Linux" أو "Windows" إلى ما تقوم بتشغيل منشئ الشفرات عليه.
  4. اكتب الآن codegen example_empty.json في موجه الأوامر.
  5. انتقل إلى مشروعك في STM32CubeIDE وافتح مجلد MiniWinSimple_Common. احذف جميع الملفات الموجودة هناك.
  6. لقد تركنا "TargetName" في ملف JSON افتراضيًا في "MiniWinGen" ، وهذا هو اسم مجلد الكود الذي تم إنشاؤه. انتقل إلى المجلد الذي قمت بفك ضغط MiniWin ثم مجلد MiniWinGen_Common. حدد الآن كل هذه الملفات واسحبها وأفلتها في STM32CubeIDE في مجلد MiniWinSimple_Common الخاص بمشروعك.
  7. أعد الآن بناء المشروع وإعادة تشغيله في STM32CubeIDE وستظهر نافذة التصميم الجديدة الخاصة بك. اختفى الزر الموجود في النافذة لأن example_empty.json لا يعرّف أيًا منها.

الخطوة 4: إضافة نافذة

إضافة نافذة
إضافة نافذة

سنقوم الآن بإضافة نافذة ثانية إلى ملف تكوين JSON وإعادة إنشاء الكود.

1. افتح example_empty.json في محرر نصوص.

2. تحت قسم "Windows" ، توجد مجموعة من تعريفات النوافذ التي تحتوي حاليًا على نافذة واحدة فقط. انسخ كل هذا …

{

"الاسم": "W1" ، "العنوان": "Window 1" ، "X": 10 ، "Y": 15 ، "العرض": 200 ، "الارتفاع": 180 ، "Border": true ، "TitleBar": صحيح ، "مرئي": صحيح ، "مصغر": خطأ}

والصقها مرة أخرى بفاصلة تفصل بين التعريفين.

3. قم بتغيير "W1" إلى "W2" و "Window 1" إلى "Window 2". قم بتغيير "X" و "Y" و "Width" و "Height" إلى بعض القيم المختلفة مع الأخذ في الاعتبار أن دقة الشاشة 240 عرضًا × 320 ارتفاعًا.

4. احفظ الملف وقم بتشغيل منشئ الكود مرة أخرى.

5. انسخ الملفات كما في الخطوة السابقة ، وأعد الإنشاء ثم أعد التشغيل. سيكون لديك الآن نافذتان على شاشتك.

الخطوة 5: إضافة عنصر تحكم

إضافة عنصر تحكم
إضافة عنصر تحكم

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

1. في مواصفات النافذة W1 ، أضف فاصلة بعد الإعداد الأخير ("Minimized": false) ثم أضف هذا النص

"MenuBar": صحيح ،

"MenuBarEnabled": صحيح ، "MenuItems": ["Fred"، "Bert"، "Pete"، "Alf"، "Ian"]، "Buttons": [{"Name": "B1"، "Label": "Button1" ، "X": 10 ، "Y": 10 ، "Enabled": true ، "Visible": true}]

يضيف هذا القسم شريط قوائم يحتوي على 5 عناصر ويمكّنه (يمكن تعطيل أشرطة القوائم عالميًا ، جربها). يضيف أيضًا زرًا ممكّنًا ومرئيًا (يمكن إنشاؤه غير مرئي ثم جعله مرئيًا في الكود لاحقًا).

2. إعادة إنشاء الكود ، نسخه عبر ، إعادة البناء ، إعادة تشغيل الكل كما كان من قبل.

الخطوة 6: جعل عناصر التحكم تفعل شيئًا ما

جعل الضوابط تفعل شيئا
جعل الضوابط تفعل شيئا

الآن لدينا واجهة المستخدم الأساسية التي نحتاجها لجعلها تفعل شيئًا ما. في هذا المثال ، سنظهر مربع حوار منتقي الألوان عند الضغط على الزر في النافذة 1.

انتقل إلى مشروعك في STM32CubeIDE وافتح مجلد MiniWinSimple_Common ثم افتح الملف W1.c (يتوافق اسم هذا الملف مع حقل "الاسم" في النافذة في ملف JSON عند إنشاء الرمز).

في هذا الملف ستجد وظيفة window_W1_message_function (). تبدو هكذا:

باطل window_W1_message_function (const mw_message_t * message) {MW_ASSERT (message! = (void *) 0، "Null pointer parameter") ؛ / * توقف السطر التالي عن تحذيرات المترجم لأن المتغير غير مستخدم حاليًا * / (باطل) window_W1_data؛ التبديل (message-> message_id) {case MW_WINDOW_CREATED_MESSAGE: / * أضف أي رمز تهيئة نافذة هنا * / break ؛ الحالة MW_MENU_BAR_ITEM_PRESSED_MESSAGE: / * أضف رمز معالجة قائمة النافذة هنا * / break ؛ الحالة MW_BUTTON_PRESSED_MESSAGE: إذا (message-> sender_handle == button_B1_handle) {/ * أضف رمز المعالج الخاص بك لعنصر التحكم هنا * /} break ؛ الافتراضي: / * Keep MISRA happy * / break؛ }}

يتم استدعاء هذا بواسطة مدير النوافذ لهذه النافذة متى احتاج مدير النوافذ لإعلام النافذة بحدوث شيء ما. في هذه الحالة ، نحن مهتمون بمعرفة أنه تم الضغط على زر النافذة الوحيد. في بيان التبديل لأنواع الرسائل ، سترى حالة لـ MW_BUTTON_PRESSED_MESSAGE. يعمل هذا الرمز عند الضغط على الزر. يوجد زر واحد فقط في هذه النافذة ، ولكن يمكن أن يكون هناك المزيد ، لذلك يتم التحقق من الزر. في هذه الحالة يمكن أن يكون الزر B1 فقط (الاسم يتوافق مع اسم الزر في ملف JSON مرة أخرى).

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

mw_create_window_dialog_colour_chooser (10، 10، "Color"، MW_HAL_LCD_RED، false، message-> Receiver_handle) ؛

المعلمات هي كما يلي:

  • 10 ، 10 هو الموقع على شاشة مربع الحوار
  • "اللون" هو عنوان مربع الحوار
  • MW_HAL_LCD_RED هو اللون الافتراضي الذي سيبدأ به مربع الحوار
  • تعني "خطأ" عدم إظهار الحجم الكبير (حاول ضبطه على "صواب" ولاحظ الفرق)
  • message-> المستلم هو من يمتلك مربع الحوار هذا ، وفي هذه الحالة يكون هذا هو النافذة. مقبض النافذة موجود في معلمة رسالة الوظيفة. هذه هي النافذة التي سيتم إرسال استجابة الحوار إليها.

لمعرفة قيمة اللون الذي يختاره المستخدم ، سيرسل مدير النوافذ لنا نافذة برسالة باللون المختار عندما يضغط المستخدم على الزر "موافق" في مربع الحوار. لذلك نحن بحاجة إلى اعتراض هذه الرسالة أيضًا مع حالة أخرى في بيان التبديل الذي يبدو كالتالي:

الحالة MW_DIALOG_COLOUR_CHOOSER_OK_MESSAGE:

{mw_hal_lcd_colour_t selected_colour = message-> message_data ؛ (باطل) selected_colour ؛ } استراحة؛

نحن لا نفعل أي شيء مع اللون المختار حتى الآن ، لذا فقط نلغيه لمنع تحذير المترجم. يبدو الرمز النهائي لهذه الوظيفة الآن كما يلي:

باطل window_W1_message_function (رسالة const mw_message_t *)

{MW_ASSERT (message! = (void *) 0، "Null pointer parameter") ؛ / * توقف السطر التالي عن تحذيرات المترجم لأن المتغير غير مستخدم حاليًا * / (باطل) window_W1_data؛ التبديل (message-> message_id) {case MW_WINDOW_CREATED_MESSAGE: / * أضف أي رمز تهيئة نافذة هنا * / break ؛ الحالة MW_MENU_BAR_ITEM_PRESSED_MESSAGE: / * أضف رمز معالجة قائمة النافذة هنا * / break ؛ الحالة MW_BUTTON_PRESSED_MESSAGE: إذا (message-> sender_handle == button_B1_handle) {/ * أضف رمز المعالج لعنصر التحكم هذا هنا * / mw_create_window_dialog_colour_chooser (10، 10، "Color"، MW_HAL_LCD_RED؛ } استراحة؛ الحالة MW_DIALOG_COLOUR_CHOOSER_OK_MESSAGE: {mw_hal_lcd_colour_t selected_colour = message-> message_data ؛ (باطل) selected_colour ؛ } استراحة؛ الافتراضي: / * Keep MISRA happy * / break؛ }}

يظهر تشغيل الكود في الصورة أعلاه. قد تلاحظ أنه عندما يظهر مربع حوار ، يجب عليك الرد عليه ورفضه قبل أن تفعل أي شيء آخر. هذا يسمى السلوك المشروط. الحوارات في MiniWin وجميعها دائمًا مشروط عالميًا ويمكنك فقط عرض واحد في كل مرة. هناك المزيد من الشرح هنا …

en.wikipedia.org/wiki/Modal_window

الخطوة 7: الرسم في النافذة

الرسم في النافذة
الرسم في النافذة

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

توجد مكتبة لأوامر الرسومات في MiniWin يمكنك استخدامها. انهم جميعا نافذة على علم. هذا يعني أنه لا داعي للقلق بشأن ما إذا كانت النافذة مرئية ، أو محجوبة جزئيًا بواسطة نوافذ أخرى ، أو قيد التشغيل ، أو مغلقة جزئيًا ، أو خارج الشاشة بالكامل ، أو إذا كان تنسيق المكان الذي ترسم فيه موجودًا في منطقة العميل أو خارجها. كل شيء يتم الاعتناء به من أجلك. لا يمكنك الرسم خارج منطقة عملائك.

الرسم على مناطق العميل في مصطلحات Windows يسمى الرسم وكل نافذة لها وظيفة طلاء حيث تقوم بالرسم. لا تستدعي وظيفة الطلاء الخاصة بك ، يقوم مدير النوافذ بذلك نيابة عنك عند الحاجة. تكون مطلوبة عند نقل إحدى النوافذ أو تغيير موضع أو رؤية نافذة أخرى في الأعلى. إذا كنت بحاجة إلى إعادة طلاء نافذتك لأن بعض البيانات التي تعتمد عليها محتويات النافذة قد تغيرت (أي أنك تعلم أن إعادة الطلاء مطلوبة بدلاً من معرفة مدير النوافذ) ، فأنت تخبر مدير النوافذ أن هناك حاجة إلى إعادة الطلاء ويستدعي ذلك وظيفة الطلاء الخاصة بك. لا تسميها بنفسك. (كل هذا موضح في القسم التالي).

أولاً ، تحتاج إلى العثور على وظيفة الطلاء الخاصة بك. يقوم منشئ الكود بإنشائه لك وهو أعلى بقليل من وظيفة معالج الرسالة المعدلة في القسم السابق. انتقل إلى مشروعك وافتح الملف W1.c مرة أخرى.

في هذا الملف ستجد وظيفة window_W1_paint_function (). تبدو هكذا:

نافذة باطلة_W1_paint_function (mw_handle_t window_handle، const mw_gl_draw_info_t * draw_info)

{MW_ASSERT (draw_info! = (void *) 0، "Null pointer parameter")؛ / * ملء منطقة العميل بالنافذة باللون الأبيض الخالص * / mw_gl_set_fill (MW_GL_FILL) ؛ mw_gl_set_solid_fill_colour (MW_HAL_LCD_WHITE) ، mw_gl_set_border (MW_GL_BORDER_OFF) ، mw_gl_clear_pattern () ، mw_gl_rectangle (draw_info، 0، 0، mw_get_window_client_rect (window_handle).width، mw_get_window_client_rect (window_handle).height) ؛ / * أضف كود رسم النافذة هنا * /}

هذا هو الكود المجرد الذي تم إنشاؤه وكل ما يفعله هو ملء منطقة العميل باللون الأبيض الصلب. لنرسم دائرة صفراء مملوءة على منطقة العميل. أولاً علينا أن نفهم مفهوم سياق الرسومات (شيء آخر في windows). قمنا بتعيين معلمات الرسم في سياق الرسومات ثم نسمي روتين رسم دائرة عام. الأشياء التي يتعين علينا تعيينها في هذا المثال هي ما إذا كانت الدائرة لها حدود ، ونمط خط الحدود ، ولون الحدود ، وما إذا كانت الدائرة مملوءة ، وملء اللون ، ونمط التعبئة. يمكنك رؤية الكود أعلاه الذي يفعل شيئًا مشابهًا لملء منطقة العميل بمستطيل أبيض مملوء بلا حدود. لا يتم تذكر القيم الموجودة في سياق الرسومات بين كل استدعاء لوظيفة الطلاء ، لذا يتعين عليك إعداد القيم في كل مرة (يتم تذكرها مع وظيفة الطلاء).

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

mw_gl_set_fg_colour (MW_HAL_LCD_BLACK) ،

mw_gl_set_solid_fill_colour (MW_HAL_LCD_YELLOW) ، mw_gl_set_line (MW_GL_SOLID_LINE) ، mw_gl_set_border (MW_GL_BORDER_ON) ، mw_gl_circle (draw_info، window_simple_data.circle_x، window_simple_data.circle_y، 25) ؛

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

mw_gl_circle (draw_info ، 30 ، 30 ، 15) ؛

هذا يرسم دائرة عند الإحداثيات 30 ، 30 بنصف قطر 15. أعد بناء الكود وأعد تشغيله وسترى دائرة في النافذة كما هو موضح أعلاه. ستلاحظ أن الدائرة والزر يتداخلان ولكن الزر في الأعلى. هذا حسب التصميم. تكون عناصر التحكم دائمًا فوق أي شيء ترسمه في منطقة العميل.

الخطوة 8: نافذة البيانات

بيانات النافذة
بيانات النافذة

لقد قمنا حتى الآن بتنفيذ الكود الخاص بنا في وظيفة رسائل Window 1 (للتعامل مع الرسائل الواردة) ووظيفة الطلاء (للرسم على منطقة عميل النافذة). حان الوقت الآن لربط الاثنين. يتيح ملء الدائرة المرسومة في وظيفة الطلاء باللون الذي يختاره المستخدم بواسطة منتقي الألوان عند الضغط على الزر. تذكر أننا لا نسمي وظيفة الطلاء ، بل يقوم مدير النوافذ بذلك ، لذلك لا يمكن لوظيفة رسالتنا (التي تعرف اللون المختار) استدعاء وظيفة الطلاء نفسها مباشرة. بدلاً من ذلك ، نحتاج إلى تخزين البيانات مؤقتًا وإعلام مدير النوافذ بأن إعادة الرسم مطلوبة. سيقوم مدير النوافذ بعد ذلك باستدعاء وظيفة الطلاء التي يمكنها استخدام البيانات المخزنة مؤقتًا.

في الجزء العلوي من W1.c ، سترى بنية بيانات فارغة وكائنًا من هذا النوع معلنًا بواسطة منشئ الكود مثل هذا:

هيكل typedef

{/ * أضف بيانات أعضاء هنا * / char dummy؛ / * يشكو بعض المترجمين من البنيات الفارغة ؛ قم بإزالة هذا عندما تضيف أعضاءك * /} window_W1_data_t ؛ ثابت window_W1_data_t window_W1_data ؛

هذا هو المكان الذي نقوم فيه بتخزين بياناتنا مؤقتًا بحيث يتم حفظها عبر المكالمات وتُعرف باسم بيانات النافذة. نحتاج فقط إلى تخزين اللون المختار هنا ، مثل هذا:

هيكل typedef

{/ * أضف أعضاء البيانات الخاصة بك هنا * / mw_hal_lcd_colour_t selected_colour؛ } window_W1_data_t ؛ ثابت window_W1_data_t window_W1_data = {MW_HAL_LCD_YELLOW} ،

سنعطيه لون البداية من الأصفر. الآن في وظيفة الرسائل ، سنقوم بتغيير الرمز قليلاً لحفظ اللون المختار هنا مثل هذا:

الحالة MW_DIALOG_COLOUR_CHOOSER_OK_MESSAGE:

{window_W1_data.chosen_colour = message-> message_data ؛ } استراحة؛

ثم سنقوم بتغيير وظيفة الطلاء لاستخدام هذه القيمة عندما ترسم الدائرة على النحو التالي:

mw_gl_set_solid_fill_colour (window_W1_data.chosen_colour) ؛

لقد قمنا الآن بتغيير البيانات التي تعتمد عليها محتويات النافذة ، لذلك نحتاج إلى إعلام مدير النوافذ بأن النافذة تحتاج إلى إعادة رسمها. نقوم بذلك في وظيفة الرسالة عندما يتم استلام رسالة الحوار OK ، مثل هذا:

mw_paint_window_client (رسالة-> مُعامل_المستلم) ؛

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

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

#يشمل

#include "miniwin.h" #include "miniwin_user.h" #include "W1.h" typedef Struct {/ * أضف أعضاء بياناتك هنا * / mw_hal_lcd_colour_t selected_colour؛ } window_W1_data_t ؛ ثابت window_W1_data_t window_W1_data = {MW_HAL_LCD_YELLOW} ، window_W1_paint_function (mw_handle_t window_handle، const mw_gl_draw_info_t * draw_info) {MW_ASSERT (draw_info! = (void *) 0، "Null pointer parameter") ؛ / * ملء منطقة العميل بالنافذة باللون الأبيض الخالص * / mw_gl_set_fill (MW_GL_FILL) ؛ mw_gl_set_solid_fill_colour (MW_HAL_LCD_WHITE) ، mw_gl_set_border (MW_GL_BORDER_OFF) ، mw_gl_clear_pattern () ، mw_gl_rectangle (draw_info، 0، 0، mw_get_window_client_rect (window_handle).width، mw_get_window_client_rect (window_handle).height) ؛ / * أضف كود رسم النافذة هنا * / mw_gl_set_fg_colour (MW_HAL_LCD_BLACK) ؛ mw_gl_set_solid_fill_colour (window_W1_data.chosen_colour) ؛ mw_gl_set_line (MW_GL_SOLID_LINE) ، mw_gl_set_border (MW_GL_BORDER_ON) ، mw_gl_circle (draw_info ، 30 ، 30 ، 15) ؛ } باطل window_W1_message_function (const mw_message_t * message) {MW_ASSERT (message! = (void *) 0، "Null pointer parameter") ؛ / * توقف السطر التالي عن تحذيرات المترجم لأن المتغير غير مستخدم حاليًا * / (باطل) window_W1_data؛ التبديل (message-> message_id) {case MW_WINDOW_CREATED_MESSAGE: / * أضف أي رمز تهيئة نافذة هنا * / break ؛ الحالة MW_MENU_BAR_ITEM_PRESSED_MESSAGE: / * أضف رمز معالجة قائمة النافذة هنا * / break ؛ الحالة MW_BUTTON_PRESSED_MESSAGE: إذا (message-> sender_handle == button_B1_handle) {/ * أضف رمز المعالج لعنصر التحكم هذا هنا * / mw_create_window_dialog_colour_chooser (10، 10، "Color"، MW_HAL_LCD_RED؛ } استراحة؛ الحالة MW_DIALOG_COLOUR_CHOOSER_OK_MESSAGE: {window_W1_data.chosen_colour = message-> message_data ؛ mw_paint_window_client (رسالة-> مُعامل_المستلم) ؛ } استراحة؛ الافتراضي: / * Keep MISRA happy * / break؛ }}

قم بالبناء والتشغيل مرة أخرى ويجب أن تكون قادرًا على تعيين لون تعبئة الدائرة.

يستخدم هذا المثال لبيانات النافذة البيانات المخزنة في بنية بيانات ثابتة أعلى الملف المصدر. هذا جيد إذا كان لديك مثيل واحد فقط من النافذة ، كما نفعل في هذا المثال ، ولكن إذا كان لديك أكثر من مثيل واحد ، فسيقومون جميعًا بمشاركة نفس بنية البيانات. من الممكن أن يكون لديك بيانات لكل مثيل بحيث يكون للمثيلات المتعددة من نفس نوع النافذة بياناتها الخاصة. هذا موضح في وثائق MiniWin الموجودة في دليل docs. يستخدمه مثال الملف لإظهار صور متعددة في نفس نوع النافذة (كما هو موضح في الصورة الرئيسية في الجزء العلوي من هذا الدليل).

الخطوة 9: بعض المرح النهائي للخط

بعض المرح النهائي للخط
بعض المرح النهائي للخط

يدعم MiniWin عرض خط TrueType. إذا كان هناك شيء واحد يجعل واجهة المستخدم الخاصة بك تبدو جيدة فهي الخطوط الجذابة. توضح هذه الخطوة الأخيرة كيفية عرض خط TrueType في نافذة MiniWin.

هناك طريقتان لعرض خطوط TrueType. الأول هو رسمها مباشرة على منطقة العميل الخاصة بك كما تم القيام به للدائرة في وقت سابق ، والآخر هو إضافة عنصر تحكم مربع نص إلى نافذتك. نحن نفعل هذا الأخير لأنه أسهل.

سنقوم الآن بإضافة عنصر تحكم مربع نص إلى ملف تكوين JSON الخاص بنا. أضفه إلى تعريف النافذة 2 بحيث يبدو كالتالي:

مثله:

{

"الاسم": "W2" ، "العنوان": "Window 2" ، "X": 50 ، "Y": 65 ، "العرض": 100 ، "الارتفاع": 80 ، "Border": true ، "TitleBar": صحيح ، "مرئي": صحيح ، "مصغر": خطأ ، "مربعات نصية": [{"الاسم": "TB1" ، "X": 0 ، "Y": 0 ، "العرض": 115 ، "الارتفاع": 50، "Justification": "Center"، "BackgroundColour": "MW_HAL_LCD_YELLOW"، "ForegroundColour": "MW_HAL_LCD_BLACK"، "Font": "mf_rlefont_BLKCHCRY16"، "Enabled": true، "Visible": true}]}

كلمة سريعة حول خطوط TrueType في MiniWin. الخطوط تأتي في ملفات.ttf. في مديري النوافذ على أجهزة الكمبيوتر الأكبر حجمًا ، يتم عرضها على شاشتك عند الحاجة إليها. يتطلب هذا الكثير من طاقة المعالجة والذاكرة وهو غير مناسب للأجهزة الصغيرة. في MiniWin تتم معالجتها مسبقًا إلى صور نقطية وربطها في وقت الترجمة بحجم ونمط خط ثابت (غامق ومائل وما إلى ذلك) ، أي عليك أن تقرر ما هي الخطوط في أي حجم وأسلوب ستستخدمه في وقت الترجمة. تم إجراء ذلك من أجلك لمثالين من الخطوط في ملف MiniWin المضغوط الذي قمت بتنزيله. إذا كنت تريد استخدام خطوط أخرى بأحجام وأنماط أخرى ، فراجع توثيق MiniWin في مجلد المستندات. توجد أدوات في MiniWin لنظامي التشغيل Windows و Linux للمعالجة المسبقة لملفات ttf. في ملفات التعليمات البرمجية المصدر التي يمكنك وضعها في مشروعك.

وكلمة ثانية سريعة - معظم الخطوط هي حقوق طبع ونشر ، بما في ذلك تلك التي ستجدها في Microsoft Windows. استخدمها حسب الرغبة للاستخدام الشخصي ، ولكن أي شيء تنشره يجب أن تتأكد من أن الترخيص المنشور مع الخطوط يسمح بذلك ، كما هو الحال بالنسبة للخطين المتضمنين في MiniWin ، ولكن ليس خطوط Microsoft!

العودة إلى الكود! قم بإنشاء الملفات وإفلاتها وإنشاءها وإعادة تشغيلها كما كان من قبل وسترى أن النافذة 2 بها الآن نص افتراضي على خلفية صفراء بخط أحمق. يتيح تغيير النص عن طريق تحرير الملف المصدر لـ Window 2 W2.c.

نحتاج إلى التواصل مع مربع النص الذي أنشأناه للتو والطريقة التي تفعل بها ذلك مثل أي اتصال في MiniWin هي إرسال رسالة إليه. نريد ضبط النص في عنصر التحكم عند إنشاء النافذة ولكن قبل عرضها ، لذلك نضيف رمزًا في معالج الرسالة في حالة MW_WINDOW_CREATED_MESSAGE. يتم تلقي هذا من خلال رمز النافذة قبل عرض النافذة مباشرة وهو مخصص لعمليات التهيئة مثل هذا. أنشأ مُنشئ الكود حاملًا نائبًا يشبه هذا في وظيفة معالج الرسالة:

الحالة MW_WINDOW_CREATED_MESSAGE:

/ * أضف أي رمز تهيئة نافذة هنا * / break ؛

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

الحالة MW_WINDOW_CREATED_MESSAGE:

/ * أضف أي رمز تهيئة نافذة هنا * / mw_post_message (MW_TEXT_BOX_SET_TEXT_MESSAGE ، message- >لم المستلم ، text_box_TB1_handle ، 0UL ، "Twas a dark and stormy night…" ، MW_CONTROL_MESSAGE) ؛ استراحة؛

هذه هي المعلمات:

  • MW_TEXT_BOX_SET_TEXT_MESSAGE - هذا هو نوع الرسالة التي نرسلها إلى عنصر التحكم. تم سردها في miniwin.h وموثقة في الوثائق.
  • message-> Receiver_handle - هذا هو مرسل الرسالة - هذه النافذة - يوجد مقبضها في معلمة الرسالة التي تم تمريرها إلى وظيفة معالج الرسالة.
  • text_box_TB1_handle - لمن نرسل الرسالة - مقبض التحكم في مربع النص. يتم سرد هذه في الملف الذي تم إنشاؤه miniwin_user.h.
  • 0UL - قيمة البيانات ، لا شيء في هذه الحالة.
  • "كانت ليلة مظلمة وعاصفة …" - قيمة المؤشر - النص الجديد.
  • MW_CONTROL_MESSAGE - نوع المستلم وهو عنصر تحكم.

هذا كل شيء. قم بإعادة البناء وإعادة التشغيل كالمعتاد وسيظهر مربع النص كما في الصورة أعلاه.

يعد نشر الرسائل أمرًا أساسيًا لـ MiniWin (كما هو الحال بالنسبة لجميع مديري النوافذ). لمزيد من الأمثلة ، انظر إلى أمثلة المشاريع في الملف المضغوط وللحصول على شرح شامل ، اقرأ القسم الخاص برسائل MiniWin في الوثائق.

الخطوة 10: المضي قدمًا

Image
Image

هذا كل شيء في هذه المقدمة الأساسية لبرنامج MiniWin. يمكن لبرنامج MiniWin أن يفعل أكثر بكثير مما تم توضيحه هنا. على سبيل المثال ، الشاشة الموجودة على اللوحة المستخدمة في هذا الدليل صغيرة وعناصر التحكم صغيرة وتحتاج إلى استخدامها مع dibber. ومع ذلك ، تستخدم الأمثلة والأجهزة الأخرى عناصر تحكم أكبر (يوجد حجمان) على شاشات أكبر ويمكن تشغيلها بالأصابع.

هناك العديد من أنواع التحكم الأخرى غير تلك الموضحة هنا. لمزيد من الضوابط ، ألق نظرة على أمثلة مختلفة لملفات JSON في مجلد منشئ الكود. يتم تناول جميع أنواع التحكم في هذه الأمثلة.

النوافذ لديها الكثير من الخيارات. يمكن تكوين الحدود وشريط العنوان والرموز. يمكن أن يكون لديك أشرطة التمرير ومناطق العميل في نافذة التمرير ، ويمكن أن تكون مثيلات متعددة من نفس نوع النافذة والنوافذ عارية (فقط منطقة العميل ، بدون حدود أو شريط عنوان) مما يعني أنه تم إصلاحها في وقت التجميع في مكانها على الشاشة (انظر الصورة في هذا القسم بأيقونات كبيرة الحجم - هذه في الواقع 6 نوافذ عارية).

لا يستخدم MiniWin ذاكرة ديناميكية. هذا يجعلها مناسبة للأجهزة الصغيرة المقيدة وهو مطلب لبعض المشاريع المدمجة. كما أن برنامج MiniWin والرمز الذي ينشئه متوافقان تمامًا مع MISRA 2012 للمستوى "المطلوب".

لمزيد من المعلومات ، ألق نظرة في مجلد المستندات للوثائق وأيضًا تطبيقات الأمثلة الأخرى في ملف zip. هناك أمثلة توضح كيفية استخدام جميع ميزات MiniWin وكيفية دمج MiniWin مع FatFS و FreeRTOS.