Autor |
Beitrag |
Pow
      
Beiträge: 25
Win7
Borland Delphi 7
|
Verfasst: Sa 05.06.10 12:21
Hallo,
ich bin noch recht neu mit Delphi und habe gemerkt, dass es ein mal procedure und function gibt und wenn ich es richtig verstanden habe, kann nur function einen Wert zurückgeben.
D.h. wenn ich im Projekt mit mehreren Formularen arbeite, muss ich global etwas deklarieren, das ich auch in den anderen Formularen verwenden möchte und dann nicht mit procedure diese Variable füllen, sondern mit function oder?
Gibt es da etwas bestimmtes zu beachten?
Also wenn man z.B. Doppelklick auf einen Button macht, dann wird ja automatisch ein procedure erstellt und auch alles dafür deklariert.
Bei function müsste ich ja hingegen auch die Deklaration bei type beachten usw.
Ist sicher eine blöde Anfängerfrage - aber ich wär sehr froh, wenn ich Sicherheit hab
Ein kleiner Beispiel-Quellcode wäre echt super Moderiert von Narses: Topic aus Dateizugriff verschoben am So 06.06.2010 um 23:19
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 05.06.10 17:04
Werte zwischen zwei Formularen tauscht man so aus: www.michael-puff.de/...en-austauschen.shtml
|
|
Delphi-Laie
      
Beiträge: 1600
Erhaltene Danke: 232
Delphi 2 - RAD-Studio 10.1 Berlin
|
Verfasst: Sa 05.06.10 17:52
Pow hat folgendes geschrieben : | wenn ich es richtig verstanden habe, kann nur function einen Wert zurückgeben. |
Nein, auch Prozeduren können es, und zwar über (einen oder mehrere) sog. Variablenparameter. Hört sich hochtrabend an, ist aber einfacher dadurch beschrieben, daß es all' die Variablen sind, die in der Prozedurdeklaration ein (nicht notwendiges, also optionales) var vorangestellt bekommen, z.B. procedure(a:integer;var b:word), dort wäre es die Variable b. Es ist also beiderseitiger Informationsaustausch über die Prozedurschnittstelle möglich, aber nicht notwendig. Bei den anderen Parametern, den Werteparametern, existiert hingegen nur ein Informationsfluß in das Innere der Prozedur.
Allerdings sind Funktionen wesentlich flexibler: Man kann sie (bzw. Ihren Funktionswert) auch als Argument benutzen, z.B. für neue, weitere, oder eben auch sogar diesselbe Funktion (Funktionsverschachtelung). Allerdings benötigen sie zwingend einen Ergebnistyp; ob man den benutzt, ist davon unbeschadet.
Beispiel:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| function Funktion1:integer; function Funktion2(x:integer):string;
....
a:=Funktion2(Funktion1(3)) |
Ist im Prinzip genau wie in der Mathematik: y=sin(cos(x)). Diese Flexibilität hinsichtlich Aufrufen und Verschachtelungen besitzen jedenfalls Prozeduren nicht. Zusätzlich können Funktionen aber auch weitere Ausgaben über die o.g. Variablenparameter haben, doch die lassen sich eben nicht als Argumente verwenden.
Moderiert von Narses: Quote- durch Delphi-Tags ersetzt
|
|
hansa
      
Beiträge: 3079
Erhaltene Danke: 9
|
Verfasst: Sa 05.06.10 20:04
Delphi-Laie hat folgendes geschrieben: | daß es all' die Variablen sind, die in der Prozedurdeklaration ein (nicht notwendiges, also optionales) „var“ vorangestellt bekommen |
Was heisst hier nicht notwendig ?  In der Theorie gibt es Const-, Wert- und Variablen-Parameter. Unterschied zwischen den ersten beiden weiss ich jetzt gerade nicht. Rückgabewerte liefern die VAR - Parameter.
Programmiere mal das hier :
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure test (VAR st : string); begin st := 'Test'; end;
procedure TForm1.Button1Click(Sender: TObject); var st : string; begin st := ''; test (st); ShowMessage(st); end; |
Da steht dann : 'Test'. Mache das VAR mal weg und gucke mal, was da steht. Nix. 
_________________ Gruß
Hansa
|
|
Delphi-Laie
      
Beiträge: 1600
Erhaltene Danke: 232
Delphi 2 - RAD-Studio 10.1 Berlin
|
Verfasst: Sa 05.06.10 20:10
|
|
Pow 
      
Beiträge: 25
Win7
Borland Delphi 7
|
Verfasst: Sa 05.06.10 20:21
Hey super, genau sowas brauch ich
Variablen zwischen verschiedenen Formularen aufrufen
Ich habe mein Programm genauso angepasst, wie es auf der Seite beschrieben ist, seltsamerweise sagt er mir an einer Stelle "undefinierter Bezeichner"
Hier mal der Quellcode:
Hier quasi mein Form1:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| procedure TFrame_Anmelden.B_AnmeldenClick(Sender: TObject);
var TempS : string; Form_Anmelden : TFrame_Anmelden;
begin
Table1.Open; TempS := Table1.FieldByName('Vorname').AsString; TempS := TempS + ' ' + Table1.FieldByName('Name').AsString; Label2.Caption := TempS; Form_Anmelden := TFrame_Anmelden.Create(nil); Form_Anmelden.Bediener := Table1.FieldByName('Kürzel').AsString;
end; |
Hier quasi mein Form2:
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: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42:
| unit Unit_Anmelden;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, DB, DBTables, Unit_Auftraege, ExtCtrls;
type TF_Anmelden = class(TForm) Frame21: TFrame_Anmelden;
private FBediener : String; public property Bediener : String read FBediener write FBediener; end;
var F_Anmelden: TF_Anmelden;
implementation
uses Konfiguration, Unit1;
{$R *.dfm}
procedure TF_Anmelden.FormCreate(Sender: TObject); begin L_datum.Caption := DateToStr(date()); Timer1.Enabled := true; Label2.Caption := FBediener; end;
procedure TF_Anmelden.Timer1Timer(Sender: TObject);
begin L_uhrzeit.Caption := TimeToStr(Time); end; |
Soll also im Frame, wo man sich anmeldet, belegt werden und dann in Form1, das als Hauptfenster offen ist verwendet
Ach ja, beim ersteren meldet er in Zeile 13, dass "Bediener" ein undefinierter Bezeichner ist
Hab ich irgendwo was falsch deklariert oder vergessen? :s
|
|
Tryer
      
Beiträge: 226
Erhaltene Danke: 7
|
Verfasst: Sa 05.06.10 20:29
Vielleicht "Frame21.Label2" ?
Ansonsten bring es nichts Label.Caption im Create auf FBediener zu setzen, denn das ist ja noch nicht zugewiesen.
Besser:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| .. protected procedure SetBediener(Value: string); virtual; public property Bediener: string read FBediener write SetBediener;
.. procedure TF_Anmelden.SetBediener(Value: string); begin FBediener := Value; Frame21.Label2.Caption := FBediener; end; |
[EDIT]Und "T Frame_Anmelden.Create(nil);" soll vermutlich "T F_Anmelden.Create(nil);" heißen?[/EDIT]
Grüsse, Dirk
|
|
hansa
      
Beiträge: 3079
Erhaltene Danke: 9
|
Verfasst: Sa 05.06.10 20:40
Delphi-Laie hat folgendes geschrieben : | Das heißt, daß Prozeduren nicht mit Variablenparametern arbeiten müssen. Man kann sie damit natürlich arbeiten lassen, aber man muß nicht.
|
Moment ! Wer Rückgabewerte braucht, der MUSS var-Parameter verwenden ! Das von Dir gesagte suggeriert eher, man könne "var" einfach weglassen und fertig. Selber Effekt.  Brauche ich keinen Rückgabewert, DANN kann man nicht, sondern sollte das VAR weglassen. Alleine aufgrund der Programmlogik. Unerwähnt blieb auch noch, dass sowohl Function, als auch Procedure VAR-Rückgabewerte liefern können. Betonung liegt dabei auf der Mehrzahl. Das können auch 10 sein.
_________________ Gruß
Hansa
|
|
Pow 
      
Beiträge: 25
Win7
Borland Delphi 7
|
Verfasst: Sa 05.06.10 20:48
Ui, da sind schon einige Elemente, die für mich total neu sind
Könntest du bitte deinen kleinen Code Zeile für Zeile erklären?
dieses protected z.B. oder das virtual am Ende davon
Ich habe mir auch gedacht, ob es nicht auch so gehen könnte
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure TFrame_Anmelden.B_AnmeldenClick(Sender: TObject);
var TempS : string; Frame_Anmelden : TFrame_Anmelden;
begin
Table1.Open; TempS := Table1.FieldByName('Vorname').AsString; TempS := TempS + ' ' + Table1.FieldByName('Name').AsString; Label2.Caption := TempS; Frame_Anmelden := TFrame_Anmelden.Create(nil); Frame_Anmelden.Label2.Caption := Table1.FieldByName('Kürzel').AsString;
end; |
Er kompiliert zwar fehlerfrei, aber irgendwie setzt er die Caption trotzdem nicht im Formular - aber ich schätze, es ist kein Problem ersichtlich, oder? ^^
// EDIT
Zitat: | Und "TFrame_Anmelden.Create(nil);" soll vermutlich "TF_Anmelden.Create(nil);" heißen? |
Dachte ich auch - als ich aber auf TFrame änderte, lieferte er keine Fehler mehr. Scheint aber das richtige zu sein, weil er die ganzen Objekte (Labels usw.) auch findet, wenn ich einen Punkt setze
Zuletzt bearbeitet von Pow am Sa 05.06.10 20:50, insgesamt 1-mal bearbeitet
|
|
Delphi-Laie
      
Beiträge: 1600
Erhaltene Danke: 232
Delphi 2 - RAD-Studio 10.1 Berlin
|
Verfasst: Sa 05.06.10 20:49
hansa hat folgendes geschrieben : | Delphi-Laie hat folgendes geschrieben : | Das heißt, daß Prozeduren nicht mit Variablenparametern arbeiten müssen. Man kann sie damit natürlich arbeiten lassen, aber man muß nicht. |
Moment ! Wer Rückgabewerte braucht, der MUSS var-Parameter verwenden ! |
Oder er nimmt eine Funktion (wenn er nur einen benötigt). Diese Voraussetzung, daß man Rückgabewerte benötigt, wurde von mir doch gar nicht genannt, ich hielt mich doch allgemein(gültig)er! Ich schrieb lediglich, daß Prozeduren keine Variablenparameter (logischerweise zwingend) voraussetzen. Was gibt es an dieser korrekten Aussage zu zerreden?
hansa hat folgendes geschrieben : | Das von Dir gesagte suggeriert eher, man könne "var" einfach weglassen und fertig. Selber Effekt.  |
Es suggeriert es vielleicht bei Dir. Du darfst allerdings nicht der Versuchung erliegen, daß das, wie es Dir erscheint, auch objektiv so sei.
hansa hat folgendes geschrieben : | Unerwähnt blieb auch noch, dass sowohl Function, als auch Procedure VAR-Rückgabewerte liefern können. Betonung liegt dabei auf der Mehrzahl. Das können auch 10 sein. |
Nun, weil ich nicht die Mehrzahl verwandte, wäre es falsch geschlossen, daß ich behauptet hätte, daß es nicht mehr als einer sein könne.
|
|
hansa
      
Beiträge: 3079
Erhaltene Danke: 9
|
Verfasst: Sa 05.06.10 21:18
Du willst das nicht verstehen. Verstehe.  Lese mal im nachhinein das hier :
Delphi-Laie hat folgendes geschrieben: | ..daß es all' die Variablen sind, die in der Prozedurdeklaration ein (nicht notwendiges, also optionales) „var“ vorangestellt bekommen |
Da steht drin : Variable sind alle die in der Prozedurdeklaration ein (nicht notwendiges, also optionales) „var“ vorangestellt bekommen. Ziehe ich den Umkehrschluss, dann heisst das eben : var-Parameter können ein VAR vorangestellt kriegen, ist aber nicht notwendig. Sieht zumindest für mich so aus, als wäre es egal. Ist es aber eben ganz und gar nicht, weil es um Rückgabewerte geht ! Ich bin jetzt wirklich kein Prinzipienreiter oder gar Lehrer. Aber die Aussage ist so nicht richtig. Wird Rückgabewert gebraucht, dann ist VAR nicht optional, sondern zwingend notwendig. Die Anzahl der Rückgabewerte sind nur der Vollständigkeit halber angemerkt worden.
Moderiert von Narses: Zitat repariert.
_________________ Gruß
Hansa
|
|
Tryer
      
Beiträge: 226
Erhaltene Danke: 7
|
Verfasst: Sa 05.06.10 21:40
Du willst doch nicht den Frame, sondern die Form erzeugen! Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TFrame_Anmelden.B_AnmeldenClick(Sender: TObject); var TempS : string; F_Anmelden : TF_Anmelden; begin .. F_Anmelden := TF_Anmelden.Create(nil); F_Anmelden.Benutzer := Table1.FieldByName('Kürzel').AsString; end; |
"protected" beschreibt die Sichtbarkeit, genauso wie das "public" das du schon verwendest.
"protected" ist aber nur in abgeleiteten Klassen sichbar, nicht "überall". SetBenutzer braucht ja niemand sehen, dafür ist "property Benutzer" da.
"virtual" ermöglicht es nur die Prozedur in abgeleiteten Klassen zu überschreiben. Das hält einem also einfach Möglichkeiten offen die sonst verbaut wären. Das braucht dich aber vielleicht noch nicht unbedingt zu belasten.. alles zu seiner Zeit. Zu dem Thema findest Du auch einiges in der Hilfe (Sichtbarkeit von Klassenelementen, Vererbung, .. findet sich vermutlich mit "public" bzw. "virtual"+F1)
Grüsse, Dirk
|
|
Delphi-Laie
      
Beiträge: 1600
Erhaltene Danke: 232
Delphi 2 - RAD-Studio 10.1 Berlin
|
Verfasst: Sa 05.06.10 21:46
hansa hat folgendes geschrieben : | Du willst das nicht verstehen. Verstehe.  |
Oder hier möchte irgendjemand irgendetwas mit aller Gewalt zerreden.
hansa hat folgendes geschrieben : | Lese mal im nachhinein das hier :
hansa hat folgendes geschrieben: | ..daß es all' die Variablen sind, die in der Prozedurdeklaration ein (nicht notwendiges, also
optionales) „var“ vorangestellt bekommen |
Da steht drin : Variable sind alle die in der Prozedurdeklaration ein (nicht notwendiges, also optionales) „var“ vorangestellt bekommen. |
Sicher, ich weiß, was ich schrieb, dort steht aber nicht, daß man diese Freiheit auch dann noch hat, wenn man einen Rückgabewert benötigt.
hansa hat folgendes geschrieben : | Ziehe ich den Umkehrschluss, dann heisst das eben : var-Parameter können ein VAR vorangestellt kriegen, ist aber nicht notwendig. |
Für Fehlkonklusionen fühle ich mich nicht verantwortlich, ja, ich bin es nicht. Der Delphi-Compiler wird eine Prozedur auch dann meldungsfrei übersetzen, wenn sie ohne Variablenparameter definiert wurde - wetten?
hansa hat folgendes geschrieben : | Wird Rückgabewert gebraucht, dann ist VAR nicht optional, sondern zwingend notwendig. |
Richtig, wenn, dann! Aber mein Schnellexkurs weiter oben ging nicht von dieser Voraussetzung aus, daß ein Rückgabewert in jedem Falle benötigt wird. Ist schon schwierig, das zu begreifen...
Zuletzt bearbeitet von Delphi-Laie am Sa 05.06.10 21:53, insgesamt 2-mal bearbeitet
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 05.06.10 21:48
Jetzt kommt mal wieder runter und führt die Diskussion sachlich weiter. Bei der Diskussion um var und const hat das ja auch wunderbar geklappt.
|
|
Pow 
      
Beiträge: 25
Win7
Borland Delphi 7
|
Verfasst: Sa 05.06.10 22:01
Tryer hat folgendes geschrieben : | Du willst doch nicht den Frame, sondern die Form erzeugen! Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TFrame_Anmelden.B_AnmeldenClick(Sender: TObject); var TempS : string; F_Anmelden : TF_Anmelden; begin .. F_Anmelden := TF_Anmelden.Create(nil); F_Anmelden.Benutzer := Table1.FieldByName('Kürzel').AsString; end; |
"protected" beschreibt die Sichtbarkeit, genauso wie das "public" das du schon verwendest.
"protected" ist aber nur in abgeleiteten Klassen sichbar, nicht "überall". SetBenutzer braucht ja niemand sehen, dafür ist "property Benutzer" da.
"virtual" ermöglicht es nur die Prozedur in abgeleiteten Klassen zu überschreiben. Das hält einem also einfach Möglichkeiten offen die sonst verbaut wären. Das braucht dich aber vielleicht noch nicht unbedingt zu belasten.. alles zu seiner Zeit. Zu dem Thema findest Du auch einiges in der Hilfe (Sichtbarkeit von Klassenelementen, Vererbung, .. findet sich vermutlich mit "public" bzw. "virtual"+F1)
Grüsse, Dirk |
Hmpf, ich komm einfach nicht drauf, warum er mir dann in der Zeile F_Anmelden : TF_Anmelden; sagt undefinierter Bezeichner "TF_Anmelden"
TF_Anmelden existiert ja, ist nur eben das Hauptfenster, wohin ich meine Variable hinbeordern möchte
// EDIT
Kann es vielleicht sein, dass es doch Frame_Anmelden sein muss?
Ich hab nämlich eine etwas ungeschickte Bezeichnung im Nachhinein - das Hauptfenster heißt nämlich F_Anmelden und der Frame, in dem man sich eigentlich anmeldet, heißt Frame_Anmelden
|
|
Tryer
      
Beiträge: 226
Erhaltene Danke: 7
|
Verfasst: Sa 05.06.10 22:37
Wenn der Bezeichner unbekannt ist fehlt "Unit_Anmelden" vermutlich in der uses-Klausel.
|
|
Pow 
      
Beiträge: 25
Win7
Borland Delphi 7
|
Verfasst: Sa 05.06.10 22:43
Tryer hat folgendes geschrieben : | Wenn der Bezeichner unbekannt ist fehlt "Unit_Anmelden" vermutlich in der uses-Klausel. |
Wenn ich das hinzufüge, sagt er mir in der anderen Unit "Überkreuezender Bezug zweier Units auf 'Unit_Anmelden'"
Weil in der Unit_Anmelden unter uses die Unit_Auftraege steht (also vom Frame .. wieder sehr ungeschickte Bezeichnung)
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 05.06.10 22:52
Füge sie der Uses-Klausel im Implementation-Abschnitt hinzu.
|
|
Tryer
      
Beiträge: 226
Erhaltene Danke: 7
|
Verfasst: Sa 05.06.10 22:53
Einmal im interface-Teil in die uses-Klausel, und einmal unter implementation, dann sollte es gehen.
Der Frame sollte ja wohl _nur_ in Unit_Anmelden benötigt werden, dann könnte er an anderer Stelle ganz ausgetragen werden.
Ohne kompletten Überblick ist das schwer zu analysieren.
Grüsse, Dirk
|
|
Pow 
      
Beiträge: 25
Win7
Borland Delphi 7
|
Verfasst: Sa 05.06.10 23:07
Wenn ich es unter Implementation einfüge, ändert sich leider nichts.
Ich hänge mal das Projekt mit dem Quellcode als Anhang rein, damit man bei Bedarf reinschauen kann.. vielleicht wird es dann ersichtlicher, was ich falsch mache :s
//EDIT
Oke, ich hab es nun etwas anders und scheinbar viel simpler gelöst
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| ... public BedienerName : String; ... Label2.Caption := Frame21.BedienerName; ... |
Herzlichen Dank für die Hilfestellungen
Hab auf jeden Fall ein paar Dinge gelernt
Einloggen, um Attachments anzusehen!
|
|
|