Paint-Nachricht kommt bei Maximieren nicht bei den Kindfenstern an



  • Hiho,

    meine GUI hat folgenden Aufbau: ich habe mit dem Assistenten eine SDI-Anwendung ohne Dokumenten-Verwaltung erzeugt (VS2005 Prof). Bei dem Kindfenster habe ich die View rausgeschmissen und durch eine eigene Klasse, welche von CWnd erbt, ersetzt. Dieses besitzt nun wiederum 2 Kindfenster. Der Aufbau ist im Bild dargestellt:

    http://img190.imageshack.us/img190/5614/mfcgui.png

    Wenn ich nun mein Bild maximiere, kommt kein Paint bei den Kindfenstern der 2. Ebene an (also die Fenster, welche in meinem View-Fenster sind). Ich nehme mal an, das liegt irgendwie daran, weil meine View nicht von CView erbt sondern von CWnd?

    Fangen tue ich in den ganzen Kindfenstern noch die Erasebackground und mache da nur return TRUE. Die Kindfenster der View decken das View-Fenster zu 100% ab, daher brauche ich kein Löschen mit einer Hintergrundfarbe.
    Ach ja, und bei dem View-Fenster fange ich auch die WM_SIZE Methode und rufe dann für die beiden Kindfenster SetWindowPos und habe NICHT das Flag SWP_NOREDRAW gesetzt. Bei Flags geht nur 0 rein. Warum kommt da das Neuzeichnen nicht?
    Falls ich mich zu unklar ausgedrückt habe, bitte nachfragen^^
    Weiß wer Rat? Was muss ich noch fangen und durchleiten, dass meine GUI letztlich richtig neu gezeichnet wird.

    MfG Pellaeon



  • Eine weitere Frage hätte ich noch dazu: wenn ich meine Anwendung offen habe, eine andere darüber lege udn dann wieder zu meiner wechsel, zeichnet er sich nicht neu. Ich msss das Fenster erst am Rahmen anpacken, um ein Neuzeichnen auszulösen.

    Es scheint, als wenn das View seine Kindfenster nicht immer über das Neuzeichen informiert? Ich lege die Fenster folgender Maßen an:

    int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    	if (CWnd::OnCreate(lpCreateStruct) == -1) return -1;
    
    	//
    	m_pLeftWnd = new CComponentWnd();
    	m_pLeftWnd->Create(0,0,WS_CHILD | WS_VISIBLE | WS_BORDER,CRect(0,0,0,0),this,IDR_COMPONENTWND);	
    
    	m_pGraphicWnd = new COpenSGWnd();	
    	m_pGraphicWnd->Create(0,0,WS_CHILD | WS_VISIBLE,CRect(0,0,0,0),this,IDR_OPENSGWND);	
    
    	return 0;
    }
    

    Die OnSize sieht so aus:

    void CChildView::OnSize(UINT nType, int cx, int cy)
    {
    	CWnd::OnSize(nType, cx, cy);
    
    	m_pLeftWnd->SetWindowPos(&wndTop,0,0,cx * 0.15f,cy,SWP_NOOWNERZORDER);
    	m_pGraphicWnd->SetWindowPos(&wndTop,cx * 0.15f,0,cx,cy,SWP_NOOWNERZORDER);
    }
    

  • Mod

    Dann gibt es überlagerte Fenster. Wenn WM_PAINT nicht ankommt denkt Windows eines Deiner Fenster liegt über einem anderen.

    1. Deine Kalkulation ist auch falsch. Zumindest die Breite des zweiten Fensters musst Du ja auch korrigieren um die Weite des ersten Fensters.
    2. Ist das mit der Angabe von wndTop Unfug. Du soltest in keinem Fall die Z-Order hier ändern. Aber das machst Du. SWP_NOZORDER muss gesett werden.
    Nimm doch einfach MoveWindow... dann machst Du auch keine Fehler 😉



  • Hallo Martin,

    stimmt die Berechnung war falsch. War Viewport-Angabe-Art von OpenGL^^
    Ich hab es jetzt folgender Maßen ersetzt:

    void CChildView::OnSize(UINT nType, int cx, int cy)
    {
    	CWnd::OnSize(nType, cx, cy);	
    
    	m_pLeftWnd->MoveWindow(0,0,cx * 0.15f,cy);
    	m_pGraphicWnd->MoveWindow(cx * 0.15f,0,cx * 0.85f,cy);
    }
    

    Einwas zerschießt mir jetzt noch die Grafik teilweise. In dem COpenSGWnd wird ein Kamerabild dargestellt. Da ich keine konstanten 30 fps brauche, habe ich einfach ind er OnPaint nach meinem Zeichen-Code ein "Invalidate();" gemacht. Das scheint er aber auch nicht zu mögen. Wenn ich das drinne lasse, habe ich im Vollbild Fehler in der Symbolleiste (rechts hab ich dann einen weißen Balken udn wenn ich die Symbolleiste abdocken will, hängt sich das Programm auf).
    Ein PostMessage mit WM_PAINT funktioniert auch nicht. Gibt es noch andere Möglichkeiten, ein zyklisches Neuzeichnen auszulösen direkt in der OnPaint? Ansonsten würde mir nur der Timer einfallen, der könnte aber dann zu grob sein oder ich muss das rendern in einen Thread auslagern, der das Fenster immer neu zeichnet.

    MfG Pellaeon


  • Mod

    Invalidate im OnPaint Handler ist ein nono!
    WM_PAINT sendet man auch nicht. Das ist genauso verboten:
    http://blog.m-ri.de/index.php/2007/12/24/die-unsitte-windows-interne-nachrichten-zu-versenden/

    Du hast es schon richtig angemerkt: Bau Dir einen Timer, immer wenn der fällt mach einen Invalidate.
    Das ist die sichere und korrekte Methode.

    Da Deine OnPaint Methode sowieso nur aufgerufen wird, wenn gerade ncihst los ist, kanst Du auch nicht garantieren, dass Sie zeitnah ausgeführt wird.
    Ansonsten dieses Fenster in einen anderen Thread auslagern (nicht das Zeichnen!).


Anmelden zum Antworten