![]() |
Unterschied zwischen "Self" und Form2 (MDI-Child-Formular)?
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe ein Programm (MDI) erstellt, das außer dem Hauptformular zwei Childfenster enthält.
Von diesen soll eines (Form3 - "Auswahlfenster" genannt) beim Programmstart sofort angezeigt werden (mittels Projektoptionen - verfügbare Formulare unter "automatisch erzeugen" eingetragen). Es soll Buttons als eine Art Auswahl enthalten, von denen aus weitere Childfenster angezeigt werden können. Jedes Childfenster soll aber nur einmal angezeigt werden können. Das zweite Childfenster ("Kindfenster" genannt) wird zur Laufzeit erzeugt und hat einen Button, mit dem es wieder geschlossen werden kann. Das habe ich auch so hinbekommen (mit dem unten auskommentierten "Form2 := nil", bin dabei aber auf ein Verständnisproblem im FormClose-Ereignis des "Kindfensters" gestoßen:
Delphi-Quellcode:
So wie der Quelltext oben angegeben ist, lässt sich das Kindfenster einmal schließen und wird beim erneuten Versuch, es zu öffnen, nicht mehr angezeigt.
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin Action := caFree; if Self = Form2 then begin // Self := nil; // klappt offenbar nicht (Child wird nach einmaligem // Schließen nicht mehr angezeigt. // TForm2(Sender) := nil; // Form2 := nil; // sonst öffnet sich das das Fenster nur beim ersten Mal // Offenbar ist "self" nicht genau dasselbe // an dieser Stelle wie "Form2". TForm(Self) := nil; // auch so geht es nicht end; end; Der aufrufende Quellcode zur Anzeige des Kindfensters lautet:
Delphi-Quellcode:
Was ich nun nicht verstehe ist, warum nur das explizite Setzen von Form2 auf nil wie gewünscht funktioniert, selbst wenn ich Self auf TForm2 caste und vorher auf "Self = Form2" getestet habe. Kann mir hierzu jemand eine Erklärung geben?
procedure TForm3.btnZeigeChildClick(Sender: TObject);
begin if Form2 = nil then // soll verhindern, dass das Child 2mal angezeigt wird begin Application.CreateForm(TForm2, Form2); end; end; Im Anhang habe ich das Beispielprojekt angehängt. Ich benutze Delphi 2010 und habe es damit kompiliert. |
AW: Unterschied zwischen "Self" und Form2 (MDI-Child-Formular)?
Self ist ein "unsichtbarer" Parameter in allen Klassen-Methoden.
Nur bei class procedure/function ist der Self-Parameter nicht die Instanz, sondern der Klassentyp. Und statische Klassenmethoden (
Delphi-Quellcode:
) haben garkein Self, womit sie praktisch genauso wie "normale" Prozeduren sind.
class procedure name(); static;
Delphi-Quellcode:
Und nun überleg mal, warum es nichts bringt diesem Parameter etwas zuzuweisen (kein
procedure TForm2.FormClose(Self: TForm2; Sender: TObject; var Action: TCloseAction);
begin Action := caFree; ... end;
Delphi-Quellcode:
).
(var Self: TForm2; ...
Die Form selber weiß von der externen Variable Form2 überhaupt nichts. Und sie weiß auch nicht, ob es sonstwo noch Variablen gibt. Und es wird auch nirgendwo verwaltet ob und welche Variablen es irgendwo gibt, in denen eventuell eine Instanz dieser Klasse drin abgelegt ist. |
AW: Unterschied zwischen "Self" und Form2 (MDI-Child-Formular)?
|
AW: Unterschied zwischen "Self" und Form2 (MDI-Child-Formular)?
Zitat:
|
AW: Unterschied zwischen "Self" und Form2 (MDI-Child-Formular)?
Hallo,
naja, dass
Delphi-Quellcode:
nichts mit der Variable zu tun hat wurde ja schon erklärt.
Self
Zitat:
Delphi-Quellcode:
In den Formularen dann jeweils ein:
function CreateForm (const FormClass : TCustomFormClass) : TCustomForm;
begin Result := FormClass.Create (Application.MainForm) end; function FindComponentByClass (const Component : TComponent; const ComponentClass : TComponentClass) : TComponent; var i : Integer; c : TComponent; begin Result := nil; for i := 0 to Component.ComponentCount - 1 do begin c := Component.Components [i]; if c is ComponentClass then begin Result := c; Break end end end; procedure ShowMDIForm (const FormClass : TCustomFormClass); var c : TComponent; f : TCustomForm; begin c := FindComponentByClass (Application.MainForm, FormClass); if Assigned (c) then f := TForm (c) else begin f := CreateForm (FormClass); if not Assigned (f) then // Do whatever you want if it fails end; if f.WindowState = wsMinimized then f.WindowState := wsNormal else f.BringToFront end;
Delphi-Quellcode:
Und an den Stellen an denen ein weiteres MDIChild angezeigt werden soo
procedure TFormX.FormClose(Sender: TObject; var Action: TCloseAction);
begin Action := caFree end;
Delphi-Quellcode:
Gruß
uses
sap.pas; procedure TFormY.ButtonClick(Sender: TObject); begin ShowMDIForm (TFormX) end; |
AW: Unterschied zwischen "Self" und Form2 (MDI-Child-Formular)?
Dank an alle für die Antworten.
@himitsu (kein "var" in der Deklaration) Was mir noch nicht ganz klar ist:
Delphi-Quellcode:
In diesem kleinen Programm wird "Sender" benutzt, um die Aufschrift von Button "btn1" zu ändern. In der Deklaration steht auch kein "var" bei Sender dennoch wird die Aufschrift verändert. Vermutlich liegt dies daran, dass die Visibility der verschiedenen Objekte nicht gleich ist. Soweit ich es jetzt verstanden habe, kann also in meinem Beispiel im Beitrag #1 das Formular sich selbst (self) nicht sehen wohl aber seine Member (wie also in diesem Beispiel oben "btn1") - schon etwas eigenartig.:roll:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) btn1: TButton; procedure btn1Click(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.btn1Click(Sender: TObject); begin (Sender as TButton).Caption := 'Änderung'; end; end. Und wenn self auch nicht exakt Form2 ist (in #1) so bezieht es sich doch letztlich auf Form2, oder ich habe den Eintrag in der Wiki aus Sir Rufos Beitrag noch nicht verstanden: Zitat:
|
AW: Unterschied zwischen "Self" und Form2 (MDI-Child-Formular)?
Da wird ja auch nicht die Referenz verändert, sondern etwas, auf das die Referenz verlinkt.
Du wolltest aber die Referenz (den Inhalt der Variable und nicht Etwas in dem, worauf die Referenz in der Variable zeigt) ändern. Der Vergleich wäre also
Delphi-Quellcode:
procedure TForm1.btn1Click(Sender: TObject);
begin Sender := nil; // oder Sender := btn2; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:23 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