Warum flackert mein Dialog, wenn ich ihn größer ziehe?



  • 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!



  • Hm, also ich hab mir das nochmal genauer angeschaut und getestet.
    Wenn ich das Fenster schön ganz langsam größer ziehe, funktioniert alles super. Mache ich jetzt mit der Maus eine ganz schnelle Bewegung beim Fenster größer ziehen, bleibt einer der Buttons an der alten Stelle stehen. Ohne das Flag WS_CLIPCHILDREN passiert das nicht. Wie kann ich das jetzt noch abfangen?



  • Ist denn das ein besonderer Button?



  • Nein, der ist genauso angelegt wie die anderen auch. Das einzige "besondere" daran ist die Tatsache, dass er als letzter angelegt wird und nicht trapezförmig ist wie die anderen, sondern achteckig in der Mitte aller anderen Buttons 😕

    EDIT: Eine noch genauere Analyse. Vielleicht kann mir ja noch irgendjemand helfen:
    Ich denke, es liegt (wie gesagt) am WS_CLIPCHILDREN. Dieser Fensterstil bewirkt ja, dass der Bereich, in dem sich die Child-Windows befinden, ausgespart wird beim neuen Zeichnen. Allerdings werden in der OnSize()-Methode alle Buttons mit neuen Koordinaten belegt und beim langsamen Ziehen ja auch neu gezeichner. Ich verwende auch noch zwei kleine Static-Controls in meinem Dialog, bei denen mit dem Fensterstil WS_CLIPCHILDREN der Hintergrund verschwindet und der Fensterhintergrund erscheint. Das könnte man evtl. mit OnCtlColor lösen, oder?
    Ich poste hier mal meine OnSize-Methode hin, vielleicht kann ja jemand meinen Fehler entdecken?

    void CStartdialog3Dlg::OnSize(UINT nType, int cx, int cy) 
    {
    	CDialog::OnSize(nType, cx, cy);
    
    	CRect rect;
    	CRgn rgn, rgnDialogZiehen, rgnDialogVergroessern;
    	GetClientRect(&rect);
    
    	if(rect.Height() < rect.Width())
    		offset = runden((double)rect.Height() / 3);
    	else
    		offset = runden((double)rect.Width() / 3);
    
    	rect.SetRect(rect.left, rect.top, rect.left + 3 * offset, rect.top + 3 * offset);
    	x = rect.left;
    	y = rect.top;
    	breite = rect.Width();
    	hoehe = rect.Height();	
    
    	// Array für Eckpunkte des Dialogs
    	CPoint p_dialog[8];
    
    	// Hilfsvariablen
    	int tmp1 = runden(0.1 * (double)offset);
    	int tmp2 = runden(0.05 * (double)offset);
    
    	// Größen, die für die Berechnung des Achtecks gebraucht werden
    	kantenlaenge = offset;
    	hilfskante = runden((double)kantenlaenge / sqrt(2));
    	kantenlaengeInnen = offset - 12 * tmp2;
    	hilfskanteInnen = runden((double)kantenlaengeInnen / sqrt(2));
    	kantenlaengeRand = offset - 2 * tmp2;
    	hilfskanteRand = runden((double)kantenlaengeRand / sqrt(2));
    
    	// Eckpunkte des Dialogs erzeugen
    	CPoint d1(offset, tmp1);
    	CPoint d2(2 * offset, tmp1);
    	CPoint d0(d1.x - hilfskante, d1.y + hilfskante);
    	CPoint d3(d2.x + hilfskante, d2.y + hilfskante);
    	CPoint d4(d3.x, d3.y + kantenlaenge);
    	CPoint d5(d2.x, d4.y + hilfskante);
    	CPoint d6(d1.x, d5.y);
    	CPoint d7(d0.x, d4.y);
    
    	// Eckpunkte in Array speichern
    	p_dialog[0] = d0;
    	p_dialog[1] = d1;
    	p_dialog[2] = d2;
    	p_dialog[3] = d3;
    	p_dialog[4] = d4;
    	p_dialog[5] = d5;
    	p_dialog[6] = d6;
    	p_dialog[7] = d7;
    
    	// 8-Eck erzeugen und zwei Regionen zum verschieben/vergrößern dransetzen
    	rgn.CreatePolygonRgn(p_dialog, 8, ALTERNATE);
    	rgnDialogZiehen.CreateEllipticRgn(d1.x - tmp1, 0, d1.x + tmp1, d1.y + tmp1);
    	CombineRgn(rgn, rgn, rgnDialogZiehen, RGN_OR);
    	rgnDialogVergroessern.CreateEllipticRgn(d5.x - tmp1, d5.y - tmp1, d5.x + tmp1, d5.y + tmp1);
    	CombineRgn(rgn, rgn, rgnDialogVergroessern, RGN_OR);
    	SetWindowRgn(static_cast<HRGN>(rgn.GetSafeHandle()), TRUE);
    
    	if(m_buttonsInitialisiert)
    	{
    		// Innen - Eckpunkte des Achtecks innen erzeugen
    		CPoint b(d1.x + 6 * tmp2, d1.y + 14 * tmp2);
    		CPoint c(d2.x - 6 * tmp2, d2.y + 14 * tmp2);
    		CPoint a(b.x - hilfskanteInnen, b.y + hilfskanteInnen);
    		CPoint d(c.x + hilfskanteInnen, c.y + hilfskanteInnen);
    		CPoint e(d.x, d.y + kantenlaengeInnen);
    		CPoint f(c.x, e.y + hilfskanteInnen);
    		CPoint g(b.x, f.y);
    		CPoint h(a.x, e.y);	
    
    		// Außen - Eckpunkte der Buttons erzeugen
    		CPoint b_(d1.x + tmp2, d1.y + tmp2 + tmp2);
    		CPoint c_(d2.x - tmp2, d2.y + tmp2 + tmp2);
    		CPoint a_(b_.x - hilfskanteRand, b_.y + hilfskanteRand);
    		CPoint d_(c_.x + hilfskanteRand, c_.y + hilfskanteRand);
    		CPoint e_(d_.x, d_.y + kantenlaengeRand);
    		CPoint f_(c_.x, e_.y + hilfskanteRand);
    		CPoint g_(b_.x, f_.y);
    		CPoint h_(a_.x, e_.y);
    
    		// Vektor anlegen, der die Eckpunkte der Buttons aufnimmt
    		std::vector<CPoint> pts;
    
    		// Button1 anlegen
    		pts.push_back(b_);
    		pts.push_back(c_);
    		pts.push_back(c);
    		pts.push_back(b);
    		m_button1.SetPoints(pts);
    		m_button1.setRgn();
    
    		// Button2 anlegen
    		pts.clear();
    		pts.push_back(c_);
    		pts.push_back(d_);
    		pts.push_back(d);
    		pts.push_back(c);
    		m_button2.SetPoints(pts);
    		m_button2.setRgn();
    
    		// Button3 anlegen
    		pts.clear();
    		pts.push_back(d);
    		pts.push_back(d_);
    		pts.push_back(e_);
    		pts.push_back(e);
    		m_button3.SetPoints(pts);
    		m_button3.setRgn();
    
    		// Button4 anlegen
    		pts.clear();
    		pts.push_back(e_);
    		pts.push_back(f_);
    		pts.push_back(f);
    		pts.push_back(e);
    		m_button4.SetPoints(pts);
    		m_button4.setRgn();
    
    		// Button5 anlegen
    		pts.clear();
    		pts.push_back(g);
    		pts.push_back(f);
    		pts.push_back(f_);
    		pts.push_back(g_);
    		m_button5.SetPoints(pts);
    		m_button5.setRgn();
    
    		// Button6 anlegen
    		pts.clear();
    		pts.push_back(g);
    		pts.push_back(g_);
    		pts.push_back(h_);
    		pts.push_back(h);
    		m_button6.SetPoints(pts);
    		m_button6.setRgn();
    
    		// Button7 anlegen
    		pts.clear();
    		pts.push_back(a_);
    		pts.push_back(a);
    		pts.push_back(h);
    		pts.push_back(h_);
    		m_button7.SetPoints(pts);
    		m_button7.setRgn();
    
    		// Button8 anlegen
    		pts.clear();
    		pts.push_back(a_);
    		pts.push_back(b_);
    		pts.push_back(b);
    		pts.push_back(a);
    		m_button8.SetPoints(pts);
    		m_button8.setRgn();
    
    		// Button9 anlegen
    		pts.clear();
    		pts.push_back(a);
    		pts.push_back(b);
    		pts.push_back(c);
    		pts.push_back(d);
    		pts.push_back(e);
    		pts.push_back(f);
    		pts.push_back(g);
    		pts.push_back(h);
    		m_button9.SetPoints(pts);
    		m_button9.setRgn();
    
    		rcVerschieben.SetRect(d1.x - runden(0.1 * (double)offset), 0, d1.x + tmp1, d1.y + tmp1);
    		rcGroesseAendern.SetRect(d5.x - tmp1, d5.y - tmp1, d5.x + tmp1, d5.y + tmp1);
    
    		if(symbol_verschieben->m_hWnd)
    			symbol_verschieben->MoveWindow(rcVerschieben, TRUE);
    		if(symbol_groesse_aendern->m_hWnd)
    			symbol_groesse_aendern->MoveWindow(rcGroesseAendern, TRUE);
    	}
    }
    

  • Mod

    Das kann auch an einem fehlenden WS_CLIPSIBLINGS liegen.



  • Habe ich schon ausprobiert 😞 Vor dem Aufruf

    CDialog::OnInitDialog();
    

    in OnInitDialog() gibts einen Fehler, wenn ich das Programm starte, und wenn ich es hinter den Aufruf schreibe, ändert sich nichts...

    Ich habe vorhin beim suchen was von BeginDeferWindowPos usw. gelesen. Kann mir das weiterhelfen? Wenn ja - wie und wo wird es benutzt?

    EDIT: Wenn ich den Dialog schnell vergrößert habe und einer der Buttons nicht auf der aktuellen Position ist, wird er an die aktuelle Position gezeichnet, wenn ich mit der Maus drüberfahre. Kann ich dieses neu zeichnen nach dem resizen irgendwie erzwingen, nachdem ich die Maus wieder losgelassen habe und der Resize beendet ist?


  • Mod

    Das macht man nicht in dem Dialog in OnInitDialog, sondern man gibt es direkt als Stil bei jedem Control im Dialogeditor an!



  • Hat leider trotzdem nichts gebracht. Ich weiß echt nicht was ich noch machen soll....



  • Hallo zusammen,

    ich hab nun auch eine Lösung gefunden für das Problem der Buttons, die teilweise am Ende eines OnSize() nicht nachgezeichnet wurden. Ich rufe jetzt in der OnPaint()-Methode des Dialogs statt

    CDialog::OnPaint();
    

    einfach

    RedrawWindow();
    

    auf und schon funktioniert es 😃



  • Glückwunsch! 😃
    Genügt evtl. auch ein Invalidate(FALSE)/*oder TRUE*/ am Ende der OnSize() ?


Anmelden zum Antworten