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.
-
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!