Flackern

NMO

Grünschnabel
Hi!

Ich weiß es gibt schon ziemlich viele Beiträge zum Thema flackern.
Ich hab mir jetzt auch nicht jeden einzeln genauestens angeschaut, aber ich denke, dass keiner mein Problem dazu lösen könnte...
Also ich hab einen simplen Texteditor mit dem Wizard generiert, indem ich eine Klasse von CEditView abgeleitet habe. An den rechten Rand möchte ich eine Leiste zeichnen, das funktioniert auch schon ganz gut, außer, dass es etwas flackert.

OnPaint sieht folgendermaßen aus:
Code:
OnPaint()
{
int m_bottomline = 1;
CString m_format;
m_format = "%05i";
int m_topmargin = 1; // Current top margin
int m_topline = 0; // Current top line number

CPaintDC dcPaint( this );
COLORREF m_fgcol = 0, m_bgcol = 16318463;
CRect rect;
GetClientRect( &rect );
m_bgcol = RGB(209,255,176);

// We double buffer the drawing -
// preparing the memory CDC
CDC dc;
dc.CreateCompatibleDC( &dcPaint );
int saved = dc.SaveDC();

// Create GDI and select objects
CBitmap bmp;
CPen pen;
bmp.CreateCompatibleBitmap( &dcPaint, rect.Width(), rect.Height() );
pen.CreatePen( PS_SOLID, 1, m_fgcol );
dc.SelectObject( &bmp );
dc.SelectObject( &pen );

// Painting the background
dc.FillSolidRect( &rect, m_bgcol );
dc.MoveTo( rect.right - 1, 0 );
dc.LineTo( rect.right - 1, rect.bottom );

// Setting other attributes
dc.SetTextColor( m_fgcol );
dc.SetBkColor( m_bgcol );
dc.SelectObject( GetParent()->GetFont() );
rect.right = 100;
dcPaint.BitBlt( 0, 0, rect. right, rect.bottom, &dc, 0, 0, SRCCOPY );

CMemDC memDC(&dc, &rect);
//CMemDC pDC(&dc);
CnewceditviewDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
dc.RestoreDC( saved );
CWnd::DefWindowProc( WM_PAINT, (WPARAM)memDC.m_hDC, 0 );

}


Ich hab außerem noch OnKeyDown überschrieben, weil es sonst gar nicht geht:

Code:
OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Fügen Sie hier Ihren Meldungsbehandlungscode ein, und/oder benutzen Sie den Standard.
this->InvalidateRect(NULL);
CEditView::OnKeyDown(nChar, nRepCnt, nFlags);
}

Jetzt ist halt das Problem, dass es bei fast jedem Zeilenumbruch flackert.
Ich hab schon probiert OnEraseBkgnd zu überschreiben, das geht nur teilweise, da
der Client-Bereich transpharent wird und es immer noch leicht flackert, wenn ich einen Zeilenumbruch mache.

Ich wäre echt für jeden Vorschlag wahnsinnig dankbar, da ich schon ziemlich viel Zeit in das Problem investiert habe und ich nicht mehr weiter komme.

Überhaupt wünsche ich alle frohe Ostern :)
 
Zuletzt bearbeitet:
Hallo,

OnEraseBkgnd zu überschreiben und darin einfach nichts zu tun (außer "return TRUE;") ist auf jeden Fall schon mal eine gute Idee, da du ja bei "OnPaint()" ohnehin den gesamten Clientbereich mit der Hintergrundfarbe füllst. Ansonsten passiert das zweimal hintereinander und dann flackert's garantiert.

Du solltest mal versuchen, mit "InvalidateRect()" nicht den gesamten Client-Bereich ungültig zu machen; sondern nur den Bereich deiner Leiste am rechten Rand (also einen RECT- oder CRect-Parameter übergeben). Jedesmal den kompletten Client-Bereich neu zu zeichnen kann trotz Pufferung mittels Memory DC dann doch so lange dauern, dass es sichtbar wird und flackert.

Gruß
MCoder
 
Also ich hab jetzt mal deinen Vorschlag ausprobiert. Leider ohne Erfolg. Es ist jetzt wahrscheinlich ein bisschen viel verlangt, aber wenn ihr Profis mal schnell meinen OnPaint- und OnKeyDown - Code in eine CEditView abgeleitete Anwendung stecken könnte, würdet ihr sicher auf das Problem kommen.
Es ist nämlich so, dass ich das nach Möglichkeit bis Montag haben sollte...:rolleyes:
 
NMO hat gesagt.:
aber wenn ihr Profis mal schnell meinen OnPaint- und OnKeyDown - Code in eine CEditView abgeleitete Anwendung stecken könnte, würdet ihr sicher auf das Problem kommen.
Zumindest ich kann dir da nicht weiterhelfen, da ich erst wieder am Dienstag ein Visual Studio zur Verfügung habe, sorry.

Gruß
MCoder
 
Hallo,
bei einem EditView ist die Überschreibung der WM_PAINT-Nachricht, glaube ich, keine so gute Idee, weil man dann mit den eigentlichen Zeichenroutinen des Controls in Konflikt kommt. Besser ist es, den Hintergrund in OnEraseBkgnd() zu zeichnen. Parameter für den Ausgabetext kann man in CtlColor() setzen. Ich habe hier mal den Hintergrundmodus transparent gesetzt, damit bei der Texteingabe der grüne Balken erhalten bleibt.
Hier mein Testcode:
C++:
BOOL CTestEditView::OnEraseBkgnd(CDC* pDC) 
{
    int     nBottomline   = 1;
    CString strFormat     = "%05i";
    int     nTopmargin    = 1;      // Current top margin
    int     nTopline      = 0;      // Current top line number

    COLORREF crFgcol = 0, crBgcol = RGB(209,255,176);

    CRect rect;
    GetClientRect(&rect);

    // We double buffer the drawing -
    // preparing the memory CDC
    CDC dc;
    dc.CreateCompatibleDC(pDC);

    // Create GDI and select objects
    CBitmap bmp;
    CPen    pen;

    bmp.CreateCompatibleBitmap( pDC, rect.Width(), rect.Height() );
    pen.CreatePen( PS_SOLID, 1, crFgcol );
    
    CBitmap *pOldBitmap = dc.SelectObject( &bmp );
    CPen    *pOldPen    = dc.SelectObject( &pen );

    // Painting the background
    
    dc.FillSolidRect( &rect, RGB(255,255,255) ); // komplett
    
    CRect rcBar(rect);
    rcBar.right = 100;
    dc.FillSolidRect( &rcBar, crBgcol );  // Rand

    dc.MoveTo( rect.right - 1, 0 );
    dc.LineTo( rect.right - 1, rect.bottom );
   
    pDC->BitBlt( 0, 0, rect. right, rect.bottom, &dc, 0, 0, SRCCOPY );

    // Aufräumen
    dc.SelectObject( pOldBitmap );
    dc.SelectObject( pOldPen );
    
    return TRUE;
}

HBRUSH CTestEditView::CtlColor(CDC* pDC, UINT nCtlColor) 
{
    pDC->SetBkMode(TRANSPARENT);
    return NULL;
}
Gruß
MCoder
 
Vielen Dank, das hat mich echt sehr weiter gebracht. :)

Mich freut es echt wahnsinnig, dass so gute Programmierer wie du auch sehr hilfsbereit sind,
das ist nämlich - wie ich herausgefunden habe - nicht selbstverständlich.

gruß NMO
 
Zurück