Autor Beitrag
steiniman1
Hält's aus hier
Beiträge: 2



BeitragVerfasst: So 31.07.22 01:24 
hallo,
nach langer Delphi-Abstinenz wollte ich ein Delphi 7 Projekt auf Delphi 11 umstellen mit gleichzeitigem Umbau von MDI zu Frames. Erste Erfolge haben sich schon eingestellt. Ich habe jedoch ein Problem, dass ich Komponenten in den Frames nicht vom Parentformular bestückt bekomme. Im ursprünglichen Script werden im Parentformular diverse MySQL-Abfragen durchgeführt und die Daten in die Komponenten der Frames eingetragen. Da augenscheinlich ein grundsätzliches Problem besteht, habe ich das Script runter gebrochen, damit das wesentliche erkannt werden kann:

Als Hintergrundinfo: Es wird ein Hauptformular erstellt, die eine Toolbar und ein PageControl enthält. Dieses enthält mehrere Tabs, in denen Frames eingebunden werden.
Klickt man auf eines der Button in der Toolbar, wird das entsprechende Tab aufgerufen und ich kann mit dem entsprechenden Frame ohne weiteres arbeiten. Eines der Frames hat eine Tabelle, das auf dessen Doppelklick eine neues Formular TForm2 als "StayOnTop" öffnet. Bis hierher ist alles schick und läuft so, wie es soll.

Auf dem Form2 ist u.A. ein PageControl (TAdvOfficePager von TMS) und weitere Edits. Im TAdvOfficePager wird dynamisch bis zu 20 Frames in jeweilige Pages packt. Nach ein bisschen herantasten hat dies auch geklappt. Die Prozeduren innerhalb des jeweiligen Frames funktionieren auch. Nur wenn ich die Frames aus Form2 füllen will, bekomme ich während der Laufzeit eine Zugriffsverletzung angezeigt. Die anderen Edits im Form2 werden ohne Probleme bedient.


Hier Code für Datei artikeldetails.pas
ausblenden volle Höhe 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:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
unit artikeldetails;

interface

uses  Windows, ..., frame_arttxt, ...

type
  TForm2 = class(TForm)
  ...
    arttxtpager: TAdvOfficePager;
    ...
    function ftxt_setzen(frame: TFrame2; framename: string; tabname: string): boolean;
  ...
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;
  ftxt1: TFrame2;
  ftxt2: TFrame2;
  ...
  
//-----------------------------------------------------------------------------------
//---  NormalTexte-Frame setzen
//-----------------------------------------------------------------------------------
function TForm2.ftxt_setzen(frame: TFrame2; framename: string; tabname: string): boolean;
begin
  frame         := TFrame2.Create(Self);
  frame.Name    := framename;
  frame.Parent  := arttxtpager.PageByCaption(tabname);
  frame.Align   := alClient;
end;

//-----------------------------------------------------------------------------------
//---  Formular erstellen
//-----------------------------------------------------------------------------------
procedure TForm2.FormCreate(Sender: TObject);
var
arttab: TAdvOfficePage;
i1, i2: integer;
begin
  For i1:=1 to arttxtmg do
    begin
      arttab := TAdvOfficePage.Create(arttxtpager);
      arttab.AdvOfficePager := arttxtpager;
      arttab.Caption := 'Texte' + IntToStr(i1);
      // Frames setzen
       case (i1) of
          1:  begin ftxt_setzen(ftxt1, 'Frame30''Texte' + IntToStr(i1)); end;
          2:  begin ftxt_setzen(ftxt2, 'Frame31''Texte' + IntToStr(i1)); end;
      ....
       end;
    end;
end;

//-----------------------------------------------------------------------------------
//---  Formular aktivieren
//-----------------------------------------------------------------------------------
procedure TForm2.FormActivate(Sender: TObject);
begin
  ftxt1.arttxtb.Text := 'hallo';
end;  

end;



Und hier für frame_arttxt.pas
ausblenden volle Höhe 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:
32:
Unit frame_arttxt;

interface

uses
  Windows, ClipBrd,.., AdvEdit,...;

type
  TFrame2 = class(TFrame)
    Label108: TLabel;
    artcopyb: TAdvGlowButton;
    arttxtb: TAdvLUEdit;
  ...
    procedure artcopybClick(Sender: TObject);
    ...
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

implementation

{$R *.dfm}

//-----------------------------------------------------------------------------------
//---  Artikelbezeichnung in die Zwischenablage
//-----------------------------------------------------------------------------------
procedure TFrame2.artcopybClick(Sender: TObject);
begin
  Clipboard.AsText := arttxtb.Text;
end;


Ich hoffe, dass ich nicht zuviel entfernt habe. Vielleicht kann mir jemand einen Denkanstoß geben. Komischerweise wird der Zugriff ftxt1.arttxtb.Text im Editor ohne Probleme zugelassen.
Vielen Dank im vorraus...
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: So 31.07.22 08:44 
Hallo und :welcome:

schau dir mal im Debugger in FormCreate vor und nach dem Aufruf von ftxt_setzen den Wert von ftxt1 bzw. ftxt2 an.
Ich könnte dir jetzt sofort die Lösung verraten, aber vllt. kommst du ja selber darauf?!

PS: Deine Schleife in Zusammenhang mit dem case (...) of ist ein Anti-Pattern: Loop-switch sequence.
Und du solltest deinen Klassen (und Variablen) bessere Namen als TForm2 oder TFrame2 geben (am besten so wie auch deine Dateien heißen).
steiniman1 Threadstarter
Hält's aus hier
Beiträge: 2



BeitragVerfasst: So 31.07.22 21:36 
hallo Th69,

gleich mehrere Hausaufgaben auf einmal... mit dem Debugger habe ich bislang noch wenig Berührungspunkte gehabt, zumal mir dann zu viele "nil"-Pferde rumlaufen... :D Da werde ich wohl noch einige Tage brauchen, um richtig durchzusteigen

Ich bin eigentlich der Typ, der aus Beispielscripten am besten rumspielt und lernt. Leider fand ich nix, was für meine Idee passendsten war.

Bezüglich meines Anliegens habe ich einen Teilerfolg verbuchen können. Wenn ich in der ebenfalls als suboptimiere angesehene Case Lösung die nachfolgende Änderung vornehme, kann ich auf schon mal auf das gewünschte Edit zugreifen. Bei der Auslagerung klappt, trotz der entsprechenden Änderung (Self -> Form2) noch nicht. Da fehlt ihm also immer noch eine Zuordnung.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
          case (i1) of
          1:  begin
                ftxt1         := TFrame2.Create(Form2);
                ftxt1.Name    := 'Frame30';
                ftxt1.Parent  := arttxtpager.PageByCaption('Texte' + IntToStr(i1));
                ftxt1.Align   := alClient;
//          ftxt_setzen(ftxt1, 'Frame30', 'Texte' + IntToStr(i1));
                ...
              end;


Zu den anderen Hinweisen: Die Pages haben zwar die gleichen Frames, aber diese werden in dem Case individuell modifiziert, so dass ich denke, dass der Ansatz nicht ganz verkehrt ist. Sicher gibt es weitere Optimierungsmöglichkeiten, aber ich muss ja auch für später was zum basteln haben... ;)

Das TForm2 etc. hat mich nicht sonderlich gestört, da war ich eher bei den Komponentennamen zu Gange, aber hier gelobe ich Besserung.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mo 01.08.22 08:59 
Wie kann man denn ohne Debugger (vernünftig) entwickeln?

Kennst du wenigstens die Schlüsselwörter var und out (als Referenz-Parameter)? Ansonsten s. Parameter (Delphi).

Und wenn du mehrere Frames hast, warum nutzt du dann kein Array? So bräuchtest du nur einmal im Code ftxt_setzen(...) verwenden.
Individuelle Änderungen kannst du ja dann nach der Schleife vornehmen.

Und sie (bzw. das Array) sollten private Member der Klasse TForm2 sein, keine globalen Variablen.

Außerdem ist mir noch aufgefallen, daß ftxt_setzen zwar als boolean definiert ist, du aber keinen Wert zurückgibst (sollte da nicht wenigstens eine Warnung beim Kompilieren erscheinen?). Alternativ zu var bzw. out könntest du auch (das erzeugte) TFrame zurückgeben (und die Funktion dann in CreateFrame umbenennen ;-)).