Listview flackert auf Dialog Win32 beim Aus- und Wieder Addition aller Einzelteile und alle Spalten

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

Frage

Betrachten wir einen einfachen Win32 Dialog mit Listview-Steuerelement (im Report-Modus) in C ++ geschrieben. Bei einem bestimmten Ereignis alle Elemente und alle Spalten werden gelöscht und neue Spalten und Elemente erstellt werden. Grundsätzlich als Inhaltsänderungen, werden die Spalten automatisch generiert basierend auf dem Inhalt.

Wenn alte Elemente / Spalten werden entfernt und neue hinzugefügt, flackert Listenansicht wie die Hölle. Ich habe versucht, WM_SETREDRAW und LockWindowUpdate() ohne Änderung visuelle Erfahrung.

Ich habe sogar erweiterte Listenansicht Stil LVS_EX_DOUBLEBUFFER gesetzt und das hat nicht geholfen überhaupt.

Der übergeordnete Dialog hat WS_CLIPCHILDREN Satz.

Haben Sie Vorschläge, wie diese Arbeit machen mit so wenig Flimmern wie möglich? Ich denke dabei zwei Ansichten verwendet zu verwenden, Sichtbarkeit abwechselnd, die versteckte man als Back-Puffer verwenden, aber das klingt wie ein Overkill. Es muss eine einfache Möglichkeit, sein.

War es hilfreich?

Lösung

Die Standardliste Steuer Malerei ist ziemlich fehlerhaft. Aber es gibt einen einfachen Trick, um Ihre eigene Double-Buffering-Technik zu implementieren:

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);
    }
}

Dies wird eine Bitmap erstellen und dann die Standardfensterprozedur rufen Sie die Listensteuerung in das Bitmap zu malen und dann Blitten den Inhalt der Bitmap in die Farbe DC.

Sie sollten auch einen Handler für WM_ERASEBKGND hinzufügen:

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

Damit wird die Steuerung stoppt immer den Hintergrund vor einem Neuaufbau zu löschen. Sie können die OnPaint weiter optimieren, wenn Sie eine Membervariable für die Bitmap hinzufügen und nur (wieder) es schaffen, wenn die Größe des Fensters geändert (da immer ein Bitmap Erstellen von der Größe abhängig kostspielig sein kann aus dem Fenster).

Das sollte ziemlich gut funktionieren.

Andere Tipps

Nach vielen Dinge zu versuchen und vor allem Vorschlägen der humbagumba Ich bin gekommen, um eine sehr einfache Schlussfolgerung. LockWindowUpdate ist jedermanns Freund in einer solchen Situation. Ich bin nicht sicher, wie kommt es versäumt es für mich das erste Mal an die Arbeit, aber nach benutzerdefinierten gescheitert Malerei in allen Situationen zu liefern, ich LockWindowUpdate versucht haben, noch einmal und es hat funktioniert!

Grundsätzlich wickelt nur alle Arbeiten auf Listenansicht in einem LockWindowUpdate(hWnd) und LockWindowUpdate(NULL) und Dinge schön zu arbeiten. Es gibt nicht einmal ein Scrollbar Flimmern nicht mehr.

So stellen Sie sicher nicht zu nisten LockWindowUpdate als nur ein Fenster zu einem Zeitpunkt gesperrt werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top