Formular zur Laufzeit erzeugen ?

Rund um die LCL und andere Komponenten
Antworten
Cocky
Beiträge: 46
Registriert: Sa 15. Nov 2008, 13:17

Formular zur Laufzeit erzeugen ?

Beitrag von Cocky »

Ich hab eine Unit, die sich hauptsächlich um die Vewaltung einer bestimmten Datenbank kümmert. Diese kommt bisher gut ohne visuelle Komponenten aus und ich hab sie auch so aufgebaut, daß ich sie für mehrere Projekte 'recyclen' kann. Nun möchte ich wärend länger andauernden Läufen eine Progress Bar einbauen, die in einem eigenen Mini Fenster (50x300 Pixel) angezeigt wird.

Ich habs bisher erfolglos so versucht : (Auszug)

Code: Alles auswählen

unit InvDB; 
 
{$mode objfpc}{$M+}
 
interface
 
uses
  Classes, SysUtils, Dialogs, Dbf, db, Dbf_Common, Graphics, STIclass,
  Forms, StdCtrls, ComCtrls, Controls;
 
type
// ********** TDBProgress Class *************************************//
   TDBProgress = class
 
   private
   FForm:  TForm;
   FLabel: TLabel;
   FBar:   TProgressBar;
   FMin:   Integer;
   FMax:   Integer;
 
   procedure SetProgress (Progress: Integer);
 
   public
   // Constructor and Destructor
   constructor Create(Min, Max: Integer; Title: String);
   destructor Destroy; override;
   property Progress: Integer write SetProgress;
   procedure Step;
 
end;   
...
implementation
...
//********************************************************//
// TDBProgress  implementation                            //
//********************************************************//
 
constructor TDBProgress.Create (Min, Max: Integer; Title: String);
begin
   inherited Create;
   FForm             := TForm.Create(owner);
   FForm.Height      := 50;
   FForm.Width       := 300;
   FForm.Position    := poScreenCenter;
   FForm.FormStyle   := fsStayOnTop;
   FForm.Caption     := Title;
   FForm.BorderIcons := FForm.BorderIcons - [biHelp];
   FForm.BorderIcons := FForm.BorderIcons - [biMaximize];
   FForm.BorderIcons := FForm.BorderIcons - [biMinimize];
   FForm.BorderIcons := FForm.BorderIcons - [biSystemMenu];
   FForm.BorderStyle := bsSingle;
   FLabel            := TLabel.Create(FForm);
   FLabel.Parent     := FForm;
   FLabel.Caption    := 'Fortschritt :';
   FLabel.Font.Style := FLabel.Font.Style + [fsBold];
   FLabel.Font.Style := FLabel.Font.Style + [fsUnderline];
   FLabel.Top        := 5;
   FLabel.Left       := 5;
   FBar              := TProgressBar.Create(FForm);
   FBar.Parent       := FForm;
   FBar.Min          := Min;
   FMin              := Min;
   FBar.Max          := Max;
   FMax              := Max;
   FBar.Top          := 25;
   FBar.Left         := 5;
   FBar.Height       := 20;
   FBar.Width        := 290;
   ShowMessage('Create');     // nur zum Testen, ob aufgerufen wird
   FBar.StepBy(1);
   FLabel.Show;
   FBar.Show;
   FForm.Show;
 
end;
 
destructor TDBProgress.destroy;
begin
  inherited destroy;
  FForm.Close;
  FLabel.Free;
  FBar.Free;
  FForm.Free;
end;
 
procedure TDBProgress.SetProgress (Progress: Integer);
begin
   FBar.Position := Progress;
end;
procedure TDBProgress.Step;
begin
   FBar.StepIt;
end;
und dann in der Main ....

Code: Alles auswählen

private 
PBar: TDBProgress;
...
implementation
...
procedure TForm1.Button1Click(Sender: TObject);
// var   PBar: TDBProgress;  <--- so gibts SIGSEGV !
begin
  PBar.Create(0,100,'Test Bar');
  ShowMessage('mal gucken ....');
  PBar.Free;
end;
Passieren tut gar nichts. Auch keine Fehlermeldung. Der Construktor wird auch nicht ausgeführt (zumindest kommt die Messagebox nicht, die ich eingebaut hab). Irgendwie hab ich da wohl nen Knoten im Hirn. Hab sämtliche Onlinequellen nachgelesen und auch meine 2 Delphi Bücher helfen mir nicht wirklich ...

Kann mir jemand sagen, wie man's richtig macht ??

LG Cocky

KOBOLD Messring GmbH
Beiträge: 155
Registriert: Mi 22. Aug 2007, 14:52
OS, Lazarus, FPC: Mandriva Linux 2008 (L 0.9.28 FPC 2.2.4)
CPU-Target: 32Bit
Wohnort: 65719 Hofheim am Taunus
Kontaktdaten:

Re: Formular zur Laufzeit erzeugen ?

Beitrag von KOBOLD Messring GmbH »

1. Musst Du sowas machen (den Klassen-Konstruktor aufrufen):

Code: Alles auswählen

PBar := TDBProgress.Create (0,100,'Test Bar');
2. Dein Progress-Bar wird zwar wohl irgendwie aktualisiert werden, aber die Anwendung verarbeitet die Window-Messages nicht: da muss ein Application.ProcessMessages rein, damit der ProgressBar auch neu gezeichnet wird (bei jeder Veränderung seines Wertes Progress).

3. Ich hätte es anders rum gemacht: Du hast eine Klasse, die ein Fenster beinhaltet (FForm). Ich habe solche Dinger mit einer Klasse, die direkt von TForm erbt, gemacht. Also einfach ein Dialogfenster in der Lazarus-IDE designed und eine public Procedure AktualisiereProgressBar (nNeuerWert: Integer); (oder sowas in der Art), die dann vom Hauptprogramm aufgerufen wird. mit FormProgress.Show; FormProgress.AktualisiereProgressBar (50); und dann FormProgress.Hide;

Cocky
Beiträge: 46
Registriert: Sa 15. Nov 2008, 13:17

Re: Formular zur Laufzeit erzeugen ?

Beitrag von Cocky »

KOBOLD Messring GmbH hat geschrieben:1. Musst Du sowas machen (den Klassen-Konstruktor aufrufen):

Code: Alles auswählen

PBar := TDBProgress.Create (0,100,'Test Bar');
OMG :shock: ! ... gutes kann so einfach sein ! Liegt warscheinlich daran, daß man sich den ganzen Tag auf ein Problem verbeißt und einem dann selbst die einfachsten Fehler nicht mehr auffallen.
KOBOLD Messring GmbH hat geschrieben:2. Dein Progress-Bar wird zwar wohl irgendwie aktualisiert werden, aber die Anwendung verarbeitet die Window-Messages nicht: da muss ein Application.ProcessMessages rein, damit der ProgressBar auch neu gezeichnet wird (bei jeder Veränderung seines Wertes Progress).
Du meinst so in etwa ??

Code: Alles auswählen

procedure TDBProgress.SetProgress (Progress: Integer);
begin
   if (Progress < FMax) and (Progress >= FMin) then 
      begin
      FBar.Position := Progress;
      Application.ProcessMessages;
      end;
end;
KOBOLD Messring GmbH hat geschrieben:3. Ich hätte es anders rum gemacht: Du hast eine Klasse, die ein Fenster beinhaltet (FForm). Ich habe solche Dinger mit einer Klasse, die direkt von TForm erbt, gemacht. Also einfach ein Dialogfenster in der Lazarus-IDE designed und eine public Procedure AktualisiereProgressBar (nNeuerWert: Integer); (oder sowas in der Art), die dann vom Hauptprogramm aufgerufen wird. mit FormProgress.Show; FormProgress.AktualisiereProgressBar (50); und dann FormProgress.Hide;
Hätte ich warscheinlich auch. Allerdings weiß die MainUnit nicht, wie weit die DatenbankUnit mit ihrer Arbeit ist. Und kann daher auch nicht den Progress setzen. Die DBUnit bzw. -Klasse liest z.B. eine xml Datei ein, um die Bezeichnungen der Datensätze zu lokalisieren (Namen und Beschreibungen mit einer anderen Sprache (z.B. Russisch) zu überschreiben). Soll ja eben gerade der Sinn sein, daß sich die Main Unit nicht mehr darum kümmern muß und die DBUnit zudem 'recycled' werden kann.

Und bevor ich es vergesse ... ganz herzlichen Dank für Deine Antwort !!! :)

LG Cocky

KOBOLD Messring GmbH
Beiträge: 155
Registriert: Mi 22. Aug 2007, 14:52
OS, Lazarus, FPC: Mandriva Linux 2008 (L 0.9.28 FPC 2.2.4)
CPU-Target: 32Bit
Wohnort: 65719 Hofheim am Taunus
Kontaktdaten:

Re: Formular zur Laufzeit erzeugen ?

Beitrag von KOBOLD Messring GmbH »

Du meinst so in etwa ??
Genau das meinte ich, sonst arbeitet die Anwendung die komplette DB-Schaufelei ab um dann am Schluss mit allen aufgelaufenen Windows-Messages den Progress-bar 100mal zu aktualisieren :)
P.D. Gern geschehen.

Antworten