Linien werden schwarz

Olaf Lehmann

Mitglied
Hallo erstmal,
ich hatte ja vor längerer Zeit schon mal paar Fragen zu meinem Telemetryprogramm gestellt.

Im Programm gibt es viele Buttons. Wenn ich die Drücke dann werden Linien dargestellt für Geschwindigkeit, Drehzahl, usw.,usw., usf. Ich kann mehrere Runden darstellen. Dann wird die erste rot gezeichnet, die zweite blau usw.
Wenn ich nun viele Linien zeichne und hoch gezoomt habe werden auf einmal alle Linien schwarz. Oftmals wenn ich gerade die Bildlaufleiste verwende (aber nicht nur dann). Auch verwende ich die Bildlaufleiste viele Male vorher, wobei alles perfekt funktioniert. Ich vermute, dass es mit den vielen Buttons zusammenhängt. Ich bringe hier mal ein Beispile. Den Programmtext des Geschwindigkeit-Buttons:

C++:
void CDateiDlg::OnButton2() 
{
	// TODO: Code für die Behandlungsroutine der Steuerelement-Benachrichtigung hier einfügen
	CClientDC dc(this);
AUSEIN2++;           //GESCHWINDIGKEIT
if(AUSEIN2 % 2) {
CPen Pen;

	int Auswahl=7;   //Auswahl was telemetrisch angezeigt wird Y-Koord
	float YZoom=2.25;
	if(ZeitoWeg==0) XZoom=Strecklang; else XZoom=ZeitX;  //ZoomX für Weg oder Zeit zusammenführen
		for(int x=0;x<AnzRu;x++) {
		if(x==0)	Pen.CreatePen(PenStyle,1,crColor1a);  //RGB(100,0,40)
		if(x==1)	Pen.CreatePen(PenStyle,1,crColor2a);  //RGB(40,0,80)
		if(x==2)	Pen.CreatePen(PenStyle,1,crColor3a);  //RGB(140,150,50)
		if(x==3)	Pen.CreatePen(PenStyle,1,crColor4a);  //RGB(160,160,160)
		dc.SelectObject(Pen);
		int d=0;
			for(d=Runden[Rund[x]];d<Runden[Rund[x]+1];d++) {
				if(R_Wert[d][ZeitoWeg]>Scroll1) {
				dc.MoveTo((R_Wert[d][ZeitoWeg]-Scroll1)/XZoom*breit*Zoo,hoch-m_Wert[d][Auswahl]*YZoom); 
				break;} }
					for(int t=d;t<Runden[Rund[x]+1];t++) {
					if((R_Wert[t][ZeitoWeg]-Scroll1)/XZoom*breit*Zoo>breit)  break;
					dc.LineTo((R_Wert[t][ZeitoWeg]-Scroll1)/XZoom*breit*Zoo,hoch-m_Wert[t][Auswahl]*YZoom); }
			Pen.DeleteObject(); } 
} else { 
	Invalidate(); UpdateWindow(); 
	if(AUSEIN2  % 2) { AUSEIN2++;  OnButton2(); }
	if(AUSEIN3  % 2) { AUSEIN3++;  OnButton3(); }
	if(AUSEIN4  % 2) { AUSEIN4++;  OnButton4(); }	
	if(AUSEIN8  % 2) { AUSEIN8++;  OnButton8(); }
	if(AUSEIN9  % 2) { AUSEIN9++;  OnButton9(); }
	if(AUSEIN10 % 2) { AUSEIN10++; OnButton10(); }
	if(AUSEIN11 % 2) { AUSEIN11++; OnButton11(); }
	if(AUSEIN12 % 2) { AUSEIN12++; OnButton12(); }
	if(AUSEIN14 % 2) { AUSEIN14++; OnButton14(); }
	if(AUSEIN16 % 2) { AUSEIN16++, OnButton16(); }
	if(AUSEIN18 % 2) { AUSEIN18++, OnButton18(); }
	if(AUSEIN20 % 2) { AUSEIN20++; OnButton20(); }
	if(AUSEIN21 % 2) { AUSEIN21++; OnButton21(); }
	if(AUSEIN17 % 2) { AUSEIN17++; OnButton17(); }
	if(AUSEIN22 % 2) { AUSEIN22++; OnButton22(); }
	if(AUSEIN23 % 2) { AUSEIN23++; OnButton23(); }
	if(AUSEIN24 % 2) { AUSEIN24++; OnButton24(); }
	if(AUSEIN25 % 2) { AUSEIN25++; OnButton25(); }
	if(AUSEIN26 % 2) { AUSEIN26++; OnButton26(); }
	if(AUSEIN27 % 2) { AUSEIN27++; OnButton27(); }
	if(AUSEIN28 % 2) { AUSEIN28++; OnButton28(); }
	if(AUSEIN29 % 2) { AUSEIN29++, OnButton29(); }
	if(AUSEIN30 % 2) { AUSEIN30++; OnButton30(); }
	if(AUSEIN31 % 2) { AUSEIN31++; OnButton31(); }
	if(AUSEIN32 % 2) { AUSEIN32++; OnButton32(); }
	if(AUSEIN33 % 2) { AUSEIN33++; OnButton33(); }
	if(AUSEIN34 % 2) { AUSEIN34++; OnButton34(); }
	if(AUSEIN35 % 2) { AUSEIN35++; OnButton35(); }
	if(AUSEIN36 % 2) { AUSEIN36++; OnButton36(); }
	if(AUSEIN37 % 2) { AUSEIN37++; OnButton37(); }
	if(AUSEIN38 % 2) { AUSEIN38++; OnButton38(); }
	if(AUSEIN39 % 2) { AUSEIN39++, OnButton39(); }
	if(AUSEIN40 % 2) { AUSEIN40++; OnButton40(); }
	if(AUSEIN41 % 2) { AUSEIN41++; OnButton41(); }
	if(AUSEIN42 % 2) { AUSEIN42++; OnButton42(); }
	if(AUSEIN43 % 2) { AUSEIN43++; OnButton43(); }
	if(AUSEIN44 % 2) { AUSEIN44++; OnButton44(); }
	CPen Pen;
	Pen.CreatePen(PenStyle,1,RGB(0,0,0));  dc.SelectObject(Pen);
	dc.MoveTo(poi,0);	dc.LineTo(poi,730);
	Pen.DeleteObject();
}
}
Vergesse ich da irgendwas wieder freizugeben? Soweit ich weiss wird CClientDC dc(this) doch automatisch bei Ende der Funktion freigegeben, oder?

Freue mich über jeden Tipp.

MfG
Olaf
 
Zuletzt bearbeitet:

MCoder

Erfahrenes Mitglied
Vergesse ich da irgendwas wieder freizugeben?
Bei "SelectObject()" musst du den ursprünglichen Zustand wiederherstellen. Außerdem erwartet die Methode einen Zeiger als Parameter; da hätte der Compiler eigentlich meckern müssen.
C++:
CPen *pOldPen = dc.SelectObject(&Pen);

// ...

dc.SelectObject(pOldPen);
Den Aufruf von "Pen.DeleteObject();" dagegen kannst du dir sparen. Das wird schon durch den CPen-Destruktor erledigt.

BTW: Bitte die Code-Tags verwenden: [code=cpp] ... [/code].
In der aktuellen Form ist der Code ziemlich unleserlich :)

Gruß
MCoder
 

Olaf Lehmann

Mitglied
Danke!
Nach meine bisherigen Tests scheint es das Problem zu lösen.

Ich hatte bisher

C++:
CPen *pOldPen=dc.SelectObject(&Pen);
nicht verstanden. Ich hab immer gedacht das kann doch nur die neuen Einstellungen speichern und erschien mir von daher fehlerhaft. In der Form wie oben mit = besteht der Compiler übrigens dann auch wier Du schreibst auf das &.

Verstehe ich das richtig, dass in meiner Form immer mehr Zeichenstifte gespeichert werden und irgendwann sind es mehr als mein Computer verkraften kann und dann arbeitet er mit dem Standardstift weiter?
 

MCoder

Erfahrenes Mitglied
Verstehe ich das richtig, dass in meiner Form immer mehr Zeichenstifte gespeichert werden und irgendwann sind es mehr als mein Computer verkraften kann und dann arbeitet er mit dem Standardstift weiter?
Ein neu erzeugter Gerätekontext (DC) hat Standardeinstellungen für jedes der möglichen GDI-Objekte (Pen, Brush, Font usw.). Es kann aber von jeder Art nur immer ein GDI-Objekt ausgewählt sein. Daher gibt SelectObject() einen Zeiger auf das aktuell eingestellte GDI-Objekt zurück. Wenn es die Standardeinstellung ist (also beim allerersten Aufruf von SelectObject() für eine GDI-Objekt-Art), muss dieser Zeiger gemerkt und wieder restauriert werden, weil Windows sonst den dafür verwendeten Speicher nach Löschen des Gerätekontextes nicht mehr freigeben kann. Das gibt dann ein klassisches Memory Leak. Verschärft wird die Situation noch dadurch, dass der für GDI-Objekte verwendbare Speicher begrenzt ist. Da führen schon relativ kleine Sünden zu den seltsamsten Effekten am Bildschirm.

Gruß
MCoder