GDI Problem - Verschwinden von gewählten Brushes sowie Flimmern
-
Hallo,
ich habe eine GDI Routine geschrieben, die ich in einem Programm brauche. Es soll ein simples, 2D Fenster dargestellt werden. Die Zeichnung wird nur für ein Fenster durchgeführt, und alle 50 Millisekunden mittels Windows Timer aktualisiert.
Dies sollte keine zu hohe Anforderung an GDI stellen, trotzdem bemerke ich folgende Probleme bei jeder Ausführung meiner Anwendung:o Das Gezeichnete Objekt flimmert sehr stark.
o Die Brusheinstellungen verschwinden, nach ca. 5 Sekunden Programmlaufzeit. Das heißt, meine Farben die ich eingestellt habe, werden am Anfang angezeigt, dann werden die Zeichnungen plötzlich schwarz, und flimmern sogar noch mehr.Ich gehe davon aus, ich mache etwas brutal falsch, komme aber nicht drauf und suche schon den ganzen Tag. Wer kann mir helfen? Als Anhang der Code:
HBRUSH brush1; HPEN pen1; Rectangle(hdc,drect.left,drect.top,drect.right,drect.bottom); MoveToEx(hdc,drect.left,drect.top+GFX_CAPTION_HEIGHT,NULL); LineTo(hdc,drect.right,drect.top+GFX_CAPTION_HEIGHT); // Farbverlauf Captionlinie sofern highcolor aktiviert. // Falls nicht, einfach einfärben. if(!highcolor) { brush1=CreateSolidBrush(GFX_CAPTION_COLORSOLID); pen1=CreatePen(PS_NULL,0,RGB(255,255,255)); SelectObject(hdc,brush1); SelectObject(hdc,pen1); Rectangle(hdc,drect.left+1,drect.top+1,drect.right,drect.top+1+ (GFX_CAPTION_HEIGHT)); DeleteObject(brush1); DeleteObject(pen1); } else { for(int i=0;i<GFX_CAPTION_HEIGHT-1;i++) { COLORREF shadecolor; shadecolor=RGB(GFX_CAPTION_SHADE_R+ (GFX_CAPTION_SHADEINCREMENT*i),GFX_CAPTION_SHADE_G+ (GFX_CAPTION_SHADEINCREMENT*i),GFX_CAPTION_SHADE_B+ (GFX_CAPTION_SHADEINCREMENT*i)); pen1=CreatePen(PS_SOLID,1,shadecolor); SelectObject(hdc,pen1); MoveToEx(hdc,drect.left+1,drect.top+1+i,NULL); LineTo(hdc,drect.right-1,drect.top+1+i); DeleteObject(pen1); } } // Titel in Caption zeichnen RECT titlerect; titlerect.left=drect.left+4; titlerect.top=drect.top+2; titlerect.right=drect.right; titlerect.bottom=drect.bottom; HFONT titlefont= CreateFont(16,0,0,0,FW_BOLD,false,false,false,DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH, "verdana"); SelectObject(hdc,titlefont); SetTextColor(hdc,GFX_CAPTION_FORECOLOR); SetBkMode(hdc,TRANSPARENT); DrawText(hdc,dtitle.c_str(),dtitle.length(),&titlerect,DT_LEFT); DeleteObject(titlefont);Ich habe diesen Code in einer seperaten Klasse als Methode... der Aufruf erfolgt bei WM_PAINT wie folgt:
hdc=BeginPaint(hwnd,&ps); BlablaKlasse.BlablaZeichenfunktion(); EndPaint(hwnd,&ps); break;Danke für eure Zeit.

Hoffe auf Antwort...!
-
Du musst dir den Rückgabewert von SelectObject merken und den alten Pen/Brush wieder in den DC zurückselektieren bevor du brush1/pen1 löscht.
Zum Flackern: DoubleBuffering
-
Danke für die schnelle Antwort, leider muss ich das Forum nochmal mit dieser Frage belasten, weil für mich noch nicht alles geklärt ist.
Also ich merke mir nun die zurückgegebenen Handles von SelectObject und lösche sie später. Nun verschwinden die Brushes nicht nach 5 Sekunden sondern nach
30-60... Ich mach also noch etwas falsch. Was meinst du, mit "zurückselektieren"? Ich verstehe den Sinn nicht ganz.Am Double-Buffering habe ich mich jetzt mal versucht, funktioniert aber leider nicht ganz wie gewünscht... Was ist hier falsch? Würde mich freuen, wenn sich jemand den folgenden Code nochmal kurz anschauen könnte:
HDC hdc; HDC showdc; PAINTSTRUCT ps; HBITMAP backbuffer; RECT wndrect; HGDIOBJ oldbuffer; ... case WM_PAINT: showdc=BeginPaint(hwnd,&ps); hdc=CreateCompatibleDC(showdc); backbuffer=CreateCompatibleBitmap(showdc,wndrect.right-wndrect.left,wndrect.bottom-wndrect.top); oldbuffer=SelectObject(hdc,backbuffer); zeichenfunktion(HDC hdc); //Hier wird das Handle des CompatibleDCs //übergeben. BitBlt(hdc,0,0,wndrect.right-wndrect.left,wndrect.bottom-wndrect.top,hdc,0,0,SRCCOPY); DeleteObject(backbuffer); DeleteDC(hdc); EndPaint(hwnd,&ps); DeleteObject(oldbuffer); break;
-
Entschuldigung für das Doppelpost...
Bei BitBlt muss das erste "hdc" natürlich "showdc" heißen... Habe ich falsch hier eingetragen. Muss mich hier mal langsam registrieren, dann kann man ja editieren.
-
Hast du dir schonmal die Anzahl der GDI-Objekte im Taskmanager angeschaut?
GDI-Neuling schrieb:
Was meinst du, mit "zurückselektieren"? Ich verstehe den Sinn nicht ganz.
Naja so:
brush1=CreateSolidBrush(GFX_CAPTION_COLORSOLID); pen1=CreatePen(PS_NULL,0,RGB(255,255,255)); oldBrush = SelectObject(hdc,brush1); oldPen = SelectObject(hdc,pen1); Rectangle(hdc,drect.left+1,drect.top+1,drect.right,drect.top+1+ (GFX_CAPTION_HEIGHT)); SelectObject(hdc,oldBrush); SelectObject(hdc,oldPen); DeleteObject(brush1); DeleteObject(pen1);Warum man das macht - du kannst/darfst/sollst nichts löschen, was noch in einen DC selektiert ist

-
Danke für deine bisherige Hilfe!

Das Back-Buffering funktioniert nun einwandfrei, mit dem "GDI-Leck" hab ich immernoch Probleme, auch wenn sich das nun auf ein Auftreten nach 2-3 Minuten reduziert hat. Leider kann ich die Stelle nicht sehen, wodurch dieser Fehler begünstigt wird:HBRUSH brush1; HPEN pen1; HGDIOBJ oldbrush; HGDIOBJ oldpen; HGDIOBJ oldfont; Rectangle(hdc,drect.left,drect.top,drect.right,drect.bottom); MoveToEx(hdc,drect.left,drect.top+GFX_CAPTION_HEIGHT,NULL); LineTo(hdc,drect.right,drect.top+GFX_CAPTION_HEIGHT); if(!highcolor) { brush1=CreateSolidBrush(GFX_CAPTION_COLORSOLID); pen1=CreatePen(PS_NULL,0,RGB(255,255,255)); oldbrush=SelectObject(hdc,brush1); oldpen=SelectObject(hdc,pen1); Rectangle(hdc,drect.left+1,drect.top+1,drect.right,drect.top+1+(GFX_CAPTION_HEIGHT)); SelectObject(hdc,oldbrush); SelectObject(hdc,oldpen); DeleteObject(brush1); DeleteObject(pen1); } else { for(int i=0;i<GFX_CAPTION_HEIGHT-1;i++) { COLORREF shadecolor; shadecolor=RGB(GFX_CAPTION_SHADE_R+(GFX_CAPTION_SHADEINCREMENT*i),GFX_CAPTION_SHADE_G+(GFX_CAPTION_SHADEINCREMENT*i),GFX_CAPTION_SHADE_B+(GFX_CAPTION_SHADEINCREMENT*i)); pen1=CreatePen(PS_SOLID,1,shadecolor); oldpen=SelectObject(hdc,pen1); MoveToEx(hdc,drect.left+1,drect.top+1+i,NULL); LineTo(hdc,drect.right-1,drect.top+1+i); SelectObject(hdc,oldpen); DeleteObject(pen1); } } RECT titlerect; titlerect.left=drect.left+4; titlerect.top=drect.top+2; titlerect.right=drect.right; titlerect.bottom=drect.bottom; HFONT titlefont= CreateFont(16,0,0,0,FW_BOLD,false,false,false,DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,"verdana"); oldfont=SelectObject(hdc,titlefont); SetTextColor(hdc,GFX_CAPTION_FORECOLOR); SetBkMode(hdc,TRANSPARENT); DrawText(hdc,dtitle.c_str(),dtitle.length(),&titlerect,DT_LEFT); SelectObject(hdc,oldfont); DeleteObject(titlefont); DeleteObject(oldpen); DeleteObject(oldbrush); DeleteObject(oldfont);
-
flenders schrieb:
Hast du dir schonmal die Anzahl der GDI-Objekte im Taskmanager angeschaut?
Steigt die Anzahl der GDI-Objekte mit der Zeit? Falls nicht dürfte der Fehler an anderer Stelle zu suchen sein

-
Berichtige mich wenn ich falsch liege, aber ich habe keine Stelle im Windows 98 Taskmanager gefunden, wo man die GDI-Objekte hätte sehen können. Kannst du mir genau schreiben, was du meinst? Danke für deine Geduld...
-
Lad dir "Process Explorer"