Funktion aus OnPaint() aufrufen klappt nicht



  • Hallo zusammen,

    ich habe in meiner Anwendung eine Lampe visualisiert, die entweder aus (=grau) oder ein (=rot) erscheinen soll. Der Status dieser Lampe liegt in einer eigenen Klasse vor und wird von dort über eine öffentliche Memberfunktion abgefragt.

    Ich bin davon ausgegangen, dass ich die Grafik (generell) in OnPaint() zeichnen muss. In Zeile 30 rufe ich nun die Memberfunktion meiner Klasse auf, um den Status der Lampe abzufragen:

    void CMyDlg::OnPaint() 
    {
    	if (IsIconic())
    	{
    		[fürs Posting entfernt, da irrelevant]
    	}
    	else
    	{
    		/* Eigener Code - Start */
    		/* LED anzeigen */
    		CPaintDC dc(this);
    		CBrush BrushActive(RGB(255,0,0));				// Pinsel für aktive LED
    		CBrush BrushInactive(RGB(128,128,128));			// Pinsel für inaktive LED
    		CBrush *pOldBrush=NULL;							// Zeiger auf alten Pinsel
    		CPen Pen(PS_SOLID,1,RGB(0,0,0));				// Zu verwendender Stift
    		CPen *pOldPen=NULL;								// Zeiger auf alten Stift
    		if(m_HIL.GetStatus()==true)					// Pinsel je nach Status auswählen
    			pOldBrush=dc.SelectObject(&BrushActive);
    		else
    			pOldBrush=dc.SelectObject(&BrushInactive);
    		pOldPen=dc.SelectObject(&Pen);					// Stift auswählen
    		dc.Ellipse(690,260,707,277);					// Kreis zeichnen
    		dc.SelectObject(pOldBrush);					// Alten Pinsel wiederherstellen
    		dc.SelectObject(pOldPen);					// Alten Stift wiederherstellen
    		/* Eigener Code - Ende */
    
    		CDialog::OnPaint();
    	}
    }
    

    Leider klappt diese Vorgehensweise nicht. Die if-Abfrage wird immer mit "false" beantwortet und die Lampe bleibt immer dunkel. Interessanterweise ändert sich dies erst dann, wenn ich explizit einen Breakpoint auf die Memberfunktion setze und dann im Einzelschritt den Ablauf verfolge. Erst dann wird die if-Abfrage wie erwartet beantwortet.

    Woran liegt das? Was kann ich tun, um die Lampe richtig zu aktualisieren? Ist es überhaupt richtig, sie in OnPaint() zeichnen zu lassen?

    Grüße
    Steffen



  • Steffen H. schrieb:

    Die if-Abfrage wird immer mit "false" beantwortet und die Lampe bleibt immer dunkel.

    das erste if oder das zweite if?



  • Hast du beachtet, dass deine OnPaint nicht ständig aufgerufen wird!
    Du musst, wenn der Status sich ändert den Client-Bereich neu zeichnen lassen (Funktion Invalidate() oder weitere).
    Könnte man auch mit einem Timer realisieren, der z.b. jede Sekunde den Status prüft und bei Änderung eine Membervariable auf true setzt und dann macht man den Clientbereich mit Invalidate ungültig und veranlasst mit UpdateWindow() das Neuzeichnen (ruft intern dann OnPaint auf).

    Das erklärt auch die Funktion beim Debuggen, da durch den Fensterwechsel zur IDE ständig neu gezeichnet wird.
    OnPaint wird nur aufgerufen wenn etwas neu gezeichnet werden muss und auch nur der Bereich wird aktualisiert, der invalidiert wurde!



  • Ja, das war ein Volltreffer! Wenn ich mit Invalidate() zyklisch den Inhalt neuzeichnen lasse, dann wird auch meine Lampe aktualisiert.

    Ich hatte mir ursprünglich mal in OnPaint() einen Breakpoint gesetzt und gemerkt, dass der ständig aufgerufen wird. Daher dachte ich, dass die Methode wohl automatisch in einem bestimmten Zeitraster ausgeführt wird. Aber jetzt ist es klar, dass sich das selbst bedingt.

    Soweit so gut. Nur, dummerweise flackert jetzt mein gesamter Fensterinhalt, wenn ich Invalidate() anwende. Er zeichnet also alles neu, obwohl sich ja eigentlich nur der kleine Bereich der "Lampe" geändert hat. Wie bringe ich ihm bei, nur diesen Bereich zu aktualisieren? Sobald er in OnPaint() ist, aktualisiert er ja alles. Daher denke ich, dass ich ihm das vorher mitteilen muss. Nur kann ich von außen ja nicht auf meine "Lampe" zugreifen...? Lege ich dafür nun eine Membervariable an?

    Grüße
    Steffen



  • P.s. @lampen-gewerkschaft: Ich meinte also die zweite if-Abfrage!



  • Dann verwende Invalidate halt mit einem Rechteck das den "zu-invalidierenden-Bereich" festlegt. Die Funktion heisst dann vermutlich InvalidateRect(). Müsste jetzt nachgucken, schert mich aber grad nicht...


Anmelden zum Antworten