Entwickler-Ecke
Grafische Benutzeroberflächen (VCL & FireMonkey) - Zugriff auf Komponenten eines MDIChilds
chrissi1968 - Do 04.11.10 19:33
Titel: Zugriff auf Komponenten eines MDIChilds
Hallo,
ich habe folgendes Problem:
In einer MDI-Anwendung erzeuge ich ein MDIChild. Nun möchte ich aus dem MDIParent (Oder einem anderen MDIChild) eine procedure innerhalb dieses Childs aufrufen. Das klappt auch, nur erhalte ich eine Zugriffsverletzung wenn ich innerhalb dieser procedure eine Komponente aufrufe welche sich auf dem Child-Formular befindet.
Hat jemand von Euch eine Idee woran dies liegen könnte bzw. wo man sowas nachlesen kann?
Vielen Dank und viele Grüße
Chrissi
bummi - Do 04.11.10 19:38
wird schwierig ohne Code...
chrissi1968 - Do 04.11.10 22:33
Hallo,
hier der Code:
1) Erzeugung der Child-Formulare:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
| procedure TFMain.CreateMDIChild(frm: TFormClass); var i : Integer; bCreated: Boolean; fForm : TForm;
begin bCreated:=False; for i := 0 to FMain.MDIChildCount - 1 do begin if FMain.MDIChildren[i] is frm then begin fForm:=FMain.MDIChildren[i] as frm; bCreated:=True; Break; end; end; if not bCreated then frm.Create(Application) else begin FForm.ActiveMDIChild; FForm.Show; end; end; |
Hier der Aufruf:
....
CreateMDIChild(TFVPlan);
....
2) Die function innerhalb des Child:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| procedure TFVPlan.ScrollToNodeInCalendar(iMachine: Integer; iOrder: Integer); var dtBeginn: TDateTime; iNode : IVcNode;
begin iNode:=VcPlan.GetNodeByID(IntToStr(iMachine) + '|' + IntToStr(iOrder)); if iNode <> nil then begin dtBeginn:=iNode.DataField[4]; VcPlan.ScrollToNode(iNode, vcLeftAligned); VcPlan.ScrollToDate(dtBeginn, vcLeftAligned, 2); iNode.MarkNode:=True; end; end; |
3) Und hier der Aufruf aus einem anderen Child:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| procedure TFVPlanningData.TBSelectionFindClick(Sender: TObject); var iMachine: Integer; iOrder : Integer; i: Integer; begin iMachine:=DSSQLPlanDB.DataSet.FieldByName('P_Maschine').AsInteger; iOrder:=DSSQLPlanDB.DataSet.FieldByName('B_Auftrag').AsInteger; for i := 0 to FMain.MDIChildCount - 1 do if FMain.MDIChildren[i] is TForm then begin if TForm(FMain.MDIChildren[i]).Name = 'FVPlan' then begin FMain.MDIChildren[i].BringToFront; FMain.MDIChildren[i].SetFocus; FVPlan.ScrollToNodeInCalendar(iMachine, iOrder); break; end; end; end; |
Dies ist meine erste MDI-Applikation, habe also von MDI keine Ahnung! In der Applikation werden Aufträge graphisch dargestellt und es wäre schön wenn man von dem Datengrid (Child1) durch anklicken eines Auftrages diesen im graphischen Grid (Child2) sehen könnte.
Krachen tut's hier:
Delphi-Quelltext
1: 2: 3:
| iNode:=VcPlan.GetNodeByID(IntToStr(iMachine) + '|' + IntToStr(iOrder)); |
Wird die function innerhalb vom Formular selbst aufgerufen funzt's einwandfrei!
Ich habe auch mal versucht dies mit zwei einfachen Formularen und zwei Buttons darzustellen. Auch hier das gleiche Problem!
Vielen Dank und viele Grüße
Chrissi
jaenicke - Do 04.11.10 22:55
Vermutlich ist VcPlan nicht initialisiert. Das siehst du aber ja im Debugger.
Bei welcher Adresse passiert denn die Schutzverletzung? Wenn das Adresse z.B. 20 oder sowas in der Größenordnung ist, dann ist das Objekt nicht initialisiert.
bummi - Do 04.11.10 23:49
ich vermute die böse Ecke ist
FVPlan.ScrollToNodeInCalendar(iMachine, iOrder);
wenn ich es richtig verstanden werden die MDI's ohne Zuweisung erzeugt es wäre die Frage was in FVPlan steht.
Delphi-Quelltext
1: 2:
| if not bCreated then frm.Create(Application |
chrissi1968 - Fr 05.11.10 11:29
Hallo,
zunächst schon mal herzlichen Dank für Eure Hilfe!
Ich habe auch mal versucht diesen Fehler an einem einfachen Beispiel zu simulieren:
In einer MDI-Anwendung gibt es zwei Formulare:
- Eines welches als "fsNormal" und
- eines welches als "fsMDIChild" erzeugt wird
Auf beiden Formularen gibt es einen Button. Nach der Erzeugung der Formulare frage ich aus dem "fsMDIForm" den caption des Buttons durch eine procedure innerhalb des Formulars ab:
1) Erzeugung von fsMDIChild:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
| procedure TFMainForm.CreateMDIChild(frm: TFormClass); var i : Integer; bCreated: Boolean; fForm : TForm; Child: TFTest1;
begin bCreated:=False; for i := 0 to FMainForm.MDIChildCount - 1 do begin if FMainForm.MDIChildren[i] is frm then begin fForm:=FMainForm.MDIChildren[i] as frm; bCreated:=True; Break; end; end; if not bCreated then begin frm.Create(Application) end else begin FForm.ActiveMDIChild; FForm.Show; end; end; |
2) Erzeugung von fsNormal:
Delphi-Quelltext
1: 2: 3: 4: 5:
| procedure TFMainForm.Formular21Click(Sender: TObject); begin Application.CreateForm(TFTest2, FTest2); FTest2.Show; end; |
3) Abfrage im MDIChild:
Delphi-Quelltext
1: 2: 3: 4:
| procedure TFTest1.KomponenteTest1; begin ShowMessage(Button1.Caption); end; |
--> Zugriffsverletzung bei Adresse 004728D1 in Modul "MDIAPP.exe". Lesen von Adresse 00000360.
4) Abfrage im "Normalen" Fenster:
--> Funzt!
Die Zugriffsverletzung in meinem eigentlichen Projekt lautet:
Zugriffsverletzung bei Adresse 008534A2 in Modul "MDIAPP.exe". Lesen von Adresse 00000394.
Dieses VcPlan ist eine ActiveX-Komponente. Ich habe versucht an dieser Stelle nur mal die caption eines Buttons abzufragen:
.....
ShowMessage(TBExit.Caption);
--> Kracht genau so!!!!
iNode:=VcPlan.GetNodeByID(IntToStr(iMachine) + '|' + IntToStr(iOrder));
.....
Zugriffsverletzung bei Adresse 00853465 in Modul "CkPlan.exe". Lesen von Adresse 0000036C.
Es scheint mir so als ob ich auf die einzelnen Objekte meines Child-Formulars keinen Zugriff haben wenn ich dieser Zugriff von außen kommt. Bei einem "normalen" Formular klappt das einwandfrei!
Viele Grüße
Chrissi
jaenicke - Fr 05.11.10 11:48
chrissi1968 hat folgendes geschrieben : |
Delphi-Quelltext 1:
| frm.Create(Application) | |
Aua...
Du rufst die Methode Create des nicht existierenden Objekts frm auf...
Wie war das nochmal mit einem Konstruktoraufruf? ;-)
chrissi1968 - Fr 05.11.10 12:10
Ups....... :autsch: :autsch: :autsch: :autsch: :autsch: :autsch:
Vielen herzlichen Dank!
Das kommt davon wenn man aus Planlosigkeit einen Code abtippt!
Funzt jetzt supergut und einwandfrei!!
Viele Grüße
Chrissi
SvenAbeln - Fr 05.11.10 12:16
frm ist hier aber doch kein Objekt sondern eine Klasse:
Delphi-Quelltext
1:
| procedure TFMainForm.CreateMDIChild(frm: TFormClass); |
jaenicke - Fr 05.11.10 12:22
Stimmt, da habe ich wiederum nicht drauf geachtet. Der Name ist dann ja auch sehr passend gewählt... :roll:
Die Stelle ist aber trotzdem die richtige. Denn das Ergebnis wurde weggeworfen, ich vermute mal das hat er jetzt auch korrigiert in:
Delphi-Quelltext
1:
| fForm := frm.Create(Application); |
chrissi1968 - Fr 05.11.10 13:19
Kleiner Nachtrag:
Habe die function für das Erzeugen der Childs wie folgt geändert:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
| procedure TFMain.CreateMDIChild(frmClass: TFormClass; var refObj); var i : Integer; bCreated: Boolean; fForm : TForm;
begin bCreated:=False; for i := 0 to FMain.MDIChildCount - 1 do begin if FMain.MDIChildren[i] is frmClass then begin fForm:=FMain.MDIChildren[i] as frmClass; bCreated:=True; Break; end; end; if not bCreated then begin Application.CreateForm(frmClass, refObj); end else begin TForm(fForm).ActiveMDIChild; TForm(fForm).Show; end; end; |
Der Aufruf erfolgt dann:
CreateMDIChild(TFVPlan, FVPlan);
Vielen Dank nochmal und viele Grüße
Chrissi
bummi - Fr 05.11.10 13:27
wäre es wie unten stehen nicht intuitiver und universeller einsetzbar, falls Du doch mal 2 Forms der Selben Klassse benötigst?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| procedure TForm1.CreateMDIChild(frmClass: TFormClass; var refObj); var i : Integer; bCreated: Boolean; begin bCreated:=False; for i := 0 to MDIChildCount - 1 do begin if MDIChildren[i]=Tform(refObj) then begin bCreated:=True; Break; end; end; if not bCreated then begin Application.CreateForm(frmClass, refObj); end else begin TForm(refObj).ActiveMDIChild; TForm(refObj).Show; end; end; |
chrissi1968 - Fr 05.11.10 15:00
Hallo brummi,
ja, Deine Lösung ist besser!! :lol: :lol:
Viele Grüße
Chrissi
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!