[Delphi] TabSheet runtime kopieren in PageControl

Pagina: 1
Acties:
  • 107 views sinds 30-01-2008
  • Reageer

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Ik heb een PageControl met 2 TabSheets. Is het nou mogelijk om tijdens runtime (bij de OnCreate bijvoorbeeld) een x aantal kopieen te maken van 1 bestaande TabSheet in die PageControl.

Ik kan ze wel aanmaken tijdens runtime maar dan zijn ze uiteraard leeg. Het moeten dus eigenlijk excate kopieen zijn. Alleen weet ik niet hoe het dan zit met de events achter de componenten op zo'n tabsheet. Worden die automatisch meegenomen ofzo?

Alvast bedankt.

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 01:25

Tomatoman

Fulltime prutser

Met DoelObject.Assign(BronObject) en BronObject.AssignTo(Doelobject) kun je - afhankelijk van de class van bron en doel - bepaalde properties e.d. kopiëren. Vaak is Assign niet geïmplementeerd en krijg je een exception, soms kun je de belangrijkste properties kopiëren.

Ze zult moeten testen en in de sourcecode van objecten moeten opzoeken wat Assign bij dat object precies doet. Waarschijnlijk zul je een aantal properties en (vooral) events gewoon moeten toekennen via iets als DoelObject.OnDoeIets := BronObject.OnDoeIets;

Een goede grap mag vrienden kosten.


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Assign wil niet:
Cannot assign a TTabSheet to a TTabSheet

AssignTo bestaat niet bij een TabSheet.

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Enig idee hoe ik dit wel kan doen?

Of is frames/forms een oplossing?

"The shell stopped unexpectedly and Explorer.exe was restarted."


Verwijderd

Weet je design-time hoe die TTabSheet eruit ziet?

Zo ja, dan zou je een nieuwe class [met ancestor TTabSheet] kunnen maken, die alle componenten die op die tabsheet staan creeert en initializeert. Nadeel: je kunt de TTabSheet design-time niet meer zien.

Wil je het flexibeler en ook nog gewoon de TTabSheet designen dan zul je denk ik of met frames, of met streams moeten werken.

Een vb van kopieeren van componenten mbv streams staat hier.

Verwijderd

Mogelijke oplossing:
1) Je pleurt alles in een TFrame en pleurt deze tweemaal (al dan niet dynamisch) op je tabsheets.
2) Stukje code:
code:
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
procedure TForm1.Button1Click(Sender: TObject);
begin
  with TTabSheet.Create(PageControl1) do
  begin
    PageControl := PageControl1;
    Caption := 'TabSheet2';
    Tag := 1;
  end;
end;

procedure TForm1.PageControl1Change(Sender: TObject);
var
  I: Integer;
  wcDoel,
  wcBron: TWinControl;
begin
  if not Assigned(PageControl1.ActivePage) then
    Exit;
  wcDoel:=PageControl1.ActivePage;
  if wcDoel.Tag = 0 then
    wcBron:=PageControl1.Pages[1]
  else
    wcBron:=TabSheet1;
  for I := 0 to wcBron.ControlCount-1 do
    wcBron.Controls[I].Parent := wcDoel;
end;

Dit is dan niet echt kopieëren maar meer verplaatsen.

Verwijderd

Dat is wel een grappige oplossing :)

Maar wat ik mij zat te bedenken: waarom heb je meerdere, dezelfde tabsheets nodig; kun je er niet beter 1 maken en een combobox erbij zetten, waarmee je een bepaalde configuratie ofzo kiest?

Verwijderd

Naast die Frame-oplossing (waar ik zelf niet direct aan zou denken, maar da's vooral omdat ik nog niet zo gek veel met Frames heb gedaan), zie ik 2 mogelijkheden:

- Een panel (alClient, en zonder Bevels) op 1 van de 2 TabSheets, en dan op de OnChange de Parent van dat Panel omzetten van 't ene TabSheet naar de andere, en natuurlijk de inhoud aanpassen. Dit kost de minste resources omdat 't Panel in feite maar 1x bestaat.

- Runtime de controls op TabSheet1 streamen naar een MemoryStream en die vervolgens weer terugstreamen naar TabSheet2. Dan bestaan alle controls wel 2x, maar alleen runtime. Designtime (en in de dfm) neemt die copie geen extra ruimte in.

Dat streamen heb ik al 's geschreven voor 2 ToolBars en ActionLists, maar die source heb ik nu even niet bij de hand. Maar als er belangstelling voor is, wil ik die morgen wel even posten...

Verwijderd

:(

Verwijderd

Hmmm, het is toch wel achterlijk dat men niet op een 'normale' manier en TTabSheet kan kopiëren... :(

Verwijderd

Op maandag 11 maart 2002 21:23 schreef Aegis het volgende:
Hmmm, het is toch wel achterlijk dat men niet op een 'normale' manier en TTabSheet kan kopiëren... :(
Wat zie jij als een 'normale' manier?
Voor Delphi is streamen de normale manier om WinControls aan te maken. Lijkt me dan ook een vrij logische manier om ze te copieren.

Dat je het TabSheet zelf niet zo 1-2-3 op die manier kunt copieren, heeft te maken met het feit dat er een PageControl onder zit die moet weten met welke TabSheets 'ie te maken heeft.

Wel vervelend dat TPageControl.InsertTab een private method is, waar je dus van buitenaf niet bij kunt, maar die doet niks meer dan
code:
1
2
3
4
5
procedure TPageControl.InsertTab(Page: TTabSheet);
begin
  Tabs.InsertObject(Page.TabIndex, Page.Caption, Page);
  UpdateActivePage;
end;

Tabs is een protected property van TCustomTabControl (de ancestor van TPageControl), en UpdateActivePage een protected method van TPageControl.
Daar kun je als argeloze Delphi programmeur nog steeds niet van buitenaf bij, maar met een simpel trucje gaat dat prima:
Defineer een class
code:
1
2
type
  THackPageControl = class(TPageControl);

in de unit waar je bij die protected properties/methods wilt (die definitie kan in het implementation deel, die heb je zelfs liever niet in 't interface deel), en je hebt gewoon toegang tot z'n protected parts. :)
(Als je die PageControls cast naar THackPageControls tenminste.)

Verwijderd

Verwijderd schreef op 11 maart 2002 @ 15:46:
Mogelijke oplossing:
1) Je pleurt alles in een TFrame en pleurt deze tweemaal (al dan niet dynamisch) op je tabsheets.
2) Stukje code:
code:
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
procedure TForm1.Button1Click(Sender: TObject);
begin
  with TTabSheet.Create(PageControl1) do
  begin
    PageControl := PageControl1;
    Caption := 'TabSheet2';
    Tag := 1;
  end;
end;

procedure TForm1.PageControl1Change(Sender: TObject);
var
  I: Integer;
  wcDoel,
  wcBron: TWinControl;
begin
  if not Assigned(PageControl1.ActivePage) then
    Exit;
  wcDoel:=PageControl1.ActivePage;
  if wcDoel.Tag = 0 then
    wcBron:=PageControl1.Pages[1]
  else
    wcBron:=TabSheet1;
  for I := 0 to wcBron.ControlCount-1 do
    wcBron.Controls[I].Parent := wcDoel;
end;

Dit is dan niet echt kopieëren maar meer verplaatsen.
Ik heb de 2e oplossing gebruikt en deze werkt enigzins. Het gaat goed als ik een 2e tabblad 'aanmaak'. Zodar het er meer worden dan neem ie het betreffende component(Twebbrowser) niet mee, ook al maak ik een stuk of 5 tabbladen aan dan blijven er steedt (iedere keer verschillend) tabbladen leeg.

Weet iemand hoe ik dit kan oplossen?
Pagina: 1