سؤال

حسنًا ، في طلبي ، هناك مجموعة من Winapi وبعض عناصر التحكم المخصصة. ياي...

الآن ، عادة ، سوف يعيدون رسم أنفسهم بهدوء للرسوم المتحركة ، وتغيير الحالة ، إلخ .... وكل شيء يعمل بشكل جيد.

لكن لدي طريقة من نافذة الفصل تسمى fix (). وهذا ما يسمى كلما تحتاج النافذة بأكملها إلى تحديث. يغير عناصر التحكم ويبطل النافذة.

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

ما جربته:

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

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

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

هل كانت مفيدة؟

المحلول

في هذا الوقت ، أدرك المرء أعماق microsofts يتجاهل للمطورين الأصليين. يمكن للمرء أن يبدأ في الواقع في إيواء أوهام بجنون العظمة التي كسرها Microsoft عن قصد اللوحة الأصلية من أجل إجبار المطورين الأصليين على الانتقال إلى WPF.

أولا ، النظر WS_EX_COMPOSITED. WS_EX_COMPOSITED يبدو أن الخردل:- يقول إنه يفرض بوتون لأعلى ترتيب الطلاء لعناصر تحكم الأطفال ، وبشكل أساسي يتم التعامل مع الرسائل WM_Paint في دفعة. تقول أنه تمت إضافته في Windows 2000 (5.0) ، وبضع أسطر لأسفل ، أنه لا يعمل مع تكوين سطح المكتب الممكّن. أي أنه يتوقف عن العمل في نظام Windows Vista (6.0) ، ما لم يتم إيقاف تشغيل Aero Glass ومن سيفعل ذلك؟

بعد ذلك ، هناك اثنين من "الاختراقات" المحتملين لمحاولة الحصول على اللوحة المجانية لميضات وميض للعمل:

  • أولاً ، تحتاج إلى تحبيد مقدار الزائد. WS_EX_CLIPCHILDREN | WS_EX_CLIPSIBLINGS ضرورية لضمان أن يتم رسم أي منطقة معينة من النافذة مرة واحدة فقط. BeginDeferWindowPos من الضروري أيضًا زيادة حجم العمليات لضمان أن الحالات المؤقتة - حيث تتداخل نافذة أخرى - لا تحدث (أي عندما تم تغيير حجم النافذة A ولكن النافذة B لم تكن كذلك).

بالطبع ، عندما تحاول رسم مربع حوار بشرة ، أو استخدام مربعات المجموعة ، أو عناصر التحكم في علامات التبويب ، أو أي عدد من القيود الأخرى ، WS_EX_CLIPSIBLINGS ليس مناسبًا فقط.

  • WM_SETREDRAW هي رسالة سحرية. لا يوجد واجهة برمجة تطبيقات للوصول إلى هذه الوظيفة: WM_SETREDRAW يتم التعامل معه مباشرة بواسطة DefWindowProc لتمييز النافذة بشكل أساسي على أنها مخفية للمدة. بعد، بعدما WM_SETREDRAW, FALSE يتم إرسال المكالمات إلى GETDC/GETDCEX/GETWINDOWDC وما إلى ذلك باستخدام مقبض النافذة الأصل (وجميع أطفالها) من العاصمة التي لن ترسم على الشاشة. يمنحك هذا فرصة للقيام بجميع أنواع الأشياء للنوافذ الفرعية ، عند الانتهاء ، أرسل ملف WM_SETREDRAW,TRUE, ، (ثم إعادة النافذة يدويًا). ستقوم جميع النوافذ الفرعية - بالطبع - بالطلاء في وقتها الخاص ، وبعد أن قامت النافذة الأم بخلفية محوها ، لذا فإن WM_SetRedRaw ليس نوعًا من الدواء الشافي.

بعد الانهيار WS_EX_COMPOSITED, ، في .NET's Winforms و WPF يعيدان كتابة عناصر التحكم من الألف إلى الياء لعدم استخدام عناصر التحكم الأصلية ، حتى يتمكنوا من الخبز في الرسم المخزن المؤقت هناك. و ALPHA دعم أيضا.

نصائح أخرى

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

قد يكون ذلك على سبيل المثال BeginDeferWindowPos ويمكن للأصدقاء إصلاح الخفقان.

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

هتاف و هول. ،

- ألف

بدون رمز ، بالكاد أتخيل ما هو الموقف الفعلي ... ولكن يمكنك محاولة التعامل مع WM_ERASEBKGND ، ارجع صحيحًا كلما استلمتها لتخطي المسح.

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

نرى هنا للحصول على مثال باستخدام MFC.

في .NET هناك ControlStyle.AllPaintingInWmPaint يجب ضبطها على كل نافذة حاوية (وبالتالي النافذة الرئيسية وعلامات التبويب). لم أتمكن من العثور على مكافئ Winapi. ولكن ما يفعله هذا هو نقل لوحة الخلفية من WM_ERASEBKGND إلى WM_PAINT. كما أنه يطرح منطقة مراقبة الطفل من الوالد لتجنب وميض ، فقد تحتاج إلى القيام بذلك يدويًا.

أنا مندهش من WS_EX_COMPOSITED لا يساعد. يجب أن يعمل ذلك ، إذا قمت بتعيين ذلك على النافذة ذات المستوى الأعلى ، ولا تتصل بـ RedRawwindow على عناصر التحكم الفرعية.

تأكد أيضًا من الاختبار مع وبدون DWM/Aero. يمكنك الحصول على نتائج مختلفة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top