لقد أجريت مؤخرًا بعض التحسينات على الكود بعد الاختبار، وكان التأثير جيدًا، لكنني وجدت أن الواجهة سوف تومض، وعلى وجه التحديد سوف يومض عنصر تحكم TreeView، واللغة هي C#، وIDE هو VS2005. بعد مراجعة بعض المعلومات واستخدام بعض التقنيات الأساسية (مثل تشغيل التخزين المؤقت المزدوج)، وجدت أنه لم يكن له أي تأثير.
لذلك استخدمت أداة PRfiler لأكتشف أن الاختناق يكمن في عملية EndUpdate بعد تحديث الواجهة في كل مرة (يستخدم هذا لتقليل عدد تحديثات الواجهة، لكنه ليس مثاليًا هنا نظرًا لوجود العديد من العناصر في عنصر التحكم) أعتقد أنه في كل مرة يتم تحديثها، سيتم تحديث وإعادة رسم الطبقة السفلية من .Net لكل طبقة بدائية، وبالتالي ستكون السرعة بطيئة وتسبب الوميض. ولكن إذا كان الأمر كذلك، فإن استخدام التخزين المؤقت المزدوج يجب أن يؤدي إلى نتائج أفضل. بالنظر إلى الكود مرة أخرى، وجدت أن إجراء التحديث قد يكون متكررًا للغاية، لذلك قمت بتقليل السرعة والتحسن، لكنه ما زال لا يعمل.
استمر في البحث عبر الإنترنت وابحث أخيرًا عن الحل الأكثر ملاءمة. اتضح أن إعادة الرسم الأساسية ستؤدي إلى مسح اللوحة القماشية في كل مرة ثم إعادة رسمها بالكامل، وهذا هو السبب الرئيسي للوميض. لذلك يتم تحميل عملية إرسال الرسائل بشكل زائد ويتم تعطيل هذه الرسالة. الرمز هو كما يلي:
تجاوز محمي باطلة WndProc (المرجع الرسالة م)
{
إذا (m.Msg == 0x0014) // تعطيل مسح رسائل الخلفية
يعود؛
base.WndProc(ref m);
}
نجاح!
ملاحظة: لا يزال التخزين المؤقت المزدوج مفيدًا عندما لا تكون التحديثات متكررة جدًا ولا يحتوي عنصر التحكم على عدد كبير جدًا من العناصر. بمجرد وجود عدد كبير جدًا من العناصر، سيستغرق كل تحديث وقتًا طويلاً. حتى إذا تم استخدام التخزين المؤقت المزدوج، فلا يمكن حل مشكلة الوميض. أنا شخصياً أعتقد أن الطريقة المثالية هي تعطيل رسائل الخلفية ومسحها في النهاية.
المرفق: بعض سجلات المحاولات والإخفاقات
1) استخدم setStyle
يقال على شبكة الإنترنت أنه يتم استخدام وظيفة setStyle لتعيين معلمات عنصر التحكم، وتحديداً:
SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
يعتمد الأخير من معلمات الخيار الثلاثة هذه على الأول ويجب أن يتواجد معًا، وإلا فسيكون غير صالح. وهذه الوظيفة نفسها محمية، لذا عليك أولاً أن ترث عنصر تحكم معينًا قبل استخدامها.
يتوافق هذا الهدف مع الحل الصحيح السابق، والذي يعمل أيضًا على تعطيل مسح الخلفية وتشغيل التخزين المؤقت المزدوج، ولكنه يتطلب خيار الرسم من قبل المستخدم، وكل الرسم يتم بواسطة المستخدم. وهذا يتطلب منك تنفيذ جميع رسومات عناصر التحكم بنفسك، وهو أمر مزعج للغاية. لذا فإن هذه الطريقة ليست غير مجدية تمامًا، ولكنها تتطلب عملاً إضافيًا ولا ينصح بها. لم أستخدمها أيضًا.
2) استخدم BeginUpdate وEndUpdate
يكون لزوج العمليات هذا تأثيرًا أفضل في السيناريوهات التي تتطلب عمليات مجمعة لتحديث عناصر التحكم، مثل إضافة عدد كبير من العقد على دفعات أثناء التهيئة. العيب هو أنه لا يمكن تحديثه على الفور. لذلك، فهو غير مناسب للمواقف التي يتم فيها تحديث العقد بشكل متكرر وتريد أن تنعكس في الواجهة على الفور. إذا استخدمته ولم تقم بتعطيل رسالة الواجهة الواضحة، فسيبدو عنصر التحكم يومضًا، وستكون له خلفية بيضاء بشكل أساسي، وسيكون المحتوى غير مرئي تقريبًا (اعتمادًا على مدى تعقيد الفيديو). نظرًا لاكتمال تحديثات الواجهة في EndUpdate، تتسبب العديد من العمليات في حظر EndUpdate لفترة طويلة، ويتم مسح الواجهة أولاً وتحديثها لاحقًا، مما يتسبب في ظهور الواجهة فارغة لفترة طويلة.
3) استخدم خيار ControlStyles.EnableNotifyMessage
يتوافق تأثير هذا الخيار أيضًا مع الحل الصحيح. الاستخدام هو:
SetStyle(ControlStyles.EnableNotifyMessage, true);
تجاوز محمي باطل onNotifyMessage(Message m)
{
//اكتب رمز رسالة الفلتر هنا
}
ومع ذلك، لم تظهر التجربة الفعلية أي تأثير، ولا أعرف السبب، ولم أتحقق منها بالتفصيل.
-