Probleme mit Resize



  • Hi,

    ich habe eine Routine die auf einem TImage ein Bild aufbaut. Wenn ich die Größe der Form verändere durch größer ziehen mit der Maus, dann wird erstmal das Bild in der vorherigen Formgröße aufgebaut, und erst am Schluß "springt" die Form und das Bild dann auf die geänderte Größe. Ich hätte es aber gerne so, dass zuerst die geänderte Formgröße angezeigt wird, um dann in der neuen Formgröße das Bild aufzubauen.

    Kann mir da jemand weiterhelfen ?

    Hier ein kleines Beispielprogramm mit dem man das nachvollziehen kann. Beim Erstellen oder Verändern der Form wird TImage zeilenweise von oben nach unten mit der Farbe Rot gefüllt.

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
    	: TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     Close();	
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
     for ( int i = 0; i < Image1->Height; i++ )
    	{
    	 for ( int j = 0; j < Image1->Width; j++ )
    		{
    		 Image1->Canvas->Pixels[j][i] = clRed;
    		}
         Application->ProcessMessages();
        }	
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormResize(TObject *Sender)
    {
     // Anpassung der Buttons und TImage an die Formgröße
     Button1->Top   = Form1->ClientHeight - 2 * Button1->Height;
     Button1->Left  = Form1->ClientWidth - Button1->Width - Button1->Height;
     Button2->Top   = Form1->ClientHeight - 2 * Button2->Height;
     Button2->Left  = Form1->ClientWidth / 2 - Button2->ClientWidth / 2;
     Image1->Top    = 0;
     Image1->Left   = 0;
     Image1->Height = Form1->ClientHeight - 3 * Button1->Height;
     Image1->Width  = Form1->ClientWidth;
     Application->ProcessMessages();
     // Jetzt soll das Bild mit geänderter Größe neu dargestellt werden
     Button2Click( 0 );
    }
    //---------------------------------------------------------------------------
    


  • Schick doch statt Button2Click(0) 2 x Postmessages an den Button2

    zuerst WM_MOUSEDOWN
    danach WM_MOUSEUP

    Als Ziel gibst Du das Handle des Button an.

    Gruss
    Frank



  • Hallo Frank,

    ich kann dir da leider nicht ganz folgen. Kannst Du mir mit einem Beispiel etwas auf die Sprünge helfen ?

    Danke !

    Trial



  • mach in ...FormResize(...)

    .
      .
      .
      // Jetzt soll das Bild mit geänderter Größe neu dargestellt werden
    /* muss auskommentiert werden !!!
      Button2Click( 0 );
    */
      Image1->AutoSize=false;
      Image1->Stretch=true;
      Image1->Width=Image1->Width * 2;
      //diese Änderung sofort sichtbar machen !!!
      Image1->Refresh();
      PostMessage(Button2->Handle,WM_LBUTTONDOWN,0,0);
      PostMessage(Button2->Handle,WM_LBUTTONUP,0,0);
      .
      .
      .
    

    //und:

    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
      Image1->Height=Image1->Height * 2;
    }
    //---------------------------------------------------------------------------
    

    Das mit der Breite/ Höhe soll Dir nur das Verhaltenb zeigen!
    Wichtig ist auch Refresh();

    Gruss
    Frank



  • Hi Frank,

    vielen Dank für die Hilfe. Damit funktioniert es mit dem Button. Jetzt habe ich aber den Button nur aus Testzwecken verwendet, im eigentlichen Projekt ist der Bildaufbau in einer separaten Funktion. Ich habe das jetzt wie folgt probiert, aber so funktioniert es nicht. Weder das Ereignis Click noch MouseUp von Form1 wird aufgerufen beim Aufziehen von Form1. Hast du noch einen Tip für mich ?

    void __fastcall TForm1::FormResize(TObject *Sender)
    {
     bResize = true;
     Button1->Top     = Form1->ClientHeight - 2 * Button1->Height;
     Button1->Left    = Form1->ClientWidth - Button1->Width - Button1->Height;
     Button2->Top     = Form1->ClientHeight - 2 * Button2->Height;
     Button2->Left    = Form1->ClientWidth / 2 - Button2->ClientWidth / 2;
     Image1->Top      = 0;
     Image1->Left     = 0;
     Image1->AutoSize = false;
     Image1->Stretch  = true;
     Image1->Height   = Form1->ClientHeight - 3 * Button1->Height;
     Image1->Width    = Form1->ClientWidth;
     //diese Änderung sofort sichtbar machen !!!
     Image1->Refresh();
     Application->ProcessMessages();
     PostMessage(Form1->Handle, WM_LBUTTONDOWN, 0, 0);
     PostMessage(Form1->Handle, WM_LBUTTONUP, 0, 0);
     bResize = false;
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::FormClick(TObject *Sender)
    {
     if ( bResize ) viewPicture();
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
    	  TShiftState Shift, int X, int Y)
    {
     if ( bResize ) viewPicture();
    }
    //---------------------------------------------------------------------------
    


  • Werden die beiden Ereignis- Proceduren nicht gerufen oder nur nicht die Funktion darin?

    Lass mal das if (bReisize) ...
    weg!

    PostMessage wird erst verarbeitet, wenn die Messagw Queue abgearbeitet wird, da ist aber bResize schon wirder false!

    Oder Du probierst SendMessage(...), diese Messages werden gleich verarbeitet.

    Gruss
    Frank



  • DerAltenburger schrieb:

    Werden die beiden Ereignis- Proceduren nicht gerufen oder nur nicht die Funktion darin?

    Lass mal das if (bReisize) ...
    weg!

    Die Ereignisprozedur wird nicht gerufen. Auch ohne bResize kommt er da nicht hin beim Aufziehen.

    DerAltenburger schrieb:

    PostMessage wird erst verarbeitet, wenn die Messagw Queue abgearbeitet wird, da ist aber bResize schon wirder false!

    Oder Du probierst SendMessage(...), diese Messages werden gleich verarbeitet.

    Nee, auch mit SendMessage geht es nicht.

    Hast Du noch eine Idee ?



  • Dann ruf
    viewPicture(...)

    direkt nach Image1->Refrwesh();
    direkt auf, OHNE Messages!

    Durch das Refresh() sollte das gehen.

    Gruss
    Frank



  • Nein, leider nicht. Das Verhalten bleibt gleich 😞



  • Hallo,

    wenn du die Image-Größe änderst, dann ändert sich das zugrunde liegende Bitmap noch lange nicht.

    machs doch so:

    foo()
    {
    Image größe einstellen.....
    
    dann:
    Image->Picture->Bitmap->Height = Image->Height;
    Image->Picture->Bitmap->Width = Image->Width;
    }
    

    dazu ist nicht einmal ein Refresh oder Repaint nötig.
    Have fun.
    Rudi



  • rudiM schrieb:

    Hallo,

    wenn du die Image-Größe änderst, dann ändert sich das zugrunde liegende Bitmap noch lange nicht.

    machs doch so:

    foo()
    {
    Image größe einstellen.....
    
    dann:
    Image->Picture->Bitmap->Height = Image->Height;
    Image->Picture->Bitmap->Width = Image->Width;
    }
    

    dazu ist nicht einmal ein Refresh oder Repaint nötig.
    Have fun.
    Rudi

    Das ist schon klar. Aber wenn Du ganz oben im Beispiel schaust, dann siehst Du, dass ich das Bild (im Beispiel halt nur eine Vollfläche) neu berechne. Das funktioniert ja auch. Was mich stört ist halt nur dass beim Resize das Bild zuerst in alter Größe neu aufgebaut wird und erst am Schluß auf die neue, vergrößerte Form springt.



  • An deinem Beispiel vom Anfang ist gar nichts zu sehen, außer schlimmem Geflacker.
    Das Geflacker sollte weggehen, wenn du Application->Processmessages() aus der Schleife entfernst.
    Außerdem wird dein Bild halt auch bei winzigen "Resizes" neu berechnet. Also wenn du Die Maus ziehst, hast du erst nen kleinen Resize, der ein Neuzeichnen anstößt, wenn das fertig ist, kommen die anderen Resizes an die Reihe, die während des Neuzeichnens passiert sind.
    Wenn du davon nichts sehen willst, lagere das Neuzeichnen in einen Thread aus und stelle das Ergebnis am Ende der Berechnung dar. Wenn es zwischendurch ein neues Resize gibt, brich den Thread ab und starte einen neuen.

    Edit: Geflacker gibts nur bei DoubleBuffered=false. (ist im BCB6 noch nicht published)
    Falls du das Neuzeichnen doch sehen willst, kannst du auch Zwischenschritte des Neuzeichnens vom Thread ans Formular übergeben. Das Abbrechen und Neustarten des Threads bei neuerlichem Resize musst du dann trotzdem machen.



  • Hmm, ja das Geflacker am Anfang kommt daher, weil ich das Bild zeilenweise aufbaue, was durch Application->ProcessMessages() in dem Beispiel erreicht wird. Eigentlich hat die Lösung von Frank ja schon funktioniert, nur das ich jetzt nicht die ButtonClick Methode aufrufen will, sondern eine andere Funktion. Schade wenn das nur über einen Thread geht, naja trotzdem danke!


Log in to reply