Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Dynamisch erzeugte Komponenten ansprechen (https://www.delphipraxis.net/211896-dynamisch-erzeugte-komponenten-ansprechen.html)

josef-b 18. Nov 2022 10:03

Dynamisch erzeugte Komponenten ansprechen
 
Ich möchte einen kleinen PDF-Viewer bauen.

Es sollen mehrere PDFs auf einem Formular dynamisch angezeigt werden.

Dazu habe ich ein PageControls, wo ich dynamisch die Seiten (Pages) erzeuge.

Und danach erzeuge ich auf diesem Tab die Viewer-Componente, in dem Fall TDXPDFViewer von Devexpress.


Delphi-Quellcode:
procedure TF1.AddPage(ACaption: string; AControl: TcxPageControl);
var NewPage: TcxTabSheet;
NewViewer: TdxPDFViewer;

begin
  NewPage := TcxTabSheet.Create(AControl.Owner);
  NewPage.PageControl := AControl;
  NewPage.Caption := ACaption;
  NewPage.Name := 'Page' + inttostr(newPage.pageIndex);
  NewViewer := TDXPDFViewer.Create(NewPage);
  NewViewer.Parent := NewPage;

  AControl.activePage := NewPage;

  NewViewer.LoadFromFile(Temp_Dateiname_gl);
end;


Das aktuelle Tabsheet bekomme ich raus mit:

Delphi-Quellcode:
Showmessage('PageNAme: ' + Pcontrol.ActivePage.Name + #13#10 +
  'PageIndex: ' + inttostr(PControl.ActivePage.PageIndex) + #13#10 +
  'TABIndex: ' + inttostr(PControl.ActivePage.TabIndex)
  );
Meine Frage ist jetzt, wie spreche ich die Viewer-Komponente, die auf diesem
Tabsheet ist an?

Mit Findcomponent? Wenn ja wie genau?

himitsu 18. Nov 2022 10:24

AW: Dynamisch erzeugte Komponenten ansprechen
 
Das, was du bei deinen Komponenten als Owner beim Create angibst (hier dein TabSheet), darin kannst du dann mit DeinTabSheet.FindComponent auch danach suchen.

Oder manuell DeinTabSheet.Components nach dem Typ durchsuchen, ansatt mit FindComponent nach dem Namen (NewViewer.Name hättest du doch bestimmt noch gesetzt)

Owner -> x.Components und x.FindComponent und
Delphi-Quellcode:
for var C in x do

Parent -> x.Controls und x.FindControl (kein
Delphi-Quellcode:
for var C in x.GetControls do
, weil es keinen TEnumerator dafür gibt, was mich erstaunt, dass es das nicht gibt)

itblumi 18. Nov 2022 10:39

AW: Dynamisch erzeugte Komponenten ansprechen
 
Hier ist mal noch eine Funktion die ich benutzt habe um Controls recursiv zu finden. Vllt. hilft dir das ja.

Delphi-Quellcode:

function FindFirstControl(const aControl: TWinControl; AClass: TClass): TControl;
var
  i: Integer;
begin
  Result := nil;
  for i := 0 to aControl.ControlCount -1 do
  begin
    if aControl.Controls[i] is AClass then
    begin
      Result := aControl.Controls[i];
      break;
    end else
    begin
      Result := FindFirstControl(TwinControl(aControl.Controls[i]), AClass);
      if (Result <> nil) then
        break;
    end;
  end;
end;

BerndS 18. Nov 2022 10:39

AW: Dynamisch erzeugte Komponenten ansprechen
 
Eine einfache Methode (ohne mit FindComponent suchen zu müssen) wäre die Klasse TcxTabSheet im Form mit dem gleihem Tyenbezeichner abzuleiten und hier den Viewer zu legen.
Beispiel:
Delphi-Quellcode:
 
type
  TcxTabSheet = class(UnitName.TcxTabSheet)
  private
    Viewer : TDXPDFViewer;
  end;

  TF1 = class(TForm)
  ...
UnitName muss dabei die Unit sein, die TcxTabSheet enthält.

Erzeugt wird der

Delphi-Quellcode:
procedure TF1.AddPage(ACaption: string; AControl: TcxPageControl);
var NewPage: TcxTabSheet;

begin
  NewPage := TcxTabSheet.Create(AControl.Owner);
  NewPage.PageControl := AControl;
  NewPage.Caption := ACaption;
  NewPage.Name := 'Page'*+ inttostr(newPage.pageIndex);
  NewPage.Viewer := TDXPDFViewer.Create(NewPage);
  NewPage.Viewer.Parent := NewPage;

  AControl.activePage := NewPage;

  NewPage.Viewer.LoadFromFile(Temp_Dateiname_gl);
end;
So hast du bei TcxTabSheet immer direkt den Viewer verfügbar.

himitsu 18. Nov 2022 10:50

AW: Dynamisch erzeugte Komponenten ansprechen
 
Ach ja, alternativ kann man zusätzlich die wichtigen Komponenten auch noch in Array, TList<>, TDictionary<> oder Dergleichen speichern,
um "direkt" drauf zugreifen zu können, ohne zu suchen.

Und ja, und/oder als Komponente oder Frame zusammenfassen, mit passenden Property/Zugriffsfunktionen.

BerndS 18. Nov 2022 11:19

AW: Dynamisch erzeugte Komponenten ansprechen
 
Ein simpler class Helper sollte auch gehen.
Da ich keinen TcxTabSheet habe, kann es aber nicht testen.

Delphi-Quellcode:
  TTcxTabSheetClassHelper = class Helper for TcxTabSheet
  private
    function GetViewer: TDXPDFViewer;
  public
    property Viewer: TDXPDFViewer read GetViewer;
  end;
Wenn sichergestellt ist, dass das erste Control im Tabsheet der Viewer ist.
Delphi-Quellcode:
function TTcxTabSheetClassHelper.GetViewer: TDXPDFViewer;
begin
  Result := Controls[0] as TDXPDFViewer
end;
Wenn die Positon nicht bekannt ist, werden die Controls durchsucht:
Delphi-Quellcode:
function TTcxTabSheetClassHelper.GetViewer: TDXPDFViewer;
var
  C: TControl;
  I: Integer;
begin
  for I := 0 to ControlCount - 1 do
  begin
    C := Controls[I];
    if C is TDXPDFViewer then
      Exit(C as TDXPDFViewer);
  end;
  Result := nil;
end;

himitsu 18. Nov 2022 11:33

AW: Dynamisch erzeugte Komponenten ansprechen
 
Bei Controls mußt du aufpassen.
Eine Suche über Components ist da sicherer.

Es wurde ja explizit der Owner angegeben und genau in Jenem kann man suchen.

DevExpress verschachtelt gern übermäßig oft Komponenten ineinander ... da weißt du garnicht, ob es noch zwischenebenen gibt und ob das Control wirklich (noch) dort liegt.
Auch Delphi selbst hat einige Komponenten, wo gern mal der Parent verändert wird. (z.B. TCategoryPanel oder einige Grid-Panels usw.)

josef-b 18. Nov 2022 11:58

AW: Dynamisch erzeugte Komponenten ansprechen
 
Danke für die schnellen Anregungen und Hilfe

Habe es jetzt mit Component gemacht:

Delphi-Quellcode:
var
ActiveViewer: TDxPDFViewer;
ActiveTab: TcXTabsheet;

Delphi-Quellcode:
procedure TF1.SetActiveViewer;
var i : Integer;
begin
ActiveTab := PControl.ActivePage;

for i := 0 to ActiveTab.ComponentCount - 1 do
  begin
  if ActiveTab.Components[i] is TDxPDFViewer then
    begin
    ActiveViewer := ActiveTab.Components[i] as TDXPDFViewer;
    ....
    end;
  end;
end;

BerndS 18. Nov 2022 13:01

AW: Dynamisch erzeugte Komponenten ansprechen
 
Zitat:

Bei Controls mußt du aufpassen.
Eine Suche über Components ist da sicherer.
Da ich mit DevExpress noch nichts gemacht habe, kann das schon sein.
Zumindest wird bei Controls alles was TControl der TWinControl ist, berücksichtigt.
Ich vermute mal, das alles was bei DevExpress sichbar ist, auch von einem der Beiden abgeleitet wurde.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:34 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz