Farbige Linie mit Mouseup, und Möglichkeit performance zu verbessern?
-
Ok ist ziemlich verwirrend der Titel weiß aber nicht wie ich es besser ausdrücken soll, sorry wenn ich gleich ne zweite Frage hinterher stelle und schonmal Danke für Antworten.
Also mal versuchen das ganze zu erklären.
Ich zeichne mit WM_Paint einmal einen Text und eine 500x500 Pixelmatrix:
case WM_PAINT: { PAINTSTRUCT ps; HDC hDC; hDC = BeginPaint(hWnd, &ps); { DrawText(hDC, szTitel, lstrlen(szTitel), &rect, DT_SINGLELINE | DT_CENTER); HBRUSH hOldBrush; for (int j = 0; j <=500; j++) { for (int i = 0; i <=500; i++) { hOldBrush = (HBRUSH)SelectObject(hDC, CreateSolidBrush(RGB( matrix[i][j] , matrix[i][j], 225))); SetPixel( hDC, i, j+100, RGB(matrix[i][j],matrix[i][j],255) ); DeleteObject(SelectObject(hDC, hOldBrush)); } } } EndPaint(hWnd, &ps); return 0; }
Nun will ich mit der Maus darauf Linien zeichnen:
case WM_LBUTTONDOWN: { pause = true; point.x = LOWORD(lParam); point.y = HIWORD(lParam); return 0; } case WM_LBUTTONUP: { if (point.x != -1) { HDC hDC = GetDC(hWnd); MoveToEx(hDC, point.x, point.y, NULL); LineTo(hDC, LOWORD(lParam), HIWORD(lParam)); ReleaseDC(hWnd, hDC); point.x = -1; point.y = -1; } return 0; }
Und nun kommen wir zum Knackpunkt, diese Linien sollen Knallrot sein als RGB (0,255,255). Hab aber bisher nach Recherche keine Lösung dafür gefunden.
Und noch etwas (will ja nicht noch mit nem dritten Thema nerven...
Ich habe einen Timer der 30 Mal pro Sekunde das Pixelbild berechnet das in der WM_PAINT gezeichnet wird.
Schaut so aus:
case WM_TIMER: { switch (wParam) { case ID_TIMER_COLOR: { if (pause == false) { if (z >= 255) bchange = true; if (z <= 1) { bchange = false; } for (int j = 0; j <=500; j++) { for (int i = 0; i <=500; i++) { double x = i; double y = j; double formel = ((150 - z)/150*((sin(x/160)*cos(y/300)) + 1)*(255/2)); int ergebnis = formel; matrix[i][j] = 255-ergebnis; }} if (bchange == false) z--; if (bchange == true) z++; InvalidateRect( hWnd, NULL, FALSE); } }} return 0; }
Das ganze soll wie gesagt nach Timer 30 Mal pro Sekunde ausgeführt werden. Real sind es aber 1-2 Mal pro Sekunde. Der Grund liegt entweder darin das er so lange braucht die 250.000 Pixel zu zeichnen oder so lange braucht weil er 250.000 Mal durch die Vorschleife rennt.
Gibt es da noch optimierungsmöglichkeiten um das ganze vielleicht doch noch Echtzeitfähig zu bekommen?
Gruß
Larkis
-
Ich habe jetzt mal folgendes probiert:
HDC hDC = GetDC(hWnd); HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); HPEN hPenBak = SelectObject(hDC, hPen); MoveToEx(hDC, point.x, point.y, NULL); LineTo(hDC, LOWORD(lParam), HIWORD(lParam)); ReleaseDC(hWnd, hDC); DeleteObject(hPen); point.x = -1; point.y = -1;
Er markiert aber das SelectObject Rot und schreibt beim Compalieren:
error C2440: 'Initialisierung': 'HGDIOBJ' kann nicht in 'HPEN' konvertiert werden
Konvertierung von 'void*' in Zeiger auf nicht-'void' erfordert eine explizite Typumwandlung
-
Die Idee ist schon richtig, SetPixel ist sehr langsam.
Wegen deinem Fehler, du musst halt casten. Sagt der Compiler doch
-
Mechanics schrieb:
Die Idee ist schon richtig, SetPixel ist sehr langsam.
Gibt es für SetPixel den eine schnellere Alternative? Ich hab schonmal was von Double-Buffer gelesen, aber noch nichts gefunden wo das Anschaulich erklärt wird.
Mechanics schrieb:
Wegen deinem Fehler, du musst halt casten. Sagt der Compiler doch
Hab das Gefühl mein Tutorial war da einfach falsch.
habe jetzt
HPEN hPenBak = SelectObject(hDC, hPen);umgewandelt in
SelectObject(hDC, hPen);und habe schöne rote Linien.
-
Ok ich habs mal selbst versucht komme aber nicht weiter.
Quellcode:
hDC = BeginPaint(hWnd, &ps); //Zeichenfenster hDC erstellen { HDC hDC2 = CreateCompatibleDC(hDC); //Zeichenfesnter hDC2 erstellen HBITMAP hBM = CreateCompatibleBitmap(hDC, rect.right, rect.bottom); //Eigenschaften festlegen SelectObject(hDC2, hBM); // hDC2 auswhälen TextOut( // Text in hDC2 schreiben hDC2, 0, 40, szBeschreibung1, sizeof(szBeschreibung1)-1); TextOut( // Text in hDC2 schreiben hDC2, 0, 60, szBeschreibung2, sizeof(szBeschreibung2)-1); TextOut( // Text in hDC2 schreiben hDC2, 0, 80, szBeschreibung3, sizeof(szBeschreibung3)-1); DrawText(hDC2, // Text in hDC2 schreiben szTitel, lstrlen(szTitel), &rect, DT_SINGLELINE | DT_CENTER); // Pixelmatrix in hDC2 schreiben HBRUSH hOldBrush; for (int j = 0; j <=500; j++) { for (int i = 0; i <=500; i++) { hOldBrush = (HBRUSH)SelectObject(hDC2, CreateSolidBrush(RGB( matrix[i][j] , matrix[i][j], 225))); SetPixel( hDC2, i, j+100, RGB(matrix[i][j],matrix[i][j],255) ); DeleteObject(SelectObject(hDC2, hOldBrush)); //Pinsel freigeben BitBlt(hDC, 0, 0, rect.right, rect.bottom, hDC2, 0, 0, SRCCOPY); //hDC mit hDC2 überschreiben DeleteObject(hBM); //Eigenschaften feigeben DeleteDC(hDC2); // hDC2 freigeben } } } EndPaint(hWnd, &ps); //Zeichnen Ende return 0; }
So sollte das aussehen (bzw. so sieht es aus mit setPixel)
http://www.apload.de/images-i188313bbhjdc.pngAussehen tut es aber ungefähr so:
http://www.apload.de/images-i188314b44v7l.pngAlso grundlegend scheint das mit dem übergeben ja zu funktionieren sonst wäre die Schrift nicht da. Aber bei der Animation funktioniert das nicht.
-
Ok, nachdem ich den paint Bereich aufgeräumt habe, hats nun Funktioniert.
hDC = BeginPaint(hWnd, &ps); { HDC hDC2 = CreateCompatibleDC(hDC); HBITMAP hBM = CreateCompatibleBitmap(hDC, rect.right, rect.bottom); SelectObject(hDC2, hBM); for (int j = 0; j <=100; j++) { for (int i = 0; i <=500; i++) { SetPixel( hDC2, i, j, RGB(255,255,255) ); }} TextOut( hDC2, 0, 40, szBeschreibung1, sizeof(szBeschreibung1)-1); TextOut( hDC2, 0, 60, szBeschreibung2, sizeof(szBeschreibung2)-1); TextOut( hDC2, 0, 80, szBeschreibung3, sizeof(szBeschreibung3)-1); DrawText(hDC2, szTitel, lstrlen(szTitel), &rect, DT_SINGLELINE | DT_CENTER); for (int j = 0; j <=500; j++) { for (int i = 0; i <=500; i++) { SetPixel( hDC2, i, j+100, RGB(matrix[i][j],matrix[i][j],255) ); }} BitBlt(hDC, 0, 0, rect.right, rect.bottom, hDC2, 0, 0, SRCCOPY); DeleteObject(hBM); DeleteDC(hDC2); } EndPaint(hWnd, &ps);
Das ganze ist nun ein Stückchen schneller, aber immernoch nicht Echtzeit. Welche Möglichkeiten gibt es da denn noch?
-
SetPixel() in einer Schleife ist die schlechteste Lösung überhaupt - die Pixel einer Bitmap bearbeitet man mit Get/SetDIBits().