CDialog fängt an zu spinnen



  • Hallo,

    ich habe einen CDialog, in dem ich ein Bitmap anzeige, auf dem der User Operationen durchführen kann (Rahmen ziehen, Filter drauf anwenden, Kantenerkennung).
    Das funktioniert auch alles genau so, wie es soll. Aber wenn ich eine ganze Weile darin herumprobiere, dann treten plötzlich merkwürdige Fehler auf. Das Bild wird nicht mehr richtig dargestellt, Pixel (die erkannten Formen) werden plötzlich an falscher Stelle dargestellt und Radiobuttons, Editboxen etc. werden falsch dargestellt.
    Meine Vermutung ist ja, dass irgendwie die Speicherverwaltung da aus der Bahn gerät, aber ich sehe nicht, an welcher Stelle da was passieren könnte.

    Ich poste hier mal die Paint-Methode, da ich denke, dass hier am ehesten etwas verkehrt sein könnte:

    void COpenPicture::OnPaint()
    {
    	CDC	*cdc;
    	CRect	rect, selectionFrame[NUM_FRAMES];
    	CBrush	brush;
    
    	CBitmap bit;
    	CPoint	curPoint;
    
       	cdc = m_area.GetDC();
    
    	if(!cdc)
    		return;
    
    	m_area.GetClientRect(&rect);
    	sd.SetZoomFactor((float) rect.Width() / sd.originalBMP.Width());
    
    	// draw bmp to picture control
    	if(activeRadio == IDC_RADIO_ORIG)
    		sd.GetOriginalBMP()->DrawBMP(*cdc, 0, 0, sd.GetZoomFactor());
    	else
    		sd.GetTempBMP()->DrawBMP(*cdc, 0, 0, sd.GetZoomFactor());
    
    	// create and draw frames to select the shadows to the picture control
    	for(int i = 0; i < NUM_FRAMES; i++) {
    
    		// draw selection frame
    		if(frameSelected[i]) {
    			selectionFrame[i].SetRect(selectionFrameMin[i], selectionFrameMax[i]);
    			brush.CreateSolidBrush(RGB(50,90,228));
    			cdc->FrameRect((LPCRECT)selectionFrame[i], &brush);
    			brush.DeleteObject();	// important for being able to create the brush new
    		}
    		else if(leftMouseDown && currentShadow < NUM_FRAMES) {
    			selectionFrame[i].SetRect(selectionFrameMin[i], currentCursorPos);
    			brush.CreateSolidBrush(RGB(247,208,55));
    			cdc->FrameRect((LPCRECT)selectionFrame[i], &brush);
    			brush.DeleteObject();	// important for being able to create the brush new
    			break;
    		}
    
    		// draw ellipses and shadowpoints
    		if(currentShadow >= i) {
    			brush.CreateSolidBrush(RGB(1,0,0));
    
    			if(activeRadio != IDC_RADIO_ORIG) {
    
    				if(ellipseFromPoints) {
    					DrawEllipse(*cdc, pLeftEllipse);
    					DrawEllipse(*cdc, pRightEllipse);
    				}
    				else {
    					// temporarily show the shadowpoints
    					for(uint32 j = 0; j < sd.GetShadowPoints(i)->GetSize(); j++) {
    
    							curPoint = vtp(sd.GetShadowPointAt(i,j));
    							curPoint.x = curPoint.x * sd.GetZoomFactor();
    							curPoint.y = (sd.GetDisplayBMP()->Height() - curPoint.y) * sd.GetZoomFactor();
    							cdc->SetPixel(curPoint, RGB(255,0,0));
    					}
    				// show the ellipse
    				DrawEllipse(*cdc, sd.GetEllipse(i));
    				}
    			}
    			else {
    				// show the ellipse
    				DrawEllipse(*cdc, sd.GetEllipse(i));
    			}
    			brush.DeleteObject();	// important for being able to create the brush new
    		}
    	}
    	CDialog::OnPaint();
    }
    

    m_area ist übrigens ein CStatic und ist für die PictureControl verantwortlich.

    Ich muss dazu sagen, dass ich zum ersten Mal mit MFC arbeite und mich da nicht wirklich gut auskenne. Bin für jede Hilfe dankbar.



  • Hört sich an wie ein GDI-Leck. Ich hab jetzt gerade keine Zeit, um mir das genauer anzusehen, aber sorge dafür, dass du (gerade in OnPaint!) korrekt aufräumst. CloseHandle, ReleaseDC, DeleteObject...



  • Du arbeitest in deinen Schleifen oft mit CreateSolidBrush. Für jeden Brush wird ja ein Handle belegt. Wenn du die Objekte eh immer wieder brauchst, dann erstelle sie doch außerhalb der OnPaint als Member.


  • Mod

    1. Du verwendest nicht CPaintDC! Das musst Du aber unbedingt machen in einem WM_PAINT Handler. Die Nutzung von GetDC hier ist falsch!
    2. Der Aufruf von GetDC erfordert zwingend einen Aufruf von ReleaseDC!


Anmelden zum Antworten