أهم أقسام المدونة

الصفحات

الأربعاء، 7 يونيو 2017

إخفاء الترجمة عند اختفاء الفديو

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

من السهل تتبع حالة الخاصية Visible لأي أداة من خلاص الحدث VisibleChanged، لكن المشكلة أن إخفاء عارض الفيديو يمكن أن يحدث بأكثر من طريقة، لأنه موضوع على أدوات حاوية أخرى، ويمكن إخفاؤه بإخفائها هي.. وللأسف، لم أجد بعد بحث طويل أي حدث ينطلق حينما تختفي الأداة من على الشاشة لأي سبب غير استخدام الخاصية Visible التابعة لها.
أقرب حل للعقل، هو البحث في المشروع عن كل المواضع التي تقوم بإخفاء عارض الفيديو أو أي أداة حاوية له، وإضافة أكواد في هذه المواضع لإخفاء الترجمة.. لكني لم أفضل هذا، لأن عرض نص الترجمة وظيفة خاصة بالأداة التي تعرض الفيديو، ولا يجب إخراج جزء من وظيفتها خارج الفئة، لأن هذا ينافي مبدأ التغليف Encapsulation في البرمجة الكائنية OOP، ويعقد كتابة الكود وتصحيحه ويجعله أكثر عرضة للخطأ عند إجراء أي تعديلات أو تطويرات مستقبلية.
لهذا فضلت أن أبحث عن حل آخر يجعلني أتفاعل مع ما يحدث مع الأدوات الحاوية لعارض الفيديو، لكن من داخل الفئة.. وهذا هو ما استقر عليه عزمي، لهذا فعلت ما يلي:
- استخدمت الخاصية Parent التابعة لأداة عرض الفيديو (وهي أداة خاصة موروثة من الفئة Panel) لمعرفة الأداة الحاوية لها، وسجلت معالجا للحدث VisibleChanged الخاص بالأداة الحاوية.. ونظرا لأن هناك شجرة أدوات حاوية، فقد فعلت المثل مع كل منها إلى وصولا إلى النافذة.. هذا هو الكود:
Control p = this.Parent;
while (p != null)
{
   // إزالة أي معالج تمت إضافته سابقا لنفس الحدث على سبيل الاحتياط
   p.VisibleChanged -= Parent_VisibleChanged;
   // إضافة معالج جديد للحدث
   p.VisibleChanged += Parent_VisibleChanged;
   p = p.Parent;
}
لاحظ أن كل الأدوات الحاوية بما في ذلك النموذج ستستدعي الإجراء Parent_VisibleChanged لأنه هو معالج الحدث.. كود هذا الإجراء بسيط، ففيه نستخدم المعامل sender للحصول على الأداة الحاوية التي أطلقت الحدث، ثم نفحص قيمة الخاصية Visible لها، فإن كانت false نقوم بإخفاء نموذج الترجمة:
void Parent_VisibleChanged(object sender, EventArgs e)
{
  if (!((Control)sender).Visible)
    _formSubtitle.Hide();
}
يتبقى هنا سؤال هام:
أين نضع الكود الأول (الذي يسجل معالجات الحدث للأدوات الحاوية)؟
هل نضعه في الحدث Load الخاص بأداة عرض الفيديو (لا تنسَ أنها فئة مورثة من الفئة Panel
للأسف، ينطلق الحدث Load بعد اكتمال تحميل الأداة في الذاكرة، لكن قبل إضافتها إلى الأداة الحاوية لها، لهذا لو وضعنا الكود هناك، فستكون للخاصية Parent القيمة "لا شيء" null، ولن يتم تنفيذ الكود!
وللأسف لا تمتلك الأدوات الحدث Shown الموجود في النموذج.
لذا، فالحل الوحيد المتاح هو استخدام الحدث Paint الذي ينطلق كلما تم رسم الأداة على الشاشة.. رسم الأداة معناه أنها ظهرت على الشاشة، أي أنها أضيفت فعلا إلى الأداة الحاوية لها.
لكن لاحظ أن الحدث Paint ينطلق كثيرا كلما احتاج جزء من الأداة إلى إنعاش رسمه، لهذا ينبغي الحذر، واستخدام بعض الشروط لعدم تكرار نفس الكود مرات عديدة.. بالنسبة لي كان الشرط هو اختلاف قيمة الخاصية Owner لنموذج الترجمة عن النموذج الذي يعرض الفيديو.
أرجو أن تفيدكم هذه الأفكار في أي موقف مشابه.

ليست هناك تعليقات:

إرسال تعليق

ملحوظة: يمكن لأعضاء المدونة فقط إرسال تعليق.