![]() |
Zugriffsverletzung, ich komm nicht drauf
Noch einmal ich, aber ich komm jetzt nicht mehr weiter... Der Quellcode ist etwas umfangreicher, aber ich habs mal (fast) komplett hinkopiert.
Grundsätzlich gibt es ein Datenmodul "DM", in dem die Imagliste für die Toolbuttons (unter anderem) liegt. Zusätzlich werden die einzelnen "Seiten", die im Programm aufgerufen werden können (momentan nur "Uebersicht" und "Einstellungen" auf einem Nachkommen von TPanel in eine eigene Unit ausgelagert. Die meisten Komponenten werden zur Lz auf dem Panel angeordnet (muss ich so machen, weil ich in der Explorerversion die visuellen Komponenten nicht erweitern kann und ein paar Schmankerl eingebaut habe). Zudem hoffe ich den Quelltext etwas übersichtlicher zu bekommen, wenn jede Seite ihre eigene Unit hat. Es funktioniert auch ganz gut und mit etwas Hilfe aus dem Forum, habe ich auch meinen untergeordneten Toolbar auf dem Panel untergebracht. Die Imageliste wird dem Toolbar aus dem Datenmodul zugeordnet (auch auf dem Hauptformular) und hier hakt es auch, denn sobald ich die Liste dem Toolbar zuweise (TEinstellungen.Enter), habe ich zwar einen Glyph auf dem Button, aber beim Beenden des Programmes bekomme ich eine Zugriffsverletzung. Kommentiere ich diese Zeile aus, dann läuft es wieder. Komischerweise scheint die Zuweisung der Imageliste an den Toolbar des Hauptformulars kein Problem zu verursachen. Die Zuweisung in "OnShow", bzw. "Enter" ist übrigens, weil das Datenmodul in der Create-Routine noch nicht erzeugt ist. Kann mir jemand mal unterstützend unter die Arme greifen?? Gruß.
Delphi-Quellcode:
unit ULlesy;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ToolWin, ComCtrls, StdCtrls, ExtCtrls, XTCtrls, ImgList, UDM, UUebersicht, UEinstellungen; type TLlesy = class(TForm) TlBr: TToolBar; LblInformation: TLabel; PnlStatus: TPanel; ImgStatusConnection: TImage; ImgStatusBenutzer: TImage; TlBtnUebersicht: TToolButton; TlBtnArchiv: TToolButton; TlBtnDatenbank: TToolButton; TlBtnEinstellungen: TToolButton; ToolButton5: TToolButton; TlBtnSeparator1: TToolButton; TlBtnInformation: TToolButton; TlBtnBeenden: TToolButton; TlBtnVollbild: TToolButton; procedure FormCanResize(Sender: TObject; var NewWidth, NewHeight: Integer; var Resize: Boolean); procedure FormCreate(Sender: TObject); procedure FormShow(Sender: TObject); procedure TlBtnBeendenClick(Sender: TObject); procedure TlBtnInformationClick(Sender: TObject); procedure TlBtnEinstellungenClick(Sender: TObject); procedure TlBtnUebersichtClick(Sender: TObject); procedure TlBtnVollbildClick(Sender: TObject); private { Private-Deklarationen } Uebersicht: TUebersicht; Einstellungen: TEinstellungen; procedure SetPanel(VP: TVisiblePanel); public { Public-Deklarationen } end; var Llesy: TLlesy; implementation uses UInfo; {$R *.dfm} procedure TLlesy.FormCreate(Sender: TObject); begin //Allgemeine Vorbesetzungen Color:=clXTBackground; //Weitere Fenster erzeugen Uebersicht:=TUebersicht.Create(self,Llesy); Einstellungen:=TEinstellungen.Create(self,Llesy); end; procedure TLlesy.FormShow(Sender: TObject); begin //Allgemeine Vorbesetzungen TlBr.Images:=DM.ImgLst30x30; //Wird beim Start auf TRUE gesetzt und im Infodialog wieder gelöscht. DM.FirstStart:=True; //Infodialog aufrufen Information.Position:=poScreenCenter; Information.ShowModal; end; procedure TLlesy.FormCanResize(Sender: TObject; var NewWidth, NewHeight: Integer; var Resize: Boolean); begin //Minimale Größe auf 800x600 begrenzen if (NewWidth<800) or (NewHeight<600) then Resize:=False; end; procedure TLlesy.TlBtnBeendenClick(Sender: TObject); begin Close; end; procedure TLlesy.TlBtnInformationClick(Sender: TObject); begin Information.Position:=poMainFormCenter; Information.ShowModal; end; procedure TLlesy.SetPanel(VP: TVisiblePanel); begin Uebersicht.Visible:=VP=vpUebersicht; Einstellungen.Visible:=VP=vpEinstellungen; case VP of vpUebersicht: LblInformation.Caption:='Übersicht: Fahrzeuge an- und abmelden'; vpArchiv: ; vpDatenbank: ; vpEinstellungen: begin LblInformation.Caption:='Programm: Einstellungen bearbeiten'; Einstellungen.SetFocus; end; vpSQLService: ; end; end; procedure TLlesy.TlBtnUebersichtClick(Sender: TObject); begin SetPanel(vpUebersicht); end; procedure TLlesy.TlBtnEinstellungenClick(Sender: TObject); begin SetPanel(vpEinstellungen); end; procedure TLlesy.TlBtnVollbildClick(Sender: TObject); begin if not (Align=alClient) then begin DM.Anzeige.Top:=Top; DM.Anzeige.Left:=Left; DM.Anzeige.Width:=Width; DM.Anzeige.Height:=Height; Align:=alClient; end else begin Align:=alNone; Top:=DM.Anzeige.Top; Left:=DM.Anzeige.Left; Width:=DM.Anzeige.Width; Height:=DM.Anzeige.Height; end; end; end.
Delphi-Quellcode:
unit UEinstellungen;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ToolWin, ComCtrls, StdCtrls, ExtCtrls, XTCtrls, ImgList, UDM; type TEinstellungen = class(TPanel) private { Private-Deklarationen } TlBr: TToolBar; TlBtnSichern: TToolButton; Information: TXTPanel; InfBenutzer: TXTEdit; InfComputer: TXTEdit; Datenbank: TXTPanel; DtbTreiber: TXTEdit; DtbServer: TXTEdit; DtbName: TXTEdit; Peripherie: TXTPanel; PerAmpelIP: TXTEdit; PerAmpelPort: TXTEdit; PerAnzeigeIP: TXTEdit; PerAnzeigePort: TXTEdit; procedure Enter(Sender: TObject); public { Public-Deklarationen } constructor Create(AOwner: TComponent; AParent: TWinControl); end; implementation constructor TEinstellungen.Create(AOwner: TComponent; AParent: TWinControl); begin inherited Create(AOwner); //Allgemeine Parameter vorbesetzen Parent:=AParent; BevelInner:=bvNone; BevelKind:=bkFlat; BevelOuter:=bvNone; ParentColor:=True; Top:=50; //Beliebiger Wert, der unterhalb vom Toolbar liegt Align:=alClient; AlignWithMargins:=True; Visible:=False; OnEnter:=Enter; //Untergeordnete Elemente erzeugen TlBr:=TToolBar.Create(self); TlBr.Parent:=self; TlBr.DrawingStyle:=ComCtrls.dsGradient; TlBr.Height:=31; TlBr.ButtonHeight:=30; TlBr.ButtonWidth:=30; TlBtnSichern:=TToolButton.Create(self); TlBtnSichern.Parent:=TlBr; TlBtnSichern.ImageIndex:=6; Information:=TXTPanel.Create(self,self); Information.Caption:='Information'; Information.Top:=35; Information.Height:=80; Information.Width:=260; Information.Enabled:=False;//Nur Information, keine Eingaben möglich InfBenutzer:=TXTEdit.Create(self,Information,30); InfBenutzer.Caption:='Benutzer'; InfComputer:=TXTEdit.Create(self,Information,55); InfComputer.Caption:='Computer'; Datenbank:=TXTPanel.Create(self,self); Datenbank.Caption:='Datenbank'; Datenbank.Top:=125; Datenbank.Height:=105; Datenbank.Width:=260; DtbTreiber:=TXTEdit.Create(self,Datenbank,30); DtbTreiber.Caption:='Treiber'; DtbServer:=TXTEdit.Create(self,Datenbank,55); DtbServer.Caption:='Server'; DtbName:=TXTEdit.Create(self,Datenbank,80); DtbName.Caption:='Name'; Peripherie:=TXTPanel.Create(self,self); Peripherie.Caption:='Peripherie'; Peripherie.Top:=240; Peripherie.Height:=130; Peripherie.Width:=260; PerAmpelIP:=TXTEdit.Create(self,Peripherie,30); PerAmpelIP.Caption:='Ampel - IP'; PerAmpelPort:=TXTEdit.Create(self,Peripherie,55); PerAmpelPort.Caption:='Ampel - Port'; PerAnzeigeIP:=TXTEdit.Create(self,Peripherie,80); PerAnzeigeIP.Caption:='Anzeigetafel - IP'; PerAnzeigePort:=TXTEdit.Create(self,Peripherie,105); PerAnzeigePort.Caption:='Anzeigetafel - Port'; end; procedure TEinstellungen.Enter(Sender: TObject); begin TlBr.Images:=DM.ImgLst24x24; InfBenutzer.Text:=DM.Benutzer; InfComputer.Text:=DM.Computer; DtbTreiber.Text:=DM.Datenbank.Treiber; DtbServer.Text:=DM.Datenbank.Server; DtbName.Text:=DM.Datenbank.Name; end; end. |
Re: Zugriffsverletzung, ich komm nicht drauf
Hallo,
ich verstehe (natürlich) nicht Deine ganze Konstruktion. Ich finde aber nirgends Maßnahmen, die Du beim Closing oder im Destruktor veranlasst. Für mich sieht es so aus, als ob das Programm "selbständig" zuerst das Datenmodul auflöst und erst danach das/die Panel(s); also geht die ImageList "flöten", aber ein Panel setzt ihre Existenz noch voraus. Verfahrensvorschlag:
|
Re: Zugriffsverletzung, ich komm nicht drauf
also mir fällt als erstes auf das du Object instanzierst aber diese nicht frei gibst. Dadurch können auch AV's auftreten.
Beispiel (trifft bei dir nicht zu verdeutlicht aber das es durch events passieren kann): Man erstellt einen Timer der alle x millisekunden das OnTimer aufruft. Dann schließt man das form welches auch frei gegeben wird und der Timer der nicht freigegeben wurde versucht weiterhin das Event aufzurufen was aber fehlschlägt da das Form frei gegeben ist wo die Eventmethode drin steckte. Bevor solche leichtsinnigen Fehler nicht behoben sind ist es für mich verschenkte Zeit mir den Rest anzuschauen. Mir ist es lieber du opferst erstmal Zeit zum implementieren des Freigebens und für andere grundlegende Dinge. |
Re: Zugriffsverletzung, ich komm nicht drauf
@guidobrose
Sei mir nicht böse, aber es ist leider sehr schwierig, sich in deinem Code zurechtzufinden. Wär es eventuell möglich, den gesamten Code oder einen gekürzten Code mit einer "lauffähigen" AV als Attachment (Source keine Exe) beizulegen? Danke. |
Re: Zugriffsverletzung, ich komm nicht drauf
Hi
Ok, ich weiß nicht, ob dir meine Antwort bei der Fehlerbeseitigung hilft, aber um das Datenmodul zuerst zu erzeugen und dann erst deine Form ist einfach unter Projekt->Optionen die Reihenfolge zu ändern. Erst das Datenmodul, dann die Form. Das hilft dir zumindest, das du bei Form.Create ein gültiges Datenmodul hast. Gruß oldmax |
Re: Zugriffsverletzung, ich komm nicht drauf
Danke für die Antworten bisher, da ich das hier auf der Arbeit mache (normalerweise programmiere ich Steuerungen) konnte ich bislang nicht antworten.
Ich gehe auch davon aus, dass es etwas damit zu tun hat, dass das Datenmodul zuerst freigegeben wird und darum etwas "fehlt". Ich versuche jetzt erst mal das DM zuerst zu erzeugen und anschließend den Rest. Stimmt, ich gebe keine Objekte mehr frei, aber soviel ich jetzt gelernt habe, ist bei allen Objekten mit Owner, dieser zuständig und auch in der Lage, dies zu tun, wenn die Anwendung geschlossen wird. Irre ich mich hier? Einen Destruktor für TEinstellungen hatte ich übrigens schon einmal geschrieben, das hat aber nichts gefruchtet, darum habe ich ihn wieder entfernt. Guido |
Re: Zugriffsverletzung, ich komm nicht drauf
Hallo,
kommentiere mal testweise die Zeile TlBr.Images:=DM.ImgLst24x24; aus. Klar kommen jetzt Bildchen mehr, aber ist dann die Scutzverletzung weg ? Wenn ja, schreib in deinen Klassendestruktor (der zu Erzeuge ist) ein TlBr.Images:=NIL rein Heiko |
Re: Zugriffsverletzung, ich komm nicht drauf
@hoika: Das hatte ich schon gemacht und dann funktionierte es auch, die Sache mit dem Destruktor hatte ich ebenfalls schon probiert, allerdings ohne Erfolg.
Die gute Nachricht: Es funktioniert jetzt! Ich lasse das Datenmodul jetzt nicht mehr automatisch erzeugen, sondern mache das in der Create-Methode des Hauptformulars selbst. Danach war die (oder eine) Zugriffsverletzung zwar immer noch vorhanden, aber es lag jetzt daran, dass die ADOConnection (im Datenmodul) noch geöffnet war. Jetzt wird diese im Destruktor des Hauptformular geschlossen und es geht. Danke allen Helfern. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:07 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz