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

    Aussehen tut es aber ungefähr so:
    http://www.apload.de/images-i188314b44v7l.png

    Also 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().


Anmelden zum Antworten