Farbverfäschungen - Warum?
-
Ich habe folgendes Problem:
Ich habe zwei Simulationen geschrieben, bei denen zwei mal fast das gleiche Phänomen auftritt:
Nach (sehr)kurzer Zeit werden alle Linien, die ich zeichnen lasse einfarbig also haben die gleiche Farbe.
Außerdem werden die Bilder der Simulation nichtmehr gezeichnet.
Mein erster gedanke war, ich hätte einen Pen nicht richtig deleted, aber ich lasse alle Linien von 3 funktionen malen:bool Line(HDC &hdc, int x1, int y1, int x2, int y2, COLORREF rcColor, int size) { HPEN hPen; hPen = CreatePen(PS_SOLID, size, rcColor); SelectObject(hdc, hPen); MoveToEx(hdc, x1, y1, NULL); LineTo(hdc, x2, y2); DeleteObject(hPen); return true; } bool VVect(HDC &hdc, int x1, int y1, int y2, COLORREF rcColor, int size) { HPEN hPen; hPen = CreatePen(PS_SOLID, size, rcColor); SelectObject(hdc, hPen); MoveToEx(hdc, x1, y2, NULL); LineTo(hdc, x1, y1); if(y1 < y2){ MoveToEx(hdc, x1, y2, NULL); LineTo(hdc, x1-5, y2-5); MoveToEx(hdc, x1, y2, NULL); LineTo(hdc, x1+5, y2-5); } else{ MoveToEx(hdc, x1, y2, NULL); LineTo(hdc, x1-5, y2+5); MoveToEx(hdc, x1, y2, NULL); LineTo(hdc, x1+5, y2+5); } DeleteObject(hPen); return true; } bool HVect(HDC &hdc, int x1, int x2, int y, COLORREF rcColor, int size) { HPEN hPen; hPen = CreatePen(PS_SOLID, size, rcColor); SelectObject(hdc, hPen); MoveToEx(hdc, x1, y, NULL); LineTo(hdc, x2, y); if(x1 < x2){ MoveToEx(hdc, x2-5, y+5, NULL); LineTo(hdc, x2, y); MoveToEx(hdc, x2-5, y-5, NULL); LineTo(hdc, x2, y); } else{ MoveToEx(hdc, x2+5, y-5, NULL); LineTo(hdc, x2, y); MoveToEx(hdc, x2+5, y+5, NULL); LineTo(hdc, x2, y); } DeleteObject(hPen); return true; }
Also entweder bin ich blind, oder ich weiß nedd. Aber meiner erarchtens sind die Funktionen sauber oder?
(sie zeichnen eine Linie, einen vertikalen Pfeil und einen Horizontalen Pfeil)Der nächste Witz ist, das die Simulationen unter WinXP wunderbar Funktionieren aber unter 98 besagten Fehler machen.
Dieses unterstützt meine Theorie, das ich irgentwo unsauber gearbeitet haben muss.Eine Anmerkung noch: das einzige, was seine "richtige" Farbe behält sind sachen, die ich mit SetPixel() gemalt habe.
Ich hoffe ihr könnt mir helfen. Es ist mittelprächtig wichtig!
cu> Endy <<
-
Hi Endy!
-
Regel Nummer 1: Alles, was per SelectObject in einen DC selektiert wird, muß auch wieder 'rausselektiert' werden. Das machst Du überhaupt nicht.
BTW: Warum übergibst Du den DC nicht direkt?
-
Der Witz ist das du ein tolles GDI-Leak hinterläßt. Du selektierst ja nichtmal das alte Objekt wieder in den DC.
-
Endy is doof!
"Warum übergibst Du den DC nicht direkt?"
Wozu ne unnötige Kopie anlegen?
thx
-
BTW: Guck mal in dein Tutorial. :p
-
Original erstellt von Endy:
Endy is doof!
-
Ich glaub ich bin noch döfer!
Wie selectiere ich nochmal was raus?
(diese Frage stellen zu müssen is jetz wirklich schande für mich :()
-
Du musst SelectObject nochmal mit dem Rückgabe-Wert des ersten SelectObject aufrufen!
-
*schäm*
-
Wozu ne unnötige Kopie anlegen?
Da hast Du recht. Du solltest die restlichen Integer auch nicht direkt übergeben.
SCNR
-
LOL ^^
naja da hab ich mir dann gedacht: zeiger = 32 bit; integer = 32 bit
kommt aufs gleiche raus
-
oh man, du bist ja völlig durcheinander gekommen mit deiner cs-sucht.
-
So jetz aber ma wieder zurück zum Problem, weil die Linien verfärben sich immernoch nach kurzer Zeit nur, diesmal halt nicht in Rot Blau oder Grün sondern es werden dann alle Linien schwartz.
Freundlich forumliert ist nun die Verzweiflung groß, weil ich jetz nichtmehr die kleinste idee haben könnte, warum die Linien nichtmehr eingefärbt werden. Es is qausi so als wäre Win98 zu faul
hm wie gesagt unter XP gehts und 98 nur ne halbe Sekunde...
-
Hm hat es vielleicht damit was zu tun:
Um alle zu zeichnen habe ich einen Timer gestartet, der dauernt das neue Bild in nen Backbuffer zeichnet und am Ende den Backbuffer und das Fensterbild blittet.
Der Timer hat eine Zeit von 20 milisekunden.
(Timer unter 98 = maximal 18 timerdurchläufe pro sekunde unter XP bzw. NT sind es ja mehr)
-
Das hat mit Timern absolut nicht zu tun. Du produzierst irgendwo Lupenreine Leaks. Und irgendwann geht Dir halt die Puste aus. Auf dem einen Rechner schneller, auf dem anderen langsamer.
Wir haben jetzt drei Funktionen gesehen, in denen Du nicht hinter Dir aufräumst. Sind denn die jetzt sicher in Ordnung? Zeichnest Du noch an anderen Stellen im Programm? Wenn ja, wird dort auch sauber aufgeräumt?
-
Hm also der Timeraufruf ist noch soooooo lang darum kann ich gerne hier posten:
l+=c; //Ströme VVect(hdc, 50, 150, 50, RGB(255,0,0), 1); TextOut(hdc, 55, 55, "I", 1); HVect(hdc, 50, 550, 100, RGB(0,0,255), 1); TextOut(hdc, 535, 80, "t", 1); SetPixel(hdc, (l*c)+50, 100 + YWelle(40, l, 30, fr, 150), RGB(255,0,0)); SetPixel(hdc, (l*c)+50, 100 + YWelle(40, l, 75, fr, 150), RGB(0,255,0)); SetPixel(hdc, (l*c)+50, 100 + YWelle(40, l, 120, fr, 150), RGB(0,0,255)); FillRect(hdc, &WW, reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH))); //Transrapidmodell Rectangle(hdc, (l*c)+50, 350, (l*c)+200, 440); TextOut(hdc, (l*c)+90, 360, "Objekt", 6); //Wanderwelle for(i=0; i<600; i++) { SetPixel(hdc, i+50, 400 + YWelle(15, l, i, fr, lambda), RGB(255,0,0)); } for(i = l*c; i<(l*c)+150;i++) { SetPixel(hdc, i+50, 415 + YWelle(15, l, i, fr, lambda), RGB(0,0,255)); } // MittelTeil(Magnetfeld) for(i=0; i<30; i++) { if(i%3==0){ VVect(hdc, 56+(i*20), 250, 250+YWelle(40, l, 30, fr, 150), RGB(255,0,0), 1); VVect(hdc, 64+(i*20), 250, 250+YWelle(40, l, 30, fr, 150), RGB(255,0,0), 1); VVect(hdc, 51+(i*20), 250, 250+(YWelle(40, l, 30, fr, 150)/2), RGB(255,0,0), 1); VVect(hdc, 69+(i*20), 250, 250+(YWelle(40, l, 30, fr, 150)/2), RGB(255,0,0), 1); } if(i%3==1){ VVect(hdc, 56+(i*20), 250, 250+YWelle(40, l, 75, fr, 150), RGB(0,255,0), 1); VVect(hdc, 64+(i*20), 250, 250+YWelle(40, l, 75, fr, 150), RGB(0,255,0), 1); VVect(hdc, 51+(i*20), 250, 250+(YWelle(40, l, 75, fr, 150)/2), RGB(0,255,0), 1); VVect(hdc, 69+(i*20), 250, 250+(YWelle(40, l, 75, fr, 150)/2), RGB(0,255,0), 1); } if(i%3==2){ VVect(hdc, 56+(i*20), 250, 250+YWelle(40, l, 120, fr, 150), RGB(0,0,255), 1); VVect(hdc, 64+(i*20), 250, 250+YWelle(40, l, 120, fr, 150), RGB(0,0,255), 1); VVect(hdc, 51+(i*20), 250, 250+(YWelle(40, l, 120, fr, 150)/2), RGB(0,0,255), 1); VVect(hdc, 69+(i*20), 250, 250+(YWelle(40, l, 120, fr, 150)/2), RGB(0,0,255), 1); } Rectangle(hdc, 50+(i*20), 245, 70+(i*20), 255); } Frontbuf = GetDC(hwnd); BitBlt(Frontbuf, -40, 0, 650, 440, hdc, 0, 0, SRCCOPY); ReleaseDC(hwnd, Frontbuf); if(l>600) { l = 0; SetRect(&WW, 0, 0, 550, 500); FillRect(hdc, &WW, reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH))); SetRect(&WW, 45, 200, 650, 440); InvalidateRect(hwnd, NULL, true); }
Also ich sehe da absolut nix, was ein Leak produzieren könnte...
Und mit dem Rechner an sich hat das auchnix zu tun, weil der 98 Rechner 1. doppelt soviel Ram wie der XP rechner hat 2. neuer und schneller ist
Das hängt schon mit dem OS zusammen bzw. unter 98 muss man scheinbar irgentwas noch anders machen.
*verzweifel*
-
Du zeichnest in WM_TIMER? Zeichnungen gehören in WM_PAINT. Ruf doch als Ergebnis auf WM_TIMER einfach InvalidateRect auf und fertig ist's. Und Außerdem weiß ich noch immer nicht, wie die korrigierte Version von beispielsweise VVect aussieht.
Das hängt schon mit dem OS zusammen bzw. unter 98 muss man scheinbar irgentwas noch anders machen.
Das hängt ausschließlich mit Dir zusammen, glaub mir das. Dein Programm ist noch fehlerhaft.
-
Original erstellt von -King-:
**Du zeichnest in WM_TIMER? Zeichnungen gehören in WM_PAINT. Ruf doch als Ergebnis auf WM_TIMER einfach InvalidateRect auf und fertig ist's.
**Warum sollte man den langsameren Umweg über WM_PAINT gehen. In WM_TIMER geht das schon in Ordnung, wenn er mit GetDC und ReleaseDC arbeitet.
Windows98 reagiert, wie ich auch schon festgestellt habe, etwas empfindlicher, als spätere Windows-Versionen, auf Veränderungen von DCs. Irgendwo in deinem Programm selektierst du garantiert was rein, aber nicht wieder raus oder du löschst etwas, obwohl es noch drin ist!
-
In WM_TIMER geht das schon in Ordnung, wenn er mit GetDC und ReleaseDC arbeitet.
Ja, sicher. Bis er den Timer mal anhält, um sich die Zeichnung zu betrachten. Dann versehentlich ein anderes Fenster über die Client-Area gelegt. Und jetzt sendet er aus WM_PAINT einmal WM_TIMER an das Fenster. Na, ich weiß nicht. Ich da jedenfalls kein Freund von.
Außerdem verwendet er unter Umständen sogar InvalidateRect in seiner TimerProc.