AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Dynamischen Wizard realisieren

Ein Thema von MatthiasR · begonnen am 22. Apr 2005 · letzter Beitrag vom 25. Apr 2005
Antwort Antwort
MatthiasR

Registriert seit: 21. Apr 2005
193 Beiträge
 
#1

Dynamischen Wizard realisieren

  Alt 22. Apr 2005, 08:22
Ich soll für meine Ausbildungsfirma einen Konfigurationswizard für unser Prozess-Leitsystem erstellen. Nun stehe ich vor folgendem Problem:

Der Wizard muss dynamisch mit Inhalt bestückt werden können. Das heißt, dass sowohl die Anzahl der Wizard-Seiten variabel sein soll (was wohl eher unproblematisch ist), als auch deren Inhalt. Es soll also ein Hauptprogramm geben, das letztendlich nur eine Container-Funktion ausübt, und die eigentliche Funktionalität wird in Plugins (DLLs, Packages) ausgelagert.

Als eine der besten Möglichkeiten, einen Wizard zu realisieren, wird ja oft die PageControl in Verbindung mit TabSheets genannt. Also habe ich auch schon mich daran versucht, auf dem Hauptformular nur eine leere PageControl zu platzieren und die TabSheets dann in eine DLL auszulagern. Jedoch scheiterte es daran, das TabSheet anschließend in die PageControl einzubinden, so dass es dort auch sichtbar wird. Ich hab der von der DLL veröffentlichten "CreateTabSheet"-Funktion das Handle der PageControl übergeben, sodass dort ein neues TabSheet mit der PageControl aus dem Hauptformular als Parent kreiert werden kann. Nur reicht das ja noch nicht, um das TabSheet auch dort sichtbar zu machen. Und daran hängts momentan irgendwie.
Was ich allerdings auch noch nicht weiß ist, wie kann man in der DLL ein reines TabSheet ohne Formular und PageControl erzeugen kann und dieses dann auch mit Komponenten wie Buttons, Labels etc. bestücken??? Ohne Formular kann man sich doch auch gar nicht so schön eine Oberfläche "zusammenklicken" oder?

Ansatz Nummer 2 waren die Packages, in die ich mich anhand von einem Beispiel aus dem Netz einarbeiten wollte. Das Progrämmchen sollte schlicht und einfach per Buttonklick ein andres Formular, das in einem Package ausgelagert ist, modal öffnen. Doch obwohl ich mich strikt an die Anleitung bei der Erstellung des Progrämmchens gehalten habe funktioniert es nicht. Das Problem, an dem es wohl hängt: die Klasse TForm2 wird in der Unit2 (die im Package) im initialization-Teil zwar registriert, jedoch SOFORT wieder unregistriert im finalization-Teil. Initialization und finalization laufen also hintereinander weg durch, was doch eigentlich nicht der fall sein sollte, oder?

Hier das Hauptformular:
Delphi-Quellcode:
unit Unit1;

interface

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

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

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
  PackageModule: HModule;
  AClass: TPersistentClass;
begin
  PackageModule := LoadPackage('Package1.bpl');
  if PackageModule <> 0 then
  begin
    AClass := GetClass('TForm2');
      if AClass <> nil then
      with TComponentClass(AClass).Create(Application)
        as TCustomForm do
      begin
        ShowModal;
        Free;
      end;
    UnloadPackage(PackageModule);
  end;
end;

end.
Hier das Formular 2 aus dem Package:
Delphi-Quellcode:
unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
  TForm2 = class(TForm)
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.DFM}

initialization

RegisterClass(TForm2);

finalization

UnRegisterClass(TForm2);

end.
In der Jedi-VCL gibt es wohl bereits eine Wizard-Komponente, allerdings kommt deren Einsatz für uns wohl nicht in Frage (gibt es da irgendwelche Lizenz-technischen Gründe?). Wobei ich auch nicht weiß, ob die überhaupt so einen dynamischen Aufbau unterstützen würde.

Was habt ihr mir für Ratschläge? Wie kann ich das Konzept "Hauptprogramm mit Container" - "Plugins für die Wizard-Seiten" am besten realisieren?

Danke schonmal für die Hilfe!
  Mit Zitat antworten Zitat
Master_BB

Registriert seit: 17. Mai 2003
285 Beiträge
 
Delphi 7 Professional
 
#2

Re: Dynamischen Wizard realisieren

  Alt 22. Apr 2005, 08:36
also das mit den TahSheets ist recht einfach das habe ich bei einem meiner Projekte auch gemacht.
am besten du legst dir dafür 2 Objekte an eine TabSheetList und ein TabSheetItem.
Beim TabSheetItem machst du ne Tabsheet property und alles zeug was das
tabsheet halt so haben soll, buttons, listviews usw.
bei der tabsheetlist gibst du beim erstellen die pagecontrol mit die du dort auch als
property speicherst die brauchst du dann. dann nimmst dir ne routine namens createtabsheets
und läßt dann von der tabsheetlist welche von TObjectList oder ähnlichem abgeleitet ist
die tabsheetitems erstellen und in die liste eintragen.
aus einem meiner projekte kann cih dir ja mal den code der tabsheetliste beim erstellen geben.

Delphi-Quellcode:
      for SectionIndex := 0 to Pred(AVideoListenSections.Count) do
      begin
        ANewCreated := False;
        ATabSheetIndex := TabExists(AVideoListenIniFile.ReadString(AVideoListenSections[SectionIndex], 'Name', ''));
        if (ATabSheetIndex = -1) then
        begin
          ATabSheet := TTabSheet.Create(FPageControl);
          AListView := TListView.Create(ATabSheet);
          ATabSheetObjectItem := TTabSheetObjectItem.Create(AListView, ATabSheet);
          ANewCreated := True;
        end
        else //TabSheet Existiert bereits
          ATabSheetObjectItem := TTabSheetObjectItem(Items[ATabSheetIndex]);

        ATabSheetObjectItem.LoadFromIniFile(BuildFileName(AApplicationPath, ConstU.VideoListenFileName),
                                            AVideoListenSections[SectionIndex]);
        with ATabSheetObjectItem do
        begin
          AIniFile := TIniFile.Create(BuildFileName(MainForm.ApplicationPath, ConstU.MM3SettingsFile));
          try
            if Visible then
            begin
              TabSheet.PageControl := FPageControl;
              TabSheet.Caption := Name;
              TabSheet.ImageIndex := IconIndex;
              ListView.Parent := TabSheet;
              ListView.Align := alClient;
              ListView.Color := BackgroundColor;
              ListView.FlatScrollBars := AIniFile.ReadBool('Allgemein', 'FlatScrollBars', False);
              ListView.Font.Color := LettersColor;
              ListView.GridLines := ShowGrids;
              ListView.HideSelection := False;
              ListView.MultiSelect := True;
              ListView.PopupMenu := MainForm.OptionsPopupMenu;
              ListView.ReadOnly := True;
              ListView.RowSelect := True;
              ListView.ShowColumnHeaders := ShowHead;
              ListView.OnColumnClick := ListViewOnColumnClick;
              MakeListViewHeader;
            end;
ja das ist von meinem MovieManager projekt an dem ich schon seit einiger zeit arbeite, da hat man dynamisch viele tabsheets mit listen. drum wird hier auf dem tabsheet auch nur sichtbar die listview erstellt.
vorher wird oben noch einwenig abgefragt ob das zeug schon in der pagecontrol ist und nur aktualisiert werden muss usw.
kann man ja gut lesen.
ich hoffe ich konnte in dem punkt ein wenig helfen
Wenn das Meer unruhig ist und der Wind die Wellen treibt, erfreut es, vom Strand aus die Mühen eines Anderen zu beobachten.
  Mit Zitat antworten Zitat
MatthiasR

Registriert seit: 21. Apr 2005
193 Beiträge
 
#3

Re: Dynamischen Wizard realisieren

  Alt 22. Apr 2005, 09:29
Sorry aber das verstehe ich noch nicht ganz. Woher bekomme ich diese 2 Objekte TabSheetList und TabSheetItem? Von welcher Klasse sollen das Instanzen sein? Und hast du das ganze dann als DLL realisiert oder wie? Wenn ja, wie schaut deine Schnittstelle aus? Und wie komme ich von dieser TabSheetListe dann zu meinen TabSheets auf dem Formular???
  Mit Zitat antworten Zitat
Benutzerbild von alcaeus
alcaeus

Registriert seit: 11. Aug 2003
Ort: München
6.537 Beiträge
 
#4

Re: Dynamischen Wizard realisieren

  Alt 22. Apr 2005, 09:45
Hallo Infect,

evtl. kannst du eine der Klassen verwenden, die Torry.net anbietet: http://www.torry.net/quicksearchd.ph...zard&Title=Yes
Wir hatten auf Arbeit auch eine Wizard-Klasse, allerdings erinnere ich mich leider nicht mehr an den Namen
Ein paar der Komponenten auf Torry sehen aber ziemlich vielversprechend aus...

Greetz
alcaeus
Andreas B.
Die Mutter der Dummen ist immer schwanger.
Ein Portal für Informatik-Studenten: www.infler.de
  Mit Zitat antworten Zitat
Master_BB

Registriert seit: 17. Mai 2003
285 Beiträge
 
Delphi 7 Professional
 
#5

Re: Dynamischen Wizard realisieren

  Alt 22. Apr 2005, 17:09
-selber schreiben ist immer lehrreicher und macht mehr spaß

sorry ich war arbeiten ergo erst so spät die nächste antwort,
also woher bekommst du die objekte ganz einfach du machst ne unit auf muss keine dll sein
und erstellst sie.

also hier die beiden Objete wie du sie erstellen kannst
Delphi-Quellcode:
TabSheetItem = class
private
protected
  FName : string;
  FTabSheet : TTabSheet;
public
  property Name : string read FName write FName;
  property TabSheet : TTabSheet read FTabSheet write FTabSheet;
  constructor Create(AOwner : TComponent); //WICHTIG
end;

TabSheetList = class(TObjectList)
private
protected
  FPageControl : TPageControl;
public
  constructor Create(APageControl : TPageControl);
  property PageControl : TPageControl read FPageControl write FPageControl;
  procedure LoadTabSheets;
end;

//DER TABSHEETITEM CONSTRUCTOR IST WICHTIG DAS DAS TABSHEET ERSTMAL DA IST
constructor TabSheetItem.Create(AOwner : TComponent);
begin
  inherited;
  FTabSheet := TTabSheet.Create(AOwner);
end;

constructor TabSheetList.Create(APageControL : TPageControl);
begin
  inherited Create;
  FPageControl := APageControl;
end;

procedure TabSheetList.LoadTabSheets;
var
  AQuellTabSheetNamen : TStringList;
  ATabSheetItem : TTabSheetItem;
  ItemIndex : integer;
begin
  AQuellTabSheetNamen := TStringList.Create;
  try
    AQuellTabSheetNamen := //ja die ließt du aus irgentnem gespeicherten ort ein z.B. eine INI file
                            //da das bei dir ja variiert könntest du immer paare in die ini schreiben
                            //den Namen und obs ausgeführt wird was vorher dann in die ini geschrieben wird
                            //nach verschiedenen check routinen wovon du deine tabsheets abhänig machst
    for ItemIndex := 0 to Pred(AQuellTabSheetNamen.Count) do
    begin
      ATabSheetItem := TTabSheetItem.Create(FPageControl);
      with ATabSheetItem do
      begin
        //hier setzt du jetzt die eigenschaften des tabsheet items
        //wichtig sind
        Parent := FPageControl;
        Caption := AQuellTabSheetNames[ItemIndex];
      end;
      //jetzt kannst auch die ganzen sachen die noch drauf sollen erstellen non Visuell versteht sich
      Add(ATabSheetItem); //Das item in die liste aufnehmen
    end;
  finally
    FreeAndNil(AQuellTabSheetNamen);
  end;
end;
so an sich sind dei beiden objekte dann deine schnittstelle zwischen PageControl und TabSheets.

am besten die TabSheetList erstellst du beim OnFormCreate ereignis deiner MainForm und trägst dort
die liste gleich als property in die form mit ein unter public.
beim erstellen gibst du dem objekt ja die PageControl die du auf deiner Form hast mit damit hast du in den
objekten immer zugang zu dieser Pagecontrol auf der Form und kannst jetzt im hintergrund akkern.
so und wie kommst du wenn du auf der form arbeitest immer zu deinen tabsheets? naja
die mußt du dann suchen, jedes tabsheet hat doch einen namen was du auch in das tabsheetitem einbaust
und danach durchsuchst du einfach die liste
so hier zum beispiel als suchroutine für die liste wo du einfach den tabsheet namen mitgibst
Delphi-Quellcode:
function TabSheetList.GetTabSheetWithName(AName : string) : TTabSheetItem;
var
  ItemIndex : integer
begin
  Result := nil;

  for ItemIndex := 0 to Pred(Count) do
  begin
    if CompareText(TTabSheetItem(Items[ItemIndex]).Name, AName) = 0 then
    begin
      Result := TTabSheetItem(Items[ItemIndex]);
      Break;
    end;
  end;
end;
so ich schreib jetzt oben noch schnell die tabsheet erstell routine in die liste und dann
hast du schon nen recht gut ausgerüstetes gerüst und hast gleich nen bissle objectorientierung
gelernt.
Wenn das Meer unruhig ist und der Wind die Wellen treibt, erfreut es, vom Strand aus die Mühen eines Anderen zu beobachten.
  Mit Zitat antworten Zitat
MatthiasR

Registriert seit: 21. Apr 2005
193 Beiträge
 
#6

Re: Dynamischen Wizard realisieren

  Alt 25. Apr 2005, 08:18
Vielen Dank erstmal für deine ausführliche Hilfe, ich denke, da kann ich mir einiges für mein Projekt herausziehen! Was ich noch nicht ganz verstanden habe, wobei ich mich im Vorfeld vielleicht auch etwas unklar ausgedrückt habe, ist: wie erreichst du durch deine TabSheet-Liste, dass man später wenn das Programm fertig ist, beliebig TabSheets hinzufügen oder entfernen kann, ohne erneut am Quellcode des Programmes etwas ändern zu müssen? Also wenn dir später einfallen sollte, du brauchst an dieser und jener Stelle noch zusätzliche TabSheets, dass du diese dann einbinden kannst (wie z.B. durch eine DLL) ohne das Programm erneut compilieren zu müssen. Ziel ist es eben, dem Kunden und Nutzer des Wizards, wenn dieser neue Funktionalität wünscht, ihm eine fertig compiliertes Zusatz-Modul in die Hand zu drücken, das er nur irgendwo ablegen muss (und wegen mir noch in irgendeiner ini-File was dazuschreiben), und der Wizard dann dieses Zusatzmodul automatisch lädt und einbindet, ohne dass man eben an IHM noch was ändern müsste. In welcher Form würdest du also in deinem Fall dem Benutzer deines Programms diese Zusatzfunktionalität zu Verfügung stellen?
  Mit Zitat antworten Zitat
Master_BB

Registriert seit: 17. Mai 2003
285 Beiträge
 
Delphi 7 Professional
 
#7

Re: Dynamischen Wizard realisieren

  Alt 25. Apr 2005, 11:47
naja an sich kann du in der liste doch eine routine deklarieren die dir nen tabsheet
zusammenbaut, nach bestimmten vorgaben. möglich wäre es z.B. das man einfach
ne TXT mitgibt wo informationen über das tabsheet aussehen drin stehen. die dann
von der routine umgesetzt werden. oder du braust frames die du der routine mitgibst
welche diese nur auf das tabsheet setzt das es erstellt.

bei mir ist es z.B. eine Typisierte Datei wo infos über die movieliste drin stehen.
zB.
[Doku]
Name=Doku
BackgroundColor=clMoneyGreen
IconIndex=0
LettersColor=clBlack
PWActive=0
ShowHead=1
ShowGrids=1
Visible=1

ich hab eine routine die heißt halt loadtabsheets(afilename : string);
der gebe ich den dateinamen dieser typfile mit und dann baut der nen tabsheet
auf dem ne listview ist mit bestimmten eigenschaften.

du könntest
[Name] //des tabsheets
TLabel=Label1
Label1Width=xxx
usw

und dann läßte die routine das so zusammen bauen.
Wenn das Meer unruhig ist und der Wind die Wellen treibt, erfreut es, vom Strand aus die Mühen eines Anderen zu beobachten.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:56 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