EReadError bei eigener Komponente (war: Ich weiß nicht mehr weiter)



  • Wenn ich mit dem Objektinspektor ein Bild geladen habe, erscheint die DFM als Text wie folgt:
    (nur das wichtigste)

    object Form1: TForm1
      Left = 100
      Top = 100
      Width = 500
      Height = 200
      Caption = 'Test-Form1'
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'MS Sans Serif'
      Font.Style = []
      Icon.Data = {424D363......FFF}
      OldCreateOrder = False
      PixelsPerInch = 96
      TextHeight = 13
      object MyBild1: TMyBild
        Left = 88
        Top = 112
        Width = 185
        Height = 169
        Bild.Data = {36300000424......FFFFFF}
       end
    end
    

    Wenn ich wieder in die Ansicht zum Formular zurückkehren will, erscheint folgende Fehlermeldung:
    "Fehler beim Lesen des Formulars
    Eigenschaft kann nur gelesen werden. Fehler ignorieren und fortfahren?
    WARNUNG: Ignorieren kann bedeuten, daß Komponenten gelöscht werden oder Eigenschaftswerte verloren gehen."

    Gehe ich auf <Ignorieren>, ist mein geladenes Bild verschwunden.
    Mein Problem ist, ich weiß nicht, wie die Übergabe des Bildes vom Objektinspektor auf meine Form geschieht.
    Muss ich im Konstruktor noch eine Zuweisung einfügen, die das geladene Bild aufnimmt? Ich habe das schon mit Assign probiert, leider klappt das auch nicht.
    Hier steckt mein Fehler. Kann mir jemand zeigen, wie das geht?



  • Hallo Leute, ich geb' so schnell nicht auf!!!! 😉
    Ich habe von Euch noch keinen brauchbaren Ansatz mein Problem zu lösen. Gibt's hier keinen, der mir weiterhelfen kann?



  • Warum will mir keiner helfen?



  • Mir ist aufgefallen, dass Du nirgendwo FBild initialisierst, weshalb u.U. die entsprechende Set-Methode
    fehlschlagen könnte.

    Mein Vorschlag:

    __fastcall TMyBild::TMyBild(TComponent* Owner): 
      TGraphicControl(Owner),
      FBild(0)
    {   }
    

    Insgesamt könnte Dein Code sicherlich noch etwas überarbeitet werden 😉

    Gruß,

    Alexander



  • Alexander Kempf schrieb:

    Mir ist aufgefallen, dass Du nirgendwo FBild initialisierst, weshalb u.U. die entsprechende Set-Methode
    fehlschlagen könnte.

    das macht er in der Set Methode.

    Ich würde aber auch in Constructor das Bild erzeugen und im Destructor deleten!
    Ich denk auch , dass der Fehler irgendwie damit zu tun hat.



  • Versuch mal stored=true zu setzen bei deinem Image. Hier Beispiel bei StringList:

    __property TStringList* FixedColsText = { read=FFixedColsText, write=SetFixedColsText,stored=true};



  • DerAltenburger schrieb:

    Alexander Kempf schrieb:

    Mir ist aufgefallen, dass Du nirgendwo FBild initialisierst, weshalb u.U. die entsprechende Set-Methode
    fehlschlagen könnte.

    das macht er in der Set Methode.

    Ich glaube, das geht da schief.
    Nehmen wir an FBild zeigt irgendwohin (nicht sauber auf 0 initialisiert):

    thunderbol5 schrieb:

    void __fastcall TMyBild::SetBild(Graphics::TBitmap * Value)
    {
      // Hoffen wir das was vernünftiges übergeben wird, d.h. Value != 0 (NULL)...
      if(Value == NULL){//...dann ist diese Bedingung false, d.h. es geht unten weiter...
    
        if (FBild)
          FBild = NULL;
        return;
      };
    //...hier geht's weiter und FBild zeigt irgendwohin,...
      if(!FBild) //...d.h. !FBild ist false und...
        FBild = new Graphics::TBitmap; //...dieser Befehl wird nicht abgearbeitet
    // hier zeigt FBild immer noch irgendwohin, wohin weiß nur der liebe Gott
      FBild->Assign(Value);  // Was passiert dann?
      Invalidate();
    }
    

    Oder liege ich total daneben?
    Das müsste sich aber durch Debuggen herausfinden lassen - sofern man weiß, wie man Komponenten
    debuggt...

    Gruß,

    Alexander



  • Alexander Kempf schrieb:

    Ich glaube, das geht da schief.

    Ich sag ja, ich mach das auch lieber im Constructor/Destructor.



  • DerAltenburger schrieb:

    Ich sag ja, ich mach das auch lieber im Constructor/Destructor.

    Ich glaube nicht, dass das was mit Vorlieben zu tun hat.
    Wenn man im Konstruktor nicht sauber initialisiert, verlässt man sich auf den Zufall - ziemlich
    riskant.
    Die Frage bleibt natürlich, ob's in dem Fall daran liegt.

    Gruß,

    Alexander



  • Hallo Alexander Kempf, Der Altenburger, Christian211

    erstmal vielen Dank für Eure Mithilfe. Hatte zwischenzeitlich schon nicht mehr damit gerechnet eine Antwort in diesem Forum zu bekommen, obwohl ich mir ja richtig Mühe gemacht hatte.

    Ich habe mittlerweile das Problem gelöst. Die Kompo funktioniert jetzt einwandfrei.

    Ihr hattet Recht.

    Der Fehler liegt tatsächlich im Konstruktor. Dort muss eine Variable vom Typ TBild angelegt sein, wenn ein Bild aus dem Objektinspektor geladen werden soll.
    Ich hatte ursprünglich angenommen, dass die Übergabe eines Bitmaps, das vom Objektinspektor geladen wurde, in der Set-Funktion auf die Kompo geschieht. Das scheint aber nicht so zu sein bzw. zu funktionieren.
    Bei anderen Property-Typen wie z.B int, bool scheint eine Initialisierung im Konstruktor nicht notwendig zu sein.

    Ich habe das so gelöst:

    __fastcall TMyBild::TMyBild(TComponent* Owner):TGraphicControl(Owner){
    ...
    if (!FBild) FBild = new Graphics::TBitmap;
    ...
    }
    

    Dadurch ist in der Funktion

    void __fastcall TMyBild::SetBild(Graphics::TBitmap* Value)
    

    die Anweisung

    if (!FBild) FBild = new Graphics::TBitmap;
    

    natürlich überflüssig, da sie ja bereits im Konstruktor durchgeführt wird und die Variable erst beim Verlassen der Kompo gelöscht wird.

    __fastcall TMyBild::BeforeDestruction(void){
    if (FBild) delete FBild;
    }
    


  • thunderbol5 schrieb:

    Ich habe das so gelöst:

    __fastcall TMyBild::TMyBild(TComponent* Owner):TGraphicControl(Owner){
    ...
    if (!FBild) FBild = new Graphics::TBitmap;
    ...
    }
    

    Meines Erachtens ist hier die Überprüfung !FBild naturlich genauso falsch. Woher sollte denn im
    Konstruktor der Wert für FBild gesetzt sein? Auch dort wird er wohl irgendwo hinzeigen.
    Korrekt wäre z.B.:

    __fastcall TMyBild::TMyBild(TComponent* Owner):
      TGraphicControl(Owner),
      FBild(new Graphics::TBitmap())
    {
    ...
    }
    

    Falsch bzw. nicht initialisierte Zeiger sind immer wieder Anlass für schwer nachvollziehbare
    Fehler und Abstürze. Ich habe mir angewöhnt, jede Membervariable auf die oben gezeigte Art zu
    initialisieren. Zeiger entweder auf 0 oder auf eine neu erzeugte Instanz. Alles andere ist
    Zufallsprogrammierung.

    Gruß,

    Alexander



  • Hallo Alexander Kempf 👍

    Überzeugt!
    Habe Deinen Rat aufgenommen und den Konstruktor entsprechend umgebaut.


Anmelden zum Antworten