ListView Flickers في مربع الحوار Win32 عند إزالة جميع العناصر وإعادة تضافتها وجميع الأعمدة

StackOverflow https://stackoverflow.com/questions/3150108

سؤال

فكر في مربع حوار Win32 عادي مع التحكم في ListView (في وضع التقرير) المكتوبة في C ++. عند حدث معين ، يتم حذف جميع العناصر ويتم إنشاء جميع الأعمدة ويتم إنشاء أعمدة جديدة وعناصر. في الأساس ، مع تغييرات المحتوى ، يتم إنشاء الأعمدة تلقائيًا بناءً على المحتوى.

عند إزالة العناصر/الأعمدة القديمة وإضافة العناصر الجديدة ، وميض ListView مثل الجحيم. لقد حاولت WM_SETREDRAW و LockWindowUpdate() مع عدم وجود تغيير في التجربة البصرية.

لقد قمت حتى بتعيين نمط ListView Extended LVS_EX_DOUBLEBUFFER وهذا لم يساعد على الإطلاق.

الحوار الوالد لديه WS_CLIPCHILDREN تعيين.

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

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

المحلول

لوحة التحكم في القائمة الافتراضية معيب جدا. ولكن هناك خدعة بسيطة لتنفيذ تقنية التعويض المزدوج الخاص بك:

CMyListCtrl::OnPaint()
{
    CRect rcClient;
    GetClientRect(rcClient);

    CPaintDC dc(this);
    CDC dcMem;
    dcMem.CreateCompatibleDC(&dc);

    CBitmap bmMem;
    bmMem.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
    CBitmap* pbmOld = dcMem.SelectObject(&bmMem);

    dcMem.FillSolidRect(rcClient, ::GetSysColor(COLOR_WINDOW));

    this->DefWindowProc(WM_PAINT, (WPARAM)dcMem.m_hDC, (LPARAM)0);

    dc.BitBlt(0,0,rcClient.Width(), rcClient.Height(), &dcMem, 0, 0, SRCCOPY);
    dcMem.SelectObject(pbmOld);

    CHeaderCtrl*    pCtrl = this->GetHeaderCtrl();
    if (::IsWindow(pCtrl->GetSafeHWnd())
    {
        CRect   aHeaderRect;
        pCtrl->GetClientRect(&aHeaderRect);
        pCtrl->RedrawWindow(&aHeaderRect);
    }
}

سيؤدي ذلك إلى إنشاء صورة نقطية ثم استدعاء إجراء النافذة الافتراضية لطلاء عنصر التحكم في القائمة في صورة نقطية ، ثم ينفجر محتويات النقطية في DC Paint DC.

يجب عليك أيضًا إضافة معالج لـ WM_ERASEBKGND:

BOOL CMyListCtrl::OnEraseBkgnd(CDC* pDC)
{
    return TRUE;
}

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

هذا يجب أن يعمل بشكل جيد.

نصائح أخرى

بعد تجربة أشياء كثيرة والأهم من ذلك كله humbagumbaاقتراحات لقد توصلت إلى استنتاج بسيط للغاية. LockWindowUpdate هو صديق الجميع في هذا النوع من المواقف. لست متأكدًا كيف فشل الأمر في العمل بالنسبة لي في المرة الأولى ولكن بعد فشل الرسم المخصص في تقديم جميع المواقف التي جربتها LockWindowUpdate مرة أخرى وعملت!

في الأساس ، فقط لف كل العمل على ListView في LockWindowUpdate(hWnd) و LockWindowUpdate(NULL) والأشياء تعمل بشكل جميل. لم يعد هناك وميض شريط التمرير بعد الآن.

فقط تأكد من عدم العش LockWindowUpdate حيث يمكن قفل نافذة واحدة فقط في وقت واحد.

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