Farbwahltool: Komische Fehler bei 30 sek Maus-Drag
-
Bedenke auch, daß Du alles, was Du in einen DC hineinselektierst, auch wieder herausholen mußt!
HGDIOBJ hOld = SelectObject(hdc, hXYZ); . . . SelectObject(hdc, hOld);
-
Oh, das könnte es sein... ich dachte wenn ich den HDC lösche brauch ich das nicht...
Coolcat
-
-King- schrieb:
Bedenke auch, daß Du alles, was Du in einen DC hineinselektierst, auch wieder herausholen mußt!
HGDIOBJ hOld = SelectObject(hdc, hXYZ); . . . SelectObject(hdc, hOld);Warum ist das überhaupt nötig? Gibt es vielleicht irgendwo in der MSDN eine Erklärung dafür?
-
@King: Nee, das war es leider auch nicht...trotzdem danke!
@krendil: keine Ahnung.
Sonst noch Ideen?
Coolcat
-
krendil schrieb:
Warum ist das überhaupt nötig? Gibt es vielleicht irgendwo in der MSDN eine Erklärung dafür?
GDI-Objekte besitzen einen internen Zähler, der erhöht wird, wenn sie in einen DC eigesetzt werden. Wenn ein Objekt löscht, wird zunächst der Zähler um eins erniedrigt. Da der Zähler nicht gegen 0 geht, wenn das Objekt noch irgendwo eingesetzt ist, wird nichts gelöscht.
Dieser Umstand ist in der Tat total lasch dokumentiert.
Coolcat schrieb:
@King: Nee, das war es leider auch nicht
Wenn Du das vorher nicht hattest, ist das auf jeden Fall ein Teil der Lösung. Mach die Änderung nicht wieder Rückgängig!
Coolcat schrieb:
Sonst noch Ideen?
Ideen braucht es aber keine mehr: Entweder gibst Du nach Gebrauch nicht alles wieder frei oder Du selektierst nicht alles ordentlich zurück oder beides. Punkt.
Noch genauer könnte man etwas sagen, wenn Du einen Auszug Deines Quells zeigen würdest.
-
Naja ich denke mal ihr werdet euch nicht durch meinen kompletten Quellcode (ca. 1000 Zeilen) wühlen....daher die Kurzform:
Das hier wird bei Maus-Drag andauernt aufgerufen:
WndProc des Farbwahlfeldes:
case WM_LBUTTONDOWN: case WM_MOUSEMOVE: { if (wParam & MK_LBUTTON) { //..... hDC = GetDC(hColorSV); //hColorSV ist das Farbwahlfeld if (!hDC) return 0; HDC hDCCursorSV = CreateCompatibleDC(hDC); HGDIOBJ hGdiObj = SelectObject(hDCCursorSV, hCursorSV); // hCursorSV ist ein HBITMAP das den Cursor enthält // alten Cursor löschen BitBlt(hDC, xCurPos-4, yCurPos-4, 9, 9, hDCCursorSV, 0, 0, SRCINVERT); // neuen Cursor zeichnen xCurPos = xCur; // xCur ist die Mausposition yCurPos = yCur; // xCurPos ist eine globale Variable BitBlt(hDC, xCurPos-4, yCurPos-4, 9, 9, hDCCursorSV, 0, 0, SRCINVERT); SelectObject(hDCCursorSV, hGdiObj); DeleteDC(hDCCursorSV); ReleaseDC(hColorSV, hDC); //.... // Farbansichtsfeld neuzeichnen RedrawWindow(hViewColor, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); // siehe WM_PAINT unten! //.... return 0; } }WndProc des Farbanzeigefeldes:
case WM_PAINT: { PAINTSTRUCT ps; hDC = BeginPaint(hViewColor, &ps); // hViewColor ist das Anzeigefeld if (!hDC) return 0; RECT rect; rect.top = ps.rcPaint.top; rect.right = ps.rcPaint.right; rect.left = ps.rcPaint.left; rect.bottom = ps.rcPaint.bottom; // Draw 5 Unit Border HGDIOBJ hOldBrush = SelectObject(hDC, CreateSolidBrush(GetSysColor(COLOR_BTNFACE))); HGDIOBJ hOldPen = SelectObject(hDC, CreatePen(PS_NULL, 0, 0)); if (rect.left < 5 ) { Rectangle(hDC, 0, 0, 6, 47); rect.left = 5 ; } if (rect.top < 5 ) { Rectangle(hDC, 5, 0, 82, 6); rect.top = 5 ; } if (rect.right > 82 ) { Rectangle(hDC, 81, 0, 87, 47); rect.right = 82; } if (rect.bottom > 42 ) { Rectangle(hDC, 5, 41, 82, 47); rect.bottom = 42 ; } // Draw Rect with choosen Color SelectObject(hDC, CreateSolidBrush(dwColorHSV)); Rectangle(hDC, rect.left, rect.top, rect.right, rect.bottom); // Restore old settings SelectObject(hDC, hOldPen); SelectObject(hDC, hOldBrush); EndPaint(hViewColor, &ps); return 0; }Also ich sehe da jetzt so keine Fehler?!
Coolcat
P.S.: @Kommentare: Ja ich weiß, Deutsch-Englisch-Mix soll man nicht machen...die deutschen Kommentare hab ich nur hier fürs Forum schnell eingefügt...
-
Coolcat schrieb:
Naja ich denke mal ihr werdet euch nicht durch meinen kompletten Quellcode (ca. 1000 Zeilen) wühlen....daher die Kurzform:
Sicher nicht, deswegen schrieb ich auch Auszug.

Coolcat schrieb:
// Draw Rect with choosen Color SelectObject(hDC, CreateSolidBrush(dwColorHSV)); Rectangle(hDC, rect.left, rect.top, rect.right, rect.bottom);Was passiert mit dem Brush, den Du da mit CreateSolidBrush erzeugst? Wie, wann und wo wird der freigegeben? Wo wird der zuvor erzeugte Pen gelöscht? Wo wird der zuvor erzeugte Brush (mit COLOR_BTNFACE) gelöscht?
-
Ach, die muss ich auch wieder löschen? (ok logisch ist das schon...
)
Sorry bin eben API-Anfänger...
...mal gucken ob es das ist...Coolcat
-
Coolcat schrieb:
Ach, die muss ich auch wieder löschen?
Wenn Du sie nicht mehr beötigst: Ja! Aber das hat Dir flenders bereits vor unzähligen Beiträgen gesagt.
BTW: Der zweite in den DC eingesetzte Brush holt den Ersten wieder aus dem DC heraus. Bedenke das!
-
Ich hab die Brushes und Pens jetzt anschließend wieder mit DeleteObject gelöscht, aber das ist es auch nicht.
Ja! Aber das hat Dir flenders bereits vor unzähligen Beiträgen gesagt.
Hm, ich hatte einen HBrush nicht als GDI-Objekt angesehen...
BTW: Der zweite in den DC eingesetzte Brush holt den Ersten wieder aus dem DC heraus. Bedenke das!
Logisch, ich kann ja immer nur mit einer Farbe malen.
HGDIOBJ hGdiObj = SelectObject(hDC, hBrush1); SelectObject(hDC, hBrush2); SelectObject(hDC, hGdiObj);Aber so hab ich doch den alten Brush der vorher drin war wieder eingesetzt, oder?
Coolcat
-
Coolcat schrieb:
Ich hab die Brushes und Pens jetzt anschließend wieder mit DeleteObject gelöscht, aber das ist es auch nicht.
Mit Sicherheit nicht alle, und deswegen geht es auch noch immer nicht.
-
...ich habe endlich diesen verdammten Fehler gefunden....
also es lag an folgendem
:1. Folgendes ist falsch:
HGDIOBJ hOldGdiObj = SelectObject(hDC, hBrush); //mit Brush arbeiten... SelectObject(hDC, hOldGdiObj);Es muss so heißen:
HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, hBrush); //mit Brush arbeiten... SelectObject(hDC, hOldBrush);2. Man darf kein GDI-Objekt löschen während es selektiert ist. Ich hatte einen Brush immer zuerst gelöscht und dann erst den alten wieder selektiert.
Kann mir jemand sagen warum?THX @ All

Coolcat
-
Hallo,
Coolcat schrieb:
2. Man darf kein GDI-Objekt löschen während es selektiert ist. Ich hatte einen Brush immer zuerst gelöscht und dann erst den alten wieder selektiert.
Kann mir jemand sagen warum?das ist eigentlich alles eine Frage des genauen Lesens der Beschreibungen in der MSDN zu den jeweiligen Funktionen. Für DeleteObject findet sich dazu die wichtige Bemerkung:
MSDN schrieb:
**Do not delete a drawing object (pen or brush) while it is still selected into a device context.
**das ist das ganze Geheimnis, einfach befolgen, was dort steht, und man hat keine (na gut, weniger
) ProblemeMfG
-
Hm, muss ich wohl überlesen haben....
Coolcat