Zugriffsverletzung bei Zugriff auf Komponenten eines MDI-Child



  • Durch meinen aufruf mit

    lagerplatz_anlegen = new Tlagerplatz_anlegen(Application);
    

    erzeuge ich also eine neue gültige Instanz?

    Wieso geht dann aber mein oben beschriebener Befehl nicht? Oder kann ich sowas in OnCreate oder OnActivate überhaupt nicht aufrufen?

    Wenn ich es so

    Label15->Caption = "test";
    

    aufrufe kommt keine Fehlermeldung. Damit wäre ich ja fast beim gleichen Fehler wie am Anfang. Das verstehe ich jetzt nicht wirklich. 😞 *langsam am verzweifeln*



  • Lies dir einfach erstmal die Tutorials durch. Dann sollte dir das klar werden.



  • @Braunstein,
    habe mir das jetzt mal angeschaut. Klingt mir alles auch sehr logisch und denke ich habe das verstanden.

    Leider weiß ich nicht, wo jetzt genau mein Fehler liegt. Weil nur "new" habe ich das Formular doch erzeugt. Wieso kann ich dann meinen Befehl im OnCreate oder OnActivate nicht ausführen?



  • Geh doch mal mit dem Debugger durch und setze dir Breakpoints bei deiner Erzeugung mit new sowie in OnCreate bzw. OnActivate und schau in welcher Reihenfolge diese Funktionen aufgerufen werden.



  • Gute morgen nochmals,

    ich habe jetzt mal Breakpoints gesetzt. Demnach kommt erst das New, dann OnCreate und dann OnActivate. Dann gehts wieder zurück und es wird das nach New ausgeführt.

    Aufrufen tue ich das Formular ja folgendermaßen:

    artikel_anlegen = new Tartikel_anlegen(Application);
            artikel_anlegen->WindowState =wsMaximized;
            artikel_anlegen->Show();
    

    Das "Show" wird erst nach OnCreate und OnActivate ausgeführt. Kann es daran liegen?

    Was ich so komisch finde ist ja, dass New das gleiche bewirkt als wenn ich das Formular Automatisch erzeugen lasse. Bei New funktioniert es aber nicht. Wenn ich es automatisch erzeugen lasse klappt es aber.



  • Guten Morgen,

    Wenn du "Automatisch erzeugen" wählst, wird der Zeiger noch vor dem Start der eigentlichen Applikation (Applicatio->Run()) initialisiert. Dann muß es natürlich gehen.
    Du hast doch mit Sicherheit mehrer Forms. Wo genau ist denn dieser Aufruf den du unten gepostet hast? in welchem OnCreate hast du Breakpoints gesetzt?
    Ohne mehr Code kann man schwerlich etwas sagen. Wenn der zu umfangreich ist kannst du ihn mir auch zumailen.

    Ciao



  • Also hier ist mal das MainForm. Dort ist auch der Aufruf für die momentan drei Forms.

    //---------------------------------------------------------------------------
    #include <vcl.h>
    #pragma hdrstop
    
    #include "main_cpp.h"
    #include "artikel_anlegen_cpp.h"
    #include "About.h"
    #include "kunden_anlegen_cpp.h"
    #include "lagerplatz_anlegen_cpp.h"
    #include "funktionen.h"
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma resource "*.dfm"
    Thauptmenu *hauptmenu;
    //---------------------------------------------------------------------------
    
    __fastcall Thauptmenu::Thauptmenu(TComponent *Owner)
    	: TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    
    void __fastcall Thauptmenu::HelpAbout1Execute(TObject *Sender)
    {
    	info->ShowModal();
    }
    //---------------------------------------------------------------------------
    
    void __fastcall Thauptmenu::FileExit1Execute(TObject *Sender)
    {
    	Close();
    }
    //---------------------------------------------------------------------------
    
    void __fastcall Thauptmenu::Artikelanlegen1Click(TObject *Sender)
    {
        bool gefunden=false;
    
        //Überprüfen ob das MDIChild besteht
        for (int i = MDIChildCount - 1; i >= 0; i--) {
            if ((AnsiString)MDIChildren[i]->ClassName() == "Tartikel_anlegen") {
                MDIChildren[i]->Show();
                gefunden=true;
            }
        }
    
        if (!gefunden) {//Artikel anlegen
    //        Tartikel_anlegen *artikel_anlegen = new Tartikel_anlegen(Application);
    //Hier hatte ich einen Breakpoint
            artikel_anlegen = new Tartikel_anlegen(Application);
            artikel_anlegen->WindowState =wsMaximized;
            artikel_anlegen->Show();
        }
    }
    //---------------------------------------------------------------------------
    
    void __fastcall Thauptmenu::Kundenanlegen1Click(TObject *Sender)
    {
        bool gefunden=false;
    
        //Überprüfen ob das MDIChild besteht
        for (int i = MDIChildCount - 1; i >= 0; i--) {
            if ((AnsiString)MDIChildren[i]->ClassName() == "Tkunden_anlegen") {
                MDIChildren[i]->Show();
                gefunden=true;
            }
        }
    
        if (!gefunden) {//Kunden anlegen
    //        Tkunden_anlegen *kunden_anlegen = new Tkunden_anlegen(Application);
            kunden_anlegen = new Tkunden_anlegen(Application);
            kunden_anlegen->Show();
        }
    }
    //---------------------------------------------------------------------------
    
    void __fastcall Thauptmenu::Lagerplatzanlegen1Click(TObject *Sender)
    {
        bool gefunden=false;
    
        //Überprüfen ob das MDIChild besteht
        for (int i = MDIChildCount - 1; i >= 0; i--) {
            if ((AnsiString)MDIChildren[i]->ClassName() == "Tlagerplatz_anlegen") {
                MDIChildren[i]->Show();
                gefunden=true;
            }
        }
    
        if (!gefunden) {//Lagerplatz anlegen
    //        Tlagerplatz_anlegen *lagerplatz_anlegen = new Tlagerplatz_anlegen(Application);
            lagerplatz_anlegen = new Tlagerplatz_anlegen(Application);
            lagerplatz_anlegen->Show();
        }
    }
    //---------------------------------------------------------------------------
    
    void __fastcall Thauptmenu::FormActivate(TObject *Sender)
    {
    //dbconnect();
    }
    //---------------------------------------------------------------------------
    

    Die Breakpoints habe ich im OnCreate oder OnActivate des artikel_anlegen Forms gesetzt.

    Hier mal der Code dazu:

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include "artikel_anlegen_cpp.h"
    #include "funktionen.h"
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    Tartikel_anlegen *artikel_anlegen;
    //---------------------------------------------------------------------------
    __fastcall Tartikel_anlegen::Tartikel_anlegen(TComponent* Owner)
        : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall Tartikel_anlegen::FormActivate(TObject *Sender)
    {
    AnsiString sql_select;
    
    //Anlegen der Auswahlmenüs für den Kunden und den Lagerplatz
    //dbconnect();
    sql_select = "select * from kunden order by firma";
    DataModule1->sql_kunden->SQL->Clear();
    DataModule1->sql_kunden->SQL->Add(sql_select);
    DataModule1->sql_kunden->Open();
    DataModule1->sql_kunden->First();
    
    CBkunde->Clear();
    if(DataModule1->sql_kunden->RecordCount != 0)
    {
        for (int i = 0; i < DataModule1->sql_kunden->RecordCount; i++)
        {
            CBkunde->Items->Add(DataModule1->sql_kunden->FieldByName("firma")->AsString);
            DataModule1->sql_kunden->Next();
        }
    } else
    {
        CBkunde->Items->Add("Kunden anlegen");
    }    
    
    sql_select = "select * from lagerplatze order by bezeichnung";
    DataModule1->sql_kunden->SQL->Clear();
    DataModule1->sql_kunden->SQL->Add(sql_select);
    DataModule1->sql_kunden->Open();
    DataModule1->sql_kunden->First();
    
    CBlagerplatz->Clear();
    if(DataModule1->sql_kunden->RecordCount != 0)
    {
        for (int i = 0; i < DataModule1->sql_kunden->RecordCount; i++)
        {
            CBlagerplatz->Items->Add(DataModule1->sql_kunden->FieldByName("bezeichnung")->AsString);
            DataModule1->sql_kunden->Next();
        }
    } else
    {
        CBkunde->Items->Add("Lagerplatz anlegen");
    }
    //dbdisconnect();
    
    //Hier hatte ich einen Breakpoint
    artikel_anlegen->Label15->Caption = "test";
    }
    //---------------------------------------------------------------------------
    void __fastcall Tartikel_anlegen::FormClose(TObject *Sender,
          TCloseAction &Action)
    {
    	Action = caFree;    
    }
    //---------------------------------------------------------------------------
    void __fastcall Tartikel_anlegen::FormCreate(TObject *Sender)
    {
    
    //Hier hatte ich einen Breakpoint
    DBlagerplatze_temp->Columns->Items[0]->Title->Caption = "Artikel-Nr.";
    
    //artikel_anlegen->DBlagerplatze_temp->Columns->Items[1]->Title->Caption = "Lagerplatz";
    //artikel_anlegen->DBlagerplatze_temp->Columns->Items[2]->Title->Caption = "Menge auf Lagerplatz";
    //artikel_anlegen->DBlagerplatze_temp->Columns->Items[3]->Title->Caption = "Palettenanzahl";
    
    //artikel_anlegen_dbfelder();
    
    }
    //---------------------------------------------------------------------------
    void __fastcall Tartikel_anlegen::Button8Click(TObject *Sender)
    {
    DataModule1->sql_lagerplatze_artikel->Active = false;
    DataModule1->sql_lagerplatze_artikel->Active = true;
    
    artikel_anlegen_dbfelder();
    }
    //---------------------------------------------------------------------------
    

    Gruß



  • artikel_anlegen ist eine globale Variable. Wenn du jetzt new in der Hauptform aufrufst wird eine Innstanz von Tartikel_anlegen erzeugt. Dabei wird auch OnCreate aufgerufen. Zu diesem Zeitpunkt ist der Zeiger artikel_anlegen aber noch nicht gültig. OnCreate sollte man sowieso nicht verwenden. Wenn überhaupt, sollte derartiger Code im Konstruktor ausgeführt werden.

    1. Verlagere den Code aus OnCreate nach OnShow (wenn möglich)
    2. lass innerhalb von artikel_anlegen.cpp bei Zugriffen auf dessen Membervariablen artikel_anlegen-> weg. Wenn du unbedingt willst kannst du das durch this-> ersetzen (ist aber nicht nötig).

    z.Bsp so

    void __fastcall Tartikel_anlegen::FormCreate(TObject *Sender)
    {
    
    //Hier hatte ich einen Breakpoint
    DBlagerplatze_temp->Columns->Items[0]->Title->Caption = "Artikel-Nr.";
    // statt
    //artikel_anlegen->DBlagerplatze_temp->Columns->Items[1]->Title->Caption = "Lagerplatz";
    //artikel_anlegen->DBlagerplatze_temp->Columns->Items[2]->Title->Caption = "Menge auf Lagerplatz";
    //artikel_anlegen->DBlagerplatze_temp->Columns->Items[3]->Title->Caption = "Palettenanzahl";
    // lieber
    DBlagerplatze_temp->Columns->Items[1]->Title->Caption = "Lagerplatz";
    DBlagerplatze_temp->Columns->Items[2]->Title->Caption = "Menge auf Lagerplatz";
    DBlagerplatze_temp->Columns->Items[3]->Title->Caption = "Palettenanzahl";
    //artikel_anlegen_dbfelder();
    }
    


  • Ich wollte ja das

    DBlagerplatze_temp->Columns->Items[0]->Title->Caption = "Artikel-Nr.";
    DBlagerplatze_temp->Columns->Items[1]->Title->Caption = "Lagerplatz";
    DBlagerplatze_temp->Columns->Items[2]->Title->Caption = "Menge auf Lagerplatz";
    DBlagerplatze_temp->Columns->Items[3]->Title->Caption = "Palettenanzahl"
    

    als funktion auslagern. Damit ich es von überall wieder aufrufen kann. Dort muß ich es aber so anlegen:

    artikel_anlegen->DBlagerplatze_temp->Columns->Items[0]->Title->Caption = "Artikel-Nr.";
    artikel_anlegen->DBlagerplatze_temp->Columns->Items[1]->Title->Caption = "Lagerplatz";
    artikel_anlegen->DBlagerplatze_temp->Columns->Items[2]->Title->Caption = "Menge auf Lagerplatz";
    artikel_anlegen->DBlagerplatze_temp->Columns->Items[3]->Title->Caption = "Palettenanzahl"
    

    Im OnShow kann ich es auch nicht folgendermaßen

    DBlagerplatze_temp->Columns->Items[0]->Title->Caption = "Artikel-Nr.";
    DBlagerplatze_temp->Columns->Items[1]->Title->Caption = "Lagerplatz";
    DBlagerplatze_temp->Columns->Items[2]->Title->Caption = "Menge auf Lagerplatz";
    DBlagerplatze_temp->Columns->Items[3]->Title->Caption = "Palettenanzahl"
    

    aufrufen. Kommt auch ein Zugriffsfehler.

    Ich denke ich lass es jetzt und mache es so wie du vorgeschlagen hast. Ist das einfachste.

    Ich danke die für deine Hilfe und Geduld mit mir. :p



  • Wenn du es in eine Funktion auslagern willst, übergib ihr doch einfach den Zeiger.

    void __fastcall setDBLager(Tartikel_anlegen* artikel)
    {
       artikel->DBlagerplatze_temp->Columns->Items[0]->Title->Caption = "Artikel-Nr.";
       artikel->DBlagerplatze_temp->Columns->Items[1]->Title->Caption = "Lagerplatz";
       artikel->DBlagerplatze_temp->Columns->Items[2]->Title->Caption = "Menge auf Lagerplatz";
       artikel->DBlagerplatze_temp->Columns->Items[3]->Title->Caption = "Palettenanzahl";
    }
    

    Dieser Zeiger muß natürlich gültig sein. Diese Funktion braucht dann auch nicht Member einer Klasse zu sein. Nur die Deklaration von Tartikel_anlegen muß dort bekannt sein.


Anmelden zum Antworten