Warum flackert mein Dialog, wenn ich ihn größer ziehe?
-
Hallo Forum,
nachdem ich mein Problem mit den Buttons und Bitmaps gelöst habe, stehe ich vor dem nächsten Problem.
Für meinen Dialog habe ich selbst eine Region definiert, in der der Benutzer anpacken und den Dialog größer/kleiner ziehen kann. Das funktioniert auch alles ganz wunderbar, nur flackert das ganze beim Ziehen gewaltig.
Im Dialog sind nur Buttons (Klasse CPolyBtn von Codeproject), die halt neu gezeichnet werden
Danke schonmal! Ohne dieses Forum wäre ich schon oft völlig verloren gewesen!
-
Verdendest du beim zeichnen schonen eine MemoryDC Klasse, also zeichnet du erst in den Speicher? -> Double Buffering
-
Also die Methode DrawItem() aus der Klasse CPolyBtn sieht so aus
void CPolyBtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CRect rect = lpDrawItemStruct->rcItem; CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); UINT state = lpDrawItemStruct->itemState; UINT nStyle = GetStyle(); int nSavedDC = pDC->SaveDC(); CBrush br; br.CreateSolidBrush(m_clrFill); // fill interior pDC->SetPolyFillMode(ALTERNATE); CBrush *ob = pDC->SelectObject(&br); pDC->Polygon(m_pPoints, m_edges.size()); pDC->SelectObject(ob); pDC->SelectClipRgn(&m_rgn); // draw bitmap if (m_bmpID!=0) { CPoint pos = m_bmpOffset; if ((state & ODS_SELECTED)) { pos.x++; pos.y++; } if(m_bMouseOnButton) _TransparentBlt(*pDC, m_bmp, pos.x, pos.y, m_clrTrans); else _TransparentBlt(*pDC, m_bmpMouseover, pos.x, pos.y, m_clrTrans); } if ((state & ODS_DISABLED) && m_bmpIDD!=0) { _TransparentBlt(*pDC, m_bmpD, m_bmpOffset.x, m_bmpOffset.y, m_clrTransD); } // draw text CString txt; GetWindowText(txt); if (!txt.IsEmpty()) { pDC->SetBkMode(TRANSPARENT); if ((state & ODS_DISABLED)) { CSize cz = pDC->GetTextExtent(txt); pDC->DrawState(m_textOffset, cz, txt, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL); } else { CPoint pos = m_textOffset; if ((state & ODS_SELECTED)) { pos.x++; pos.y++; } pDC->TextOut(pos.x, pos.y, txt); } } // paint the edges for (int i=0;i<m_edges.size();i++) { int iPenStyle = PS_SOLID; COLORREF clr = m_edges.at(i).clr; if(m_bMouseOnButton) clr = m_edges.at(i).rolloverclr; else clr = m_edges.at(i).focusclr; /* if ((state & ODS_SELECTED)) { clr = m_edges.at(i).downclr; } else if ((state & ODS_DISABLED)) { clr = m_edges.at(i).disabledclr; } else if (m_bMouseOnButton) { clr = m_edges.at(i).rolloverclr; } */ CPen pen(iPenStyle, 1, clr); CPen *opp = pDC->SelectObject(&pen); pDC->MoveTo(m_edges.at(i).start); pDC->LineTo(m_edges.at(i).end); pDC->SelectObject(opp); } pDC->SelectClipRgn(NULL); pDC->RestoreDC(nSavedDC); }Ansonsten setze ich nur in OnSize() des Dialogs für jeden Button CRect neu. Die OnPaint()-Methode des Dialogs habe ich gar nicht verändert. Muss ich die Draw-Item Methode für die Buttons verändern und erst in einen MemoryDC zeichnen?
-
Versuch erst mal in OnEraseBkgnd FALSE zurückzugeben.
-
Also wenn ich in der OnEraseBkgnd() der Buttonklasse FALSE zurückgebe, ändert sich gar nichts.
Gebe ich in meiner Dialogklasse bei OnEraseBkgnd() FALSE zurück, verschwindet der Hintergrund des Dialogs, d.h. es sind nur noch meine Buttons sichtbar, und außerdem verändert sich der Hintergrund des Dialogs nicht mehr, d.h. beim größer ziehen des Dialogs sieht man noch die Buttons vom kleineren Dialog usw.
-
Zufällig habe ich das gleiche Problem. OnEraseBkgnd sendet als Returnwert FALSE bei mir. Mit einer Display-Buffer-Klasse arbeite ich auch. Denoch flackert meine von CButton abgeleitete Zeichenfläche beim größer ziehen.
Wäre es eine Lösung den Inhalt von DrawItem in OnEraseBkgnd zu schreiben.
-
Ok, ich meinte natürlich die Dialogklasse, sorry.
Flackern tut es aber erst mal nicht mehr? Jetzt könntest du in der OnPaint des Dialogs den Hintergrund selbst zeichnen (FloodFill).
Was mir aber gerade noch einfällt, rufst du in der OnSize Invalidate auf?
Wenn ja, versuchs mal Invalidate(FALSE);
-
Ich habe Invalidate() nicht aufgerufen. Habs gerade mal probiert, aber das ändert auch nichts leider.
Ich habe jetzt folgendes in meine OnPaint()-Methode geschrieben, aber es tut sich nichts. was mache ich falsch?void CStartdialog3Dlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // Gerätekontext für Zeichnen SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Symbol in Client-Rechteck zentrieren int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Symbol zeichnen dc.DrawIcon(x, y, m_hIcon); } else { CRect rect; GetClientRect(&rect); CPaintDC dc(this); dc.FloodFill(rect.left, rect.top, RGB(148,147,170)); CDialog::OnPaint(); } }
-
Schau mal hier rein: http://www.codeproject.com/gdi/flickerfree.asp
Vielleicht hilft Dir das weiter.
-
Hm, ok, also ich habe nochmal ein bisschen rumprobiert und bin dabei auf das Problem gestoßen, dass mein Dialog ja nicht rechteckig ist und ich deswegen mit
dc.FloodFill(rect.left, rect.top, RGB(148,147,170));am falschen Punkt ansetze, da sich dieser Punkt gar nicht in meinem Dialog befindet. Ändere ich also auf
CRect rect; GetClientRect(&rect); CDC* dc = this->GetDC(); dc->FloodFill(d1.x, d2.x, RGB(148,147,170)); CDialog::OnPaint();wird der Hintergrund immerhin weiß gezeichnet

-
Hihi, sorry, das liegt daran, das wahscheinlich VS hinter dem Dialog liegt und dies als Hintergrund für den Dialog genommen wird. Guck mal genau da müstte auch Text stehen

Lass das Floodfill in OnPaint weg und
versuch mal in OnEraseBkgnd folgendes:CRect rc; GetClientRect(&rc); CBrush brush(RGB(148,147,170)); pDC->FillRect(&rc,&brush); return TRUE;
-
connan schrieb:
Hihi, sorry, das liegt daran, das wahscheinlich VS hinter dem Dialog liegt und dies als Hintergrund für den Dialog genommen wird. Guck mal genau da müstte auch Text stehen
Ähm, ja, da steht auch ab und an mal Text

Die andere Möglichkeit hab ich mal ausprobiert. Jetzt ist der Hintergrund zwar wieder farbig, aber dafür flackern doch wieder alles beim ziehen. Ich hab auch nochmal zur Kontrolle FALSE zurückgegeben und da flackert das ganze Ding nicht so

-
Ja, man muss, glaube ich, auch FALSE zurückgeben (hab nicht nachgeschaut
).
Aber jetzt dürften zumindest nur noch die Buttons flackern?
-
Tja, ich weiß nicht so genau was da flackert! Alles irgendwie

-
Und wenn Du jetzt auch in OnEraseBkgnd der Buttons FALSE zurückgibst? Kann sein das Du dafür noch 'Benachrichtigen' einschalten musst.
-
Dann flackert immer noch alles

Trotzdem vielen Dank fürs viele Antworten, irgendeine Lösung finde ich sicher noch!
-
Lass es uns aber wissen

Sorry, ich bin mit meinem Latein am Ende, vieleicht hilft ja wirklich nur noch ein MemDC
-
Das Flackern beim Dialog Resize lässt sich nicth mit Double Buffering lösen, denn jedes Fenster hat seinen eigenen DC!
Besser WS_CLIPCHILDREN für den Dialog setzen!
-
Ich hab auch noch mal nachgeschaut und glaube, daß das hier genau das richtige für Dich ist:
http://www.codeproject.com/buttonctrl/NoFlicker.asp?df=100&forumid=151835&exp=0&select=1036290
Dort wird, wie schon von Martin vorgeschlagen, WS_CLIPCHILDREN benutzt.
-
Hallo!
Ihr seid echt klasse
Das flackern ist jetzt endlich weitgehend weg. Jetzt hab ich noch das Problem, dass ein Button nicht immer richtig gezeichnet wird. Aber das liegt vermutlich eher an meinem Code 
Vielen vielen Dank nochmal!