Nicht in WM_PAINT zeichnen



  • Sorry 4 that!!!

    Also, dank RECT konnte ich jetzt einige Zeilen kürzen, es sieht nun wie folgt aus:

    case WM_LBUTTONDOWN:
        InvalidateRect (hwnd, &test, false);
        //Test ist so ein RECT und hat 4 Werte, dank Watch weiß ich auch dass diese okay sind...
    

    Das Gute: Ich bekomme keinen Fehler mehr.
    Das Schlechte: Ich bekomme gar nichts, er zeichnet mir das Ding nicht 😞



  • Lol. Dieses Rechteck was du da definierst ist nur der Bereich der neugezeichnet werden soll. Rechtecke zeichnet man mit der Funktion Rectangle.



  • (.)(.) schrieb:

    Man lasst doch das updatewindow sein, das ist unnütz

    ich das hab grad auch nur angepasst, ist mir gar net aufgefallen. Aber naja egal.



  • Hört auf mich zu verwirren!!!

    Kann mir mal wer bitte 4 Zeilen Quellcode schicken???

    Danke



  • bool paintRectangle = false; // eine Variable die mit deinem Fenster assoziiert ist
    
    case WM_LBUTTONDOWN:
        paintRectangle = true;
        InvalidateRect(hWnd, NULL, TRUE);
        return 0;
    case WM_PAINT:
    {
        PAINTSTRUCT paintData;
        HDC hDC = BeginPaint(hWnd, &paintData);
        if(paintRectangle)
        {
            Rectangle(hDC, 0, 0, 100, 100);
        }
        EndPaint(hWnd, &paintData);
        return 0;
    }
    


  • Gut, nachdem ich es noch leicht angepasst habe funktioniert das jetzt, danke einmal.

    Und nur ob ich das jetzt verstanden habe:
    Ich sage ich will den Bereich den ich in dem InvalidateRect definiere noch mal zeichnen oder wie, und dann wird paint aufgerufen ... huh??



  • Du fügst mit InvalidateRect einen Bereich zur Update Region hinzu.

    Dabei wird nicht sofort eine WM_PAINT Nachricht generiert.
    (Über UpdateWindow könntest du das erzwingen.)

    Erst GetMessage/PeekMessage generieren die WM_PAINT Nachricht, wenn die Update Region nicht leer ist und keine anderen Nachrichten für das Fenster vorhanden sind.



  • Okay, dann verstehe ich inetwa was da vorgeht, werde mich noch spielen!
    Jedenfalls danke an alle beteiligten!

    Steve 🤡



  • er koennte sich aber auch den device kontext in einer beliebiegen funktion ueber GetDC() anfordern und dann nicht in WM_PAINT zeichnen... dann spart man sich diese kontroll-variablen.



  • dann ist es aber beim nächsten neuzeichnen nicht mehr da.



  • verdammt, stimmt ja... vergessen



  • Also, das funktioniert echt gut, main Zeichenprogramm (dank unglaublicher Benutzerunfreundlichkeit und schmerzhafter Bedinung Pain(t) genannt 😃 ) funktioniert einigermaßen.
    ABER: Wenn ich ein paar Sachen zeichne und das Fenster dann minimiere und wieder aufrufe ist alles weg 😞
    Nicht dass das bei meinen Zeichenkünsten schade ist aber ...
    Wie verhindere ich das?
    Gibt es dazu ein Event das ich abfangen kann?

    Grüße, Steve! 🤡



  • Wenn du alles in WM_PAINT zeichnest kommt alles wieder.

    Benutzt du jetzt doch GetDC und zeichnest direkt?



  • Was denke ich mal noch möglich wäre, wäre ein Memory DC wo du dann in WM_LBUTTONDOWN und anderen Nachrichten reinzeichnest und dieses Memory DC dann in WM_PAINT auf den DC deines Fensters blittest.



  • Also, ich mache es so:
    Wenn ich links klicke werden Koordinaten gespeichert, nach zweitem Klick wird dann, je nach Auswahl, ein Kreis oder ein Viereck (welches leider noch ein nicht transparentes "Innenleben" hat) gezeichnet, und zwar direkt im WM_PAINT.

    Die Idee mit diesem Memory DC klingt durchaus logisch.
    Verstehe ich das richtig: Ich male quasi in dieses DC und lade das bei Paint dann rein, oder?

    Und wie realisiere ich das?

    Grüße, Steve! 🤡



  • http://c-plusplus.net/forum/viewtopic.php?t=14713

    Das Anlegen des Memory-DCs kannst du dann z.B. bei WM_CREATE machen, freigeben bei WM_DESTORY (evtl. musst du noch irgendwie Größenänderungen des Fensters abfangen und dein Memory-DC ggf. vergrößern) - das BitBlt kommt dann in WM_PAINT 🙂



  • Also, ich habe das programmiert und es geht ... nur nicht richtig:
    Ich kann immer nur ein Viereck malen, beim zweiten löscht er das erste 😞
    Ich schicke mal meinen Quellcode (gekürzt):

    LRESULT ...
    {
        static HDC hdc, hdc2;
        switch(message)
        {
            case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            hdc2 = CreateCompatibleDC(hdc);
            hBM = CreateCompatibleBitmap(hdc, 800, 600);
            SelectObject(hdc2, hBM);
            //PaintAnweisungen
            BitBlt(hdc, 0, 0, 800, 600, hdc2, 0, 0, SRCCOPY);
            EndPaint(hwnd, &ps);
        }
    }
    

    ???
    Grüße, Steve! 🤡



  • Du darfst den DC nicht jedes Mal in WM_PAINT neu erstellen, erstell den einmal in WM_CREATE, so dass Du in WM_PAINT nur noch die BitBlt-Funktionalität hast. So, wie es jetzt ist erstellst Du in WM_PAINT ständig einen neuen DC, der aber auch nicht gelöscht wird. Vorgehensweise sollte also sein:

    WM_CREATE:  -MemoryDC erstellen
    WM_DESTROY: -MemoryDC zerstören
    WM_PAINT:   -MemoryDC in FensterDC blitten
    


  • Hm, ich habe jetzt echt viel rumprobiert, entweder er löscht wieder alle ausser das letzte (sprich ich kann nur einen Kreis usw zweichnen) oder er löscht beim minimieren/maximieren ...
    Kannst du mir mal ganz gekürzt bitte Code schicken?



  • Okay, ich glaube ich weiß wo ein Fehler stecken könnte, die Lösung ist mir nur noch schleierhaft:

    Bei dem Link den ich von euch bekommen habe steht folgender Code:

    HDC hDC = ...; // z.B. mit BeginPaint 
    HDC hDC2 = CreateCompatibleDC(hDC); 
    HBITMAP hBM = CreateCompatibleBitmap(hDC, cxClient, cyClient); 
    SelectObject(hDC2, hBM); 
    
    // Zeichenoperationen auf hDC2... 
    
    BitBlt(hDC, 0, 0, cxClient, cyClient, hDC2, 0, 0, SRCCOPY); 
    // Ein SelectObject(OldBitmap); ist imho nicht nötig 
    DeleteObject(hBM); 
    DeleteDC(hDC2);
    

    Gut, wenn ich nun
    HDC hdc = BeginPaint(...);
    schreibe dann mache ich das ja logischerweise in dem WM_PAINT. Wenn ich aber gleich danach das
    HDC hdc2 = CreaeCompatibleDC(hdc);
    mache dann löscht er es ja, wie schon geschrieben wurde, bei jedem PAINT und legt es neu an.
    Also wie behebe ich das jetzt?
    Nochmal das was ich habe:

    LRESULT ...
    {
        static HBITMAP hBM;
        static HDC hdc, hdc2;
        ...
        switch(message)
        {
        case WM_CREATE
        {
            ...
            hdc2 = CreateCompatibleDC(hdc); //da gibt es aber noch kein hdc (denke ich, also vielleicht das der Fehler)
            hBM = CreateCompatibleBitmap(hdc2, 800, 600);
            return 0;
        }
        case WM_PAINT:
        {
            hdc2 = BeginPaint(hwnd, &ps);
            SelectObject(hdc2, hBM);
            ...
            //Zeichnen
            ...
            BitBlt(hdc, 0, 0, 800, 600, hdc2, 0, 0, SRCCOPY);
            EndPaint(hwnd, &ps);
            return 0;
        }
    }
    

Anmelden zum Antworten