يمكنني تعليق إعادة رسم شكل حتى لقد أنجزت كافة التحديثات؟
-
03-07-2019 - |
سؤال
وعن طريق C # و. NET 2.0، أنا باستخدام شكل غير منتظم الشكل (TransparencyKey، FormBorderStyle = بلا، الخ ...) وتريد السماح "طبيعية" واسطة تحدها.
ويمكنني تغيير لون الخلفية الافتراضي من الجير يمكنني تغيير FormBorderStyle إلى FixedSingle I تغيير TransparencyKey إلى Colour.None
وUnfortuanately هذا يبدو فوضى كاملة على الشاشة مع صورة القفز بضعة بكسل أسفل وإلى الجانب وشكل الأخضر الجير.
وأعتقد أن سبب ذلك شكل يجري إعادة رسم بعد كل سطر من التعليمات البرمجية، غير أنه من الممكن تعليق رسم شكل حتى لقد جعلت التغييرات الخاص بي، وبعد ذلك فقط إعادة رسم شكل واحد؟
وG
المحلول
والجواب جديد: تجاوز WndProc ومنع رسالة WM_PAINT أثناء تطبيق خصائص النافذة الجديدة
والجواب قديم.: تجاوز WndProc، ومنع رسالة WM_ERASEBKGND
وشرح ما يقوم به الرمز أدناه:
عند ينتقض المنطقة النافذة، يرسل Windows سلسلة من الرسائل إلى عنصر التحكم الذي يؤدي إلى رسمت طازجة القطعة. رسالة في وقت مبكر من هذه السلسلة هي WM_ERASEBKGND
. عادة، ردا على هذه الرسالة، والسيطرة يرسم نفسه بلون واحد. وفي وقت لاحق، ردا على رسالة WM_PAINT
(والذي يستهلك عادة من قبلنا في حال OnPaint) ويتم الرسم الفعلي. إذا كان هذا الرسم هو غير تافهة سوف يكون هناك تأخير قبل أن يتم تحديث القطعة وستحصل على وميض مزعج.
وعند النظر إلى التعليمات البرمجية الخاصة بك مرة أخرى كنت حل واضح لمشكلة مختلفة. جرب هذا مثال جديد. فإنه سيتم منع هذه اللوحة من النموذج / السيطرة إذا علم bAllowPaint
هو ضبطه.
و <م> NEW م> مثال:
private const int WM_PAINT = 0x000F;
protected override void WndProc(ref Message m)
{
if ((m.Msg != WM_PAINT) ||
(bAllowPaint && m.Msg == WM_PAINT))
{
base.WndProc(ref m);
}
}
و <م> OLD م> مثال:
private const int WM_ERASEBKGND = 0x0014;
protected override void WndProc(ref Message m)
{
if (m.Msg != WM_ERASEBKGND) // ignore WM_ERASEBKGND
{
base.WndProc(ref m);
}
}
نصائح أخرى
وحاول الملكية Form.DoubleBuffered. تعيين إلى 'true'.
وأيضا، إذا كان النموذج الخاص بك لديه أي عناصر التحكم التابعة، أيضا تعيين DoubleBuffered إلى true لأولئك، وكذلك (والأطفال الأطفال وغيرها، وأسفل الخط).
وأخيرا، ندعو SuspendLayout قبل التغييرات وResumeLayout بعد ذلك. نضع في اعتبارنا هذا يؤثر فقط على وضع ضوابط الطفل. إذا كنت تفعل أي عرف رسم الملكية DoubleBuffered سوف اعطيكم المزيد من ضجة لباك.
وأنت تقوم بتعديل الخصائص التي لها تأثير كبير ليس على النموذج. TransparencyKey وFormBorderStyle تتطلب تغيير بت نمط الإطار. نوافذ لا تسمح هذه البتات النمط إلى أن تتغير. أشكال النوافذ تطبق عليها عن طريق تدمير تماما النافذة وإعادة إنشاء من الصفر. خدعة متقنة، ولكن ذلك يستغرق وقتا طويلا وسيتم شكل طلاؤها في كل مرة قمت بتغيير النمط. مما تسبب في المؤثرات البصرية غير سارة تراه.
وجرب هذا: 1. تعيين التعتيم إلى 0 بحيث يصبح شكل غير مرئي 2. تغيير ون_الخلفية، لا مشكلة 3. تغيير FormBorderStyle، ويحصل على صوغه نافذة 4. تغيير TransparencyKey، ويحصل على صوغه نافذة 5. تغيير التعتيم على 1، ويحصل على صوغه النافذة، ثم مرئية
وعلى سبيل المثال:
this.Opacity = 0;
this.BackColor = Color.FromKnownColor(KnownColor.Control);
this.FormBorderStyle = FormBorderStyle.Sizable;
this.TransparencyKey = Color.Empty;
this.Opacity = 1;
وإذا كان كل فشل ذلك، قد تتمكن من محاولة بعض القرصنة lowlevel من خلال منع جميع المشاركات الطلاء إلى النموذج الخاص بك.
تحذير: أنا لا تشجيع استخدام هذه الطريقة، ولكن يمكنك أن تجرب ذلك إذا كنت تريد حقا أن. وقد ساعدني في الماضي.
Win32.LockWindowUpdate(this.Handle);
try
{
//make your changes here
}
finally
{
//release the lock
Win32.LockWindowUpdate((IntPtr)0);
}
ويعتمد هذا الرمز على رمز دعم التالية:
public class Win32
{
private Win32() { }
/// <summary>
/// Lock ore relase the wndow for updating.
/// </summary>
[DllImport("user32")]
public static extern int LockWindowUpdate(HWND hwnd);
}
وهناك طريقة لإرسال جميع "صورة" من النموذج إلى الشاشة في خطوة واحدة هي لتمكين DoubleBuffer.
في منشئ يمكنك تعيين ControlStyles
وVB.NET:
SetStyle(ControlStyles.DoubleBuffer, True)