Announcement

Collapse
No announcement yet.

Gibt es eine Methode die direkt nach dem Erstellen aufgerufen wird?

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

  • Gibt es eine Methode die direkt nach dem Erstellen aufgerufen wird?

    Hallo liebe Programmierer,

    wenn ich die Größe meines selbstgemachten Labels mittels "width := Canvas.TextWidth('OwnLabel');" im Create-Constructor festlegen will erscheint immer der Fehler "Element besitz kein übergeordnetes Fenster"(oder ähnlich). Wenn ich die Breite allerdings jedes mal beim Neuzeichnen(Paint) neu zuweise klapps.
    Darum wollt ich einfach mal fragen ob es bei TGraphicControl vielleicht eine Methode gibt die direkt nach Create aufgerufen wird.
    Eine alternative Lösung wär natürlich auch nicht übel. Aber erst mal finden.
    Danke schonmal für die Hilfe.

    Einen guten Rutsch allerseits, Detlef

  • #2
    Hallo,<br>haben sie vor der Zuweisung inherited aufgerufen

    Comment


    • #3
      Das Problem ist ein anders. Das TLabel ist ein TGraphicControl und benötigt zur Darstellung ein TWinControl. Dieses ist das .Parent Control. Der TCanvas eines TGraphicControls benötigt ein Fensterhandle und ist deshalb stark verknüpft mit TGraphicControl.Parent. Sollte ein TGraphicControl KEIN Parent besitzen und somit keinen DC->TCanvas der mit einem Windows-Fensterhandle verknüft wurde, dann MUSS jeder Zugriff auf TGraphicControl.Canvas schiefgehen. Der Ausweg liegt darin diesen Canvas NICHT zu benutzen sondern auf den Dedsktop-DC zuzugreifen.

      <pre>
      function GetWidth(const Text: String; Font: TFont): Integer;
      var
      Canvas: TCanvas;
      begin
      Canvas := TCanvas.Create;
      try
      Canvas.Handle := GetDC(0);
      Canvas.Font.Assign(Font);
      Result := Canvas.TextWidth(Text);
      finally
      ReleaseDC(0, Canvas.Handle);
      Canvas.handle := 0;
      end;
      end;<br>

      // oder besser, gleich nur API

      function TextSize(const Text: String; Font: TFont): TSize;
      var
      DC: hDC;
      SaveFont: hFont;
      begin
      DC := GetDC(0);
      try
      SaveFont := SelectObject(DC, Font.Handle);
      if not GetTextExtentPoint(DC, PChar(Text), length(Text), Result) then
      begin
      Result.CX := 0;
      Result.CY := 0;
      end;
      SelectObject(DC, SaveFont);
      finally
      ReleaseDC(0, DC);
      end;
      end; <br>

      </pre>

      Nun kannst Du mit Width := TextSize(Caption, Font).CX; arbeiten.<br>

      Gruß Hage

      Comment


      • #4
        Guten Abend,

        und danke schonmal für die Hilfe. Zur Frage von Alex: Ja, ich hab inherited create(AOwner); im Create-Constructor stehen. Daran kanns dann wohl nicht liegen. Aber trotzdem Danke für die Bemühungen.

        Ein eigenes Canvas erstellen hab ich auch schon probiert, allerdings ohne das Handle vom Desktop zu verwenden. Ich hab eigentlich gar kein Handle zugewiesen und das Parent-Handle bekommt das Canvas vermutlich erst nach dem Create, oder wie muß man sich das vorstellen?

        Wenn ich die Antwort also richtig verstanden hab benötigt ein Canvas immer ein Handle eines Fensters(is ja auch klar, muß ja irgedwo gezeichnet werden).
        Auf jeden Fall hab ich das jetzt nach dem obigen Beispiel abgeändert und siehe da, es funktioniert einwandfrei.
        Vielen Dank also für die Hilfe.

        Grüße und Guten Rutsch ins neue Jahr euch beiden, Detlef

        PS: Das Beispiel mit der API-Lösung muß ich mir bei Gelegenheit auch mal genauer anschauen. Wollt mich sowieso mal mehr mit APIs beschäftigen. Bis dann

        Comment


        • #5
          Hallo Detlef,<p>
          es fehlt in der Tat bei den Komponenten an einer Methode, die immer direkt nach der vollständigen Erzeugung aufgerufen wird. Ich mißbrauche deshalb immer die Methode Paint. Damit aber nicht jedes mal beim Paint genau das ausgeführt wird, was eigentlich nur nach dem Erzeugen gemacht werden soll, spendiere ich den Objekten eine private Variable namens:<PRE>
          FOnCreate: Boolean;</PRE>
          Im Construktor (oder bei Formularen in der OnCreate-Methode) setze ich sie auf True. Die Paint-Methode sieht dann z.B. so aus:<PRE>
          procedure TWPAuswahl.FormPaint(Sender: TObject);
          begin
          if FOnCreate then begin
          { Wird in der Methode OnCreate gesetzt. }
          FOnCreate := False;
          // StartDatum errechnen
          SetEditStartDatum;
          end;

          // Ab hier kommt alles, was eben normalerweise in OnPaint gemacht werden soll.

          end;</PRE>

          Gruß<p>
          Wolfgang Rolle

          Comment


          • #6
            Man muß zwischen zwei verschiedenen Arten der Erzeugung unterscheiden.
            <li>Neu-Erzeugung eines Objectes/TComponent
            <li>laden der Componenten aus einem Stream<br>

            Im ersteren Fall benachrichtig OnCreate() direkt nach der Erstellung, bzw. man überschreibt den constructor der Komponente/Forms.
            Im zweiten Falle ist der komplette Komponentenbaum des Forms direkt vor dem Aufruf der Methode .Loaded; erzeugt und initialisiert. D.h. man sollte in diesem Falle die Methode .Loaded; überschreiben.
            Für die Komponneten-Entwicklung ist .Loaded; ideal.<br>

            Gruß Hage

            Comment


            • #7
              achso, im .Loaded; ist auch die Parent-Eigenschaft korrekt gesetzt, was im Constructor bzw. im OnCreate() NICHT der Fall sein muß.
              Allerdings wird .Loaded; bei einer zur designzeit neuerstellten Componente nicht aufgerufen

              Comment


              • #8
                Hallo Hagen,
                <BR><BR>
                dank dir im Nachhinein noch für deine Antwort.
                Mir ist irgendwann mal der Kontakt zu Delphi und damit auch diesen Foren abgebrochen, deshalb die "kleine" Verspätung.
                <BR>
                Danke.
                <BR>
                Schönes WE noch,
                Gruß Sep

                Comment

                Working...
                X