Announcement

Collapse
No announcement yet.

Canvas Größe läßt sich nicht ändern?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Canvas Größe läßt sich nicht ändern?

    Hi....
    wenn ich zur laufzeit einmal einem image.canvas eine "größe" gegeben habe, läßt sich diese nicht mehr überschreiben?

    das passiert so....
    Image zur Entwurfzeit einfügen: Height: 500; Width:500;

    Zur Laufzeit:
    ...
    Image5.Height := 2000;
    Image5.Width := 2000;
    rect := Bounds(0,0, 878, 1000);
    Image5.Canvas.Brush.Color := clSilver;
    image5.Canvas.FillRect(rect);

    dann diverses zeichnen :-).....

    wenn jetzt...wieder
    ...
    rect := Bounds(0,0, 878, 2000);
    ...

    dann....fehler: (entsteht im canvas...nicht im image)

    EOutofRessources: Der Parameter stimmt nicht.

    der fehler läßt sich noch auf eine andere art reproduzieren:

    wenn ich zur laufzeit das image, und damit ja wohl auch das canvas,
    auf Height ~>4700 zu setze
    rect := Bounds(0,0, 878, 1000);

    ...gibts den selben fehler! :-(

    ...danke

  • #2
    Hallo Wolf-Dieter,

    das Problem ist, daß du den Sinn von TImage und TCanvas nicht richtig verstanden hast. Ich reiße das hier nur kurz an, du solltest dich in der OnlineHilfe dazu ausführlicher informieren.

    TImage nimmt in Pictures eine TGraphic-Instanz auf, welches dann von TImage angezeigt wird. Eine typische TGraphic-Klasse ist TBitmap. TImage selbst kann keine Änderungen an der TGraphic-Instanz vornehmen, sie reagiert aber auf Änderungen der Instanz, indem sie die Instanz neu anzeigt. Eine direkte Änderung dieser Instanz kann daher ziemlich viel Zeit in Anspruch nehmen, weshalb ich dir weiter unten einen besseren Weg vorschlage.

    Ein TCanvas kapselt einen Gerätekontext, es stellt sozusagen eine einheitliche Zeichenfläche zum Zeichnen auf verschiedenen Oberflächen dar. Diese kann z.B. ein Windows-Fenster (TForm.Canvas), eine Druckerseite (TPrinter.Canvas) oder auch eine Bitmap (TBitmap.Canvas) sein.

    Wenn du nun etwas im Zusammenhang mit TImage zeichnen möchtest, dann bietet sich dafür eine Bitmap an. Du weist der Bitmap eine Größe zu und zeichnest über Bitmap.Canvas auf der Bitmap. Wenn du fertig bist mit der Zeichnung, dann weist du diese Bitmap einem TImage zu, um sie anzuzeigen:

    <pre>procedure TForm1.Button1Click(Sender: TObject);
    var
    Bmp : TBitmap;
    begin
    Bmp := TBitmap.Create;
    try
    Bmp.Width := 878;
    Bmp.Height := 2000;
    with Bmp.Canvas do begin
    // irgendetwas zeichnen
    end;
    Image1.Picture.Assign(Bmp);
    finally
    Bmp.Free;
    end;
    end;</pre>

    Wenn der Zeichenvorgang länger dauert und du zwischendurch einen Fortschritt anzeigen möchtest, dann kannst du mehrere Zwischenzuweisungen an TImage vornehmen. Du solltest dann allerdings bedenken, daß die Zeichenoperation dadurch verlängert wird.

    So viel zum guten Umgang mit TImage, jetzt noch etwas zur Erklärung deines Problems.

    Aus lauter Freundlichkeit für den Anfänger und zum Ärger derer, die die daraus resultierenden Fragen beantworten müssen ;-), hat Borland einen kurzen Weg in TImage eingebaut.

    Ist die Bitmap dem TImage zugewiesen, dann kommst du an diese Bitmap über 'TImage.Picture.Graphic.Bitmap' heran. An den Canvas nun entsprechend durch das Anhängen von '.Canvas'. Gleiches gibt die Funktion Canvas von TImage zurück, 'TImage.Canvas' ist also eine kurze Schreibweise von 'TImage.Picture.Graphic.Bitmap.Canvas'. Das ist aber noch nicht alles. Wenn keine TGraphic-Instanz im TImage enthalten ist, dann legt diese Funktion eine Bitmap mit den Abmaßen der TImage und der aktuellen Farbtiefe der Grafikkarte an. Ist eine andere TGraphic-Klasse als TBitmap gespeichert, dann gibt es eine Exception.

    Dein Problem rührt nun daher, daß eine Änderung der Größe von TImage die angelegte Bitmap nicht beeinflußt. Du mußt deshalb der Bitmap eine neue Größe zuweisen oder besser einfach eine neue Bitmap anlegen, zeichnen und diese zuweisen.

    MfG Peter

    Comment


    • #3
      Hallo Peter,

      'wenn ich zur laufzeit das image, und damit ja wohl auch das canvas, auf Height ~>4700 zu setze rect := Bounds(0,0, 878, 1000);'

      ...meinte damit nicht "nachträglich", sondern bevor ich damit etwas antelle. ---Das ergibt dann den gleichen Fehler, sofort bei Height := 4800, wie: erst zeichnen, dann Größe ändern! (*..das hat mich halt gewundert*).

      Hab, als das Problem auftrat (Zoomen und doch noch alles in einer ScrollBox sehen können...) das Image gleich größer setzen wollen!
      Das scheitert halt bei besagten Heigth ~> 4700. :-(

      Danke für die Erklärungen zu der Zeichenfläche des Image(Canvas?).
      Das ist die Lösung für das erste Problem.
      (Hab tatsächlich gedacht, das Canvas sei ein bißchen "enger" mit dem Image "verbunden")

      Über meine begrenzten ;-) Fähigkeiten bin ich mir schon bewußt. :-)

      Da bleibt immer noch das Problem, daß ich das Image gerne > 4700 hätte...

      Hab auch wirklich vorher alles gelesen was die Doku und einige Bücher über Image/Canvas/Größe usw. zur Verfügung stellen...und das Forum vorher durchsucht!
      Ich weiß, daß ein Forum sicherlich nicht dazu da ist, Grundlagenwissen zu vermittelen und daß ist absolut nicht meine Motivation für ein Posting...vielmehr ist es, wie in diesem Fall ein zuvor tagelanges suchen und verzweifen, weil etwas nicht geht, was verd... nochmal gehen muß (Termin!).

      ...sorry :-)

      MfG Wolf

      Ps. Hab das "Problem" erstmal sozusagen gekürzt: Height = 4600; und damit eine funktionierende, wenn auch nicht so optimale, Lösung präsentiert....doch das wundern bleib

      Comment


      • #4
        Hi

        <b> 'TImage.Canvas' ist also eine kurze Schreibweise von 'TImage.Picture.Graphic.Bitmap.Canvas'</b>

        Und das ist FALSCH ! TImage.Canvas zeichnet in den Gerätecontext von TImage.Parent.Canvas. Da TImage von TGraphicControl abgeleitet ist, und alle TGraphicControls KEINE fenterhandles besitzen, sondern intern sozusagen nur Ausschnitte des übergeordneten Fensters darstellen.

        Als einfacher Test:
        Zeichne jeweils in TImage.Canvas und TImage.Picture....Canvas. Nach dem zeichnen verschiebe das Formular zur hälfte aus dem Desktop. Schiebe es zurück. Bei TImage.Canvas wird die eine Hälfte WEISS sein, da eben in den Fenster-DC gemalt wurde und dieser nach dem Malen KEINERLEI Bufferung vornimmt. Nimmst Du den Canvas der Bitmap, verhält es sich wie eine gebufferte Anzeige. Die Bitmap enthält dauerhaft die Zeichnung. Muss sich das IMage anzeigen kopiert es den Inhalt von TImage.Picture.Graphic.Bitmap.Canvas in TImage.Canvas.

        Gruß Hage

        Comment


        • #5
          Hi,

          ich hab ein Formular mit einem TImage als Client damit es sich diversen Größenveränderungen des Formulares anpassen und das Bild neu gezeichnet werden kann. Wenn ich jetzt aber die Form vergrößere (wobei sich natürlich auch das Image vergrößert) bleibt das ClipRect von Image.Canvas jedoch gleich, womit das Bild nicht auf das gesamte Image gezeichnet werden kann. Wenn ich statt auf Image.Canvas auf Form.Canvas zeichne tritt dies nicht auf. Wie ist das zu erklären?

          Motz

          Comment


          • #6
            Hallo Wolf,

            dann haben wir jetzt ein Problem beseitigt, wenden wir uns dem nächsten zu :-)

            Windows begrenzt die maximale Größe einer Bitmap, mit der es umgehen kann. Welche Grenzen Windows setzt, hängt von Breite, Höhe und Farbtiefe, aber wohl auch vom Haupt-Speicher und der Grafikkarte ab.

            Näheres zu einigen diesbezüglichen Experimenten bei Earl. F. Glynn: http://www.efg2.com/lab/Graphics/VeryLargeBitmap.htm

            Da TBitmap eine Kapselung der Windowsbitmap ist, unterliegt diese Klasse ebenfalls diesen Beschränkungen. D.h. du mußt dich zur Lösung deines Problems von TBitmap verabschieden.

            Du solltest generell deine Problematik nicht mit TImage und einer ScrollBox lösen. Nimm zwei eigenständige ScrollBars und eine PaintBox. Im OnPaint der PaintBox zeichnest du nun je nach Stellung der Scrollbars den gewünschten Ausschnitt.

            Zur Speicherung und Darstellung größerer Bitmap gibt es von Grahame Marsh den Big Bitmap Viewer, zu finden u.a. auf Torry: http://www.torry.net/bitmap.htm

            Zur Datenhaltung und Bearbeitung ist TGraphics32 möglicherweise eine Lösung: http://www.geocities.com/den_alex/graphics32.html

            MfG Peter

            Comment


            • #7
              Hallo Hagen,

              Es ist eben nicht so, worauf massenweise Programmierer reinfliegen.

              Dein Test gibt mir recht, da er nicht die von dir vorhergesagten Ergebnisse bringt. Solche Dinge solltest du besser vor dem Schreiben selber ausprobieren :-)

              Hier noch ein anderer einfacher Gegentest:<br>
              Weise dem TImage ein MetaFile oder ein Icon zu, und benutze dann Canvas. Du wirst eine Exception erhalten. Warum wohl?

              Auch der VCL-Quelltext gibt mir recht, in TImage wird ein neues property Canvas definiert.

              <pre>
              TImage = class(TGraphicControl)
              private
              ...
              function GetCanvas: TCanvas;
              ...
              public
              ...
              property Canvas: TCanvas read GetCanvas;
              </pre>
              <pre>
              function TImage.GetCanvas: TCanvas;
              ...
              if Picture.Graphic is TBitmap then
              Result := TBitmap(Picture.Graphic).Canvas
              </pre>

              Ich denke das sollte zur Klärung genügen.

              MfG Peter

              Comment


              • #8
                Hallo Manuel,

                ich denke, meine Antworten an Wolf und Hagen sollten deine Frage beantworten.

                MfG Peter

                Comment


                • #9
                  Hallo Peter,

                  erstmal Danke für die Infos :-) Damit werde ich mich die nächsten Tage beschäftigen!

                  ...und dann die ganze Grafik-Routine neu schreiben *mit einem lachenden und einem weinenden Auge :-( *war wohl auch zu einfach gewesen..

                  tnx u. cu Wolf

                  Ps.: Bin grad Deinem ersten Hinweis nachgegangen...."Asche auf mein Haupt!

                  Comment


                  • #10
                    Hallo Peter,

                    nein, mein Problem wurde leider noch nicht gelöst. Ich habe sowohl TImage als auch TPaintbox verwendet, beides mit demselben Ergebnis... das ClipRect blieb gleich.<BR><BR>
                    Nochmal genau erklärt:<BR>
                    Beim erzeugen der Form bekommt das Image bzw. die Paintbox die Ausmaße der Clientregion.. logisch. Das ClipRect bekommt die Ausmaße des Images bzw. Paintbox.. auch logisch. Was jetzt jedoch seltsam ist.. wenn ich jetzt die Form vergrößere, vergrößert sich zwar das Image bzw. die Paintbox, jedoch das ClipRect bleibt gleich. Wenn ich die Form verkleinere, so dass sie <B>kleiner</B> ist als beim erzeugen, so verkleinert sich das ClipRect. Wenn ich die Form nun aber wieder vergrößere, so wird das ClipRect wieder maximal so groß wie es beim Erzeugen war. <B>Und das kommt mir irgendwie sehr seltsam vor!!!</B><BR>
                    Achja.. wenn ich direkt auf die Form zeichne funktioniert alles problemlos.

                    Motzi

                    PS: Ich brauch das für die Schule. Ich muss ein Programm schreiben, dem man die Koordinaten von drei Punkten angibt und das Prog berechnet alle Daten des Dreiecks. Eh ur leicht.. nur sollte es dann auch noch gezeichnet werden, und da tritt eben mein Problem auf. Bei einer Größenänderung der Form sollten die Einheiten die zum Zeichenen des Dreiecks benötigt werden neu berechnet werden, das alte Dreieck gelöscht, und mit den neuen Einheiten neu konstruiert werde

                    Comment


                    • #11
                      Hallo Manuel,

                      eigentlich ist dein Problem schon geklärt, aber es kann sein, daß du die Zusammenhänge zwischen den Problemen noch nicht verstanden hast. Im Falle von TImage gehört das ClipRect zum Canvas der Bitmap. Erst wenn du diese änderst, dann ändert sich auch die Größe des ClipRects. Warum das bei der PaintBox so sein soll, kann ich nicht nachvollziehen, es sei denn du hast auch hier vergessen, die PaintBox zu vergrößern. Oder du verwendest PaintBox falsch. In einer PaintBox sollte ausschließlich im OnPaint-Ereignis gezeichnet werden. Der Canvas sollte immer aktuell geholt werden. Und dann sollte es auch klappen. Nimm einfach das ganz zuerst geschriebene Beispiel mit der Bitmap, die einem TImage zugewiesen wird, dies ist schnell und zuverlässig.

                      MfG Peter

                      Comment


                      • #12
                        Hi Peter

                        T'schuldige Du hast recht mit dem TImage.Canvas. Ab D3 arbeitet TImage immer mit dem Canvas der TBitmap. Ich halte das aber für eine große FALLE, bzw. konkret gesagt "Designfehler" des Objectes, da es die Fensterlogik/Controllogik negiert. Besonders da ich der Meinung bin das es in D1-D2 anders war.

                        Gruß hage

                        Comment

                        Working...
                        X