Bild verschwindet manchmal
-
Hi,
ich habe ein seltsames Problem. Ich lasse mir von GDI ein Bitmap zeichnen. Das klappt wunderbar:HANDLE bild = LoadImage(NULL, iniFilePath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); HDC hdcMem = CreateCompatibleDC(hdc); HGDIOBJ hbmOld = SelectObject(hdcMem, bild); BITMAP bm; GetObject(bild, sizeof(bm), &bm); pt[0] = stretchbitmap((akt.right-200 -akt.left),(akt.bottom - akt.top),bm.bmWidth,bm.bmHeight); StretchBlt(hdc, 0, 0, pt[0].x , pt[0].y , hdcMem, 0, 0, bm.bmWidth, bm.bmHeight,SRCCOPY); SelectObject(hdcMem, hbmOld); DeleteDC(hdcMem);danach zeichne ich Kreisbögen über dises Bild. Auch das funktioniert. Nun verschiebe ich die Kreisbögen über die Tastatur.(Accelerator) Bleibe ich lang auf einer Taste, so wird der Kreisring ständig verschoben. Damit man nicht all die alten Ringe sieht, lasse ich das Bild darunter auch immer neu zeichnen.
Bleibe ich zu lang auf einer Taste, also wird mein Bild zu oft/schnell gezeichnet, so verschwindet es irgendwann! Über eine Auswahl kann ich das Bild wieder laden. Aber auch das geht nicht! Irgend ein anderes Bild aber schon.
Habt ihr ein Plan wie ich das besser machen könnte?
Mfg Mo3bius
-
WM_PAINT erzwingen mit InvalidateRect(), wenn sich etwas in der Darstellung verändert hat.
-
Ich habe die Funktion mir mal angesehen. Wenn ich das richtig verstanden habe, dann ruft diese Funktion WM_PAINT auf und zeichnet dann das Fenster/alles neu?
InvalidateRect(NULL, NULL, TRUE);So habe ich das mal versucht. Das ändert aber leider nix.
Gibt es keine Möglichkeit nur einen Teil meines Fensters neu zu zeichnen? Also kann ich das Bitmap im Hintergrund einfach stehen lassen und den Kreisbogen neu zeichnen? Dann hätte ich das Problem nicht...
Mfg Mo3bius
-
Du darfst NUR in WM_PAINT zeichen... und alles was Du nicht nochmals zeichnen willst, merke Dir z.B: in einem MemoryDC/Bitmap und kopieren es bei WM_PAINT einfach wieer ins BIld.
-
Warum darf ich nur in WM_PAINT zeichnen? Ich kann doch auch woanders was zum Zeichnen definieren?
Ich denke ich komme dem Problem näher. Ich habe hier einen interessanten Beitrag gefunden:
http://www.wer-weiss-was.de/theme9/article1082314.html
Hier nochmal mein Code:
long layout::paint(HDC hdc, RECT aktiv, bool background) { if (background) {akt = aktiv; } HPEN hpen, hpen2,hpen3,hpen4, hpenOld; HBRUSH hbrush, hbrushold; long i; char text[1000]; hpen = CreatePen(PS_SOLID, 2, RGB(0, 255, 0)); // Select the new pen and brush, and then draw. hpen2 = CreatePen(PS_SOLID, 4, RGB(255, 255, 0)); // Select the new pen and brush, and then draw. hpen3 = CreatePen(PS_SOLID, 1, RGB(0, 0, 255)); // Select the new pen and brush, and then draw. hpen4 = CreatePen(PS_SOLID, 2, RGB(255, 0, 0)); // Select the new pen and brush, and then draw. hpenOld = (HPEN)SelectObject(hdc, hpen); if(background) { SelectObject(hdc, hpen3); hbrush = CreateSolidBrush(RGB(255, 255, 255)); // Select the new pen and brush, and then draw. hbrushold = (HBRUSH)SelectObject(hdc, hbrush); Rectangle(hdc,akt.left,akt.top,akt.right-200,akt.bottom); HANDLE bild = LoadImage(NULL, iniFilePath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); /// HBITMAP tmpbitmap = CreateCompatibleBitmap(hdc, akt.right-200 -akt.left , akt.bottom - akt.top); HDC hdcMem = CreateCompatibleDC(hdc); HGDIOBJ hbmOld = SelectObject(hdcMem, bild); BITMAP bm; GetObject(bild, sizeof(bm), &bm); pt[0] = stretchbitmap((akt.right-200 -akt.left),(akt.bottom - akt.top),bm.bmWidth,bm.bmHeight); StretchBlt(hdc, 0, 0, pt[0].x , pt[0].y , hdcMem, 0, 0, bm.bmWidth, bm.bmHeight,SRCCOPY); SelectObject(hdcMem, hbmOld); DeleteDC(hdcMem); // ReleaseDC(hWnd,hdcMem); } SelectObject(hdc, hpen); DeleteObject(hbrush); DeleteObject(hpen3); return 0; }Mach ich das richtig? Oder fehlt da noch was? Also muss ich noch irgendwas releasen/deleten?
Mfg Mo3bius
-
Zu jedem CreateXXX (CreatePen, CreateSolidBrush,...) gehört auch irgendwo ein DeleteObject.
Du löscht hier z.b. nur hpen3 wieder, nicht aber hpen, hpen2, hpen4
bild wird auch nicht gelöscht.Genereller Ablauf ist etwa so:
// Pen erzeugen: HPEN aPen=CreatePen(...); // Pen in den DeviceContext selektieren und bisher selektierten Pen merken: HGDIOBJ prevPen=SelectObject(hdc,aPen); // Mit dem Pen rumzeichnen // Alten Pen wieder ins DC rein-selektieren (Rückgabewert ist jetzt aPen!) SelectObject(hdc,prevPen); // aPen löschen: DeleteObject(aPen);Im Taskmanager unter "Prozesse" kannst du dir die Spalte "GDI-Objekte" hinzufügen, wenn der Wert dort bei deiner Anwendung immer weiter steigt ist das oft ein Zeichen für GDI-Leaks.
-
So richtig verstanden habe ich wohl immer noch nicht. Ich werde mich da noch ein bisschen informieren und melde mich dann wieder.
Der Tip mit dem Taskmanager war echt gut. Ich hab defintiv ein GDI-Leak. Ich kann da locker mehrere Tausend Objekte erzeugen.

Mfg Mo3bius