Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Code auslagern mit Zugriff auf Objekte der Hauptdatei


master_mane - So 18.10.09 13:00
Titel: Code auslagern mit Zugriff auf Objekte der Hauptdatei
Code auslagern mit Zugriff auf Objekte der Hauptdatei


Guten Mittag,

Wie man Funktionen/Prozeduren in eine separate Unit auslagert und anschließend einbindet, solange kein Zugriff auf ein Objekt der Hauptdatei besteht, habe ich mittlerweile kapiert.
Wenn ich aber z.B. eine Prozedur auslagern möchte, die eine Buttonbeschriftung ändert, bringt er mir immer Tausende von Fehlern ;)
Diese kann ich dann durch einbinden der Type-Deklaration und Co, was ja eigentlich logisch ist, soweit reduzieren, dass Borland nurnoch über i.eine forward oder external Deklaration der Prozedur bzw. Funktion mekert.
Ich weiß nicht, ob mein Ansatz korrekt ist, und wie man es richtig macht.

Codebeispiel Hauptdatei:

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:
30:
31:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Unit2;

type
  TForm1 = class(TForm)
    btn_click: TButton;
    procedure btn_clickClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btn_clickClick(Sender: TObject);
begin
  ChangeCaption();
end;

end.


Delphi-Quelltext
1:
2:
3:
4:
procedure ChangeCaption();
begin
  btn_click.Caption := 'klick mich';
end;

Es soll beim Klicken auf den Button "btn_klick" die Prozedur "ChangeCaption" aus Unit2 aufgerufen werden.

Was muss ich in Unit1, was in Unit2 schreiben, dass das Ganze funktioniert wie es soll?
Codebeispiele wären sehr Hilfreich!

Vielen Dank,
Manuel


Jakob_Ullmann - So 18.10.09 13:50

Du müsstest logischerweise, da Form1.Button1 in Unit1 definiert ist, Unit1 in Unit2 einbinden, da in Unit2 auf Unit1.Form1.Button1 zugegriffen wird. Genauso wird in Unit1 auf Unit2.ChangeCaption zugegriffen. Dafür gibt es eine uses-Klausel im interface-Teil und eine uses-Klausel im implementation-Teil (Unit2):


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
unit Unit1

interface

uses
  SysUtils, ..., Unit2, ...;

...

implementation

...

  ChangeCaption;

...



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
unit Unit2

interface

uses
  SysUtils, ...;

...

implementation

uses
  Unit1

...

procedure ChangeCaption;
begin
  ...
end;


jaenicke - So 18.10.09 13:55

Besser wäre es aber alles was in den ausgelagerten Routinen benötigt wird auch mitzugeben. Sonst wird das schnell sehr unübersichtlich, wenn von überall auf irgendetwas zugegriffen wird...


master_mane - So 18.10.09 14:01

Danke, Jakob!
Zumindest einmal die "forward"-Fehlermeldungen bleiben aus, allerdings sagt er jetzt bei mir "[Fehler] Unit1.pas(29): Undefinierter Bezeichner: 'ChangeCaption'"...

Und wie macht man das, jaenicke?

Danke für die Antworten!

Lieben Gruß,
Manuel


jaenicke - So 18.10.09 14:04

user profile iconmaster_mane hat folgendes geschrieben Zum zitierten Posting springen:
Und wie macht man das, jaenicke?
Wie genau das sinnvoll ist kommt auf den genauen Anwendungszweck an. Man kann für Statusausgaben zum Beispiel eine Callback-Routine einbauen, aber ich glaube für dich reicht das so:

Delphi-Quelltext
1:
2:
3:
4:
procedure ChangeCaptionExample(AButton: TButton; ANewCaption: String);
begin
  AButton.Caption := ANewCaption;
end;
So kannst du zusätzlich zu dem was du sonst brauchst auch die Komponente mitgeben und kannst das dann universell verwenden. Denn du kannst ja verschiedene Buttons übergeben und es wird immer klappen. Und du musst nicht wissen welcher Button darin verändert wird, da du ihn angibst.


Jakob_Ullmann - So 18.10.09 14:07

Ja, das wäre eine Möglichkeit.

Ich muss gestehen, dass ich einen Fehler gemacht habe: Wenn man das ChangeCaption auch außerhalb von Unit2 verwenden will, schreibt man das noch bei interface mit rein:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
unit Unit2

interface

uses
  SysUtils, ...;

procedure ChangeCaption; // bzw. mit Argumenten, falls vorhanden

implementation

uses
  Unit1

procedure ChangeCaption; // bzw. mit Argumenten
begin
  ...
end;

end.


master_mane - So 18.10.09 14:19

Parameter zu verwenden ist natürlich noch besser! Danke, das werde ich machen!

Jetzt sagt Borland allerdings in Unit2, der Button (bzw. bei Parameterübergabe der TButton) wäre ein "undefinierter Bezeichner"...

Liebe Grüße,
Manuel


jaenicke - So 18.10.09 14:23

Halte einmal die Maus in der Formularunit über TButton, dann siehst du (bei einigermaßen modernen Delphiversionen), dass der in der Unit StdCtrls deklariert ist. Also musst du in der anderen Unit die StdCtrls ebenfalls in die uses legen.


Jakob_Ullmann - So 18.10.09 14:29

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Halte einmal die Maus in der Formularunit über TButton, dann siehst du (bei einigermaßen modernen Delphiversionen)


Bei älteren Versionen kann man auch einfach TButton in der Hilfedatei suchen.


master_mane - So 18.10.09 14:45

Dankeschön euch Beiden :)
Es funktioniert einwandfrei.
Schön, dass ihr so viel Geduld mit mir hattet.

Lieben Gruß,
Manuel