Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Eventprocedur bei virtuellen Objekten (https://www.delphipraxis.net/182935-eventprocedur-bei-virtuellen-objekten.html)

Ykcim 27. Nov 2014 14:52

Eventprocedur bei virtuellen Objekten
 
Hallo Zusammen,

wenn ich einen Button auf ein Formular ziehe, dann habe ich in dem Objektinspektor unter Ereignisse einige Procedure, die bei einem Event ausgeführt werden, z.B. onClick.

Ich habe jetzt in einer Unit ohne Formular ein Objekt created und möchte gerne eine der Eventproceduren verwenden. Es handelt sich nicht um einen Button, sondern um eine TAdvGirdExcel Komponente.

Aber vielleicht bleiben wir der Einfachheit halber bei einem Button. Wenn ich den jetzt virtuel erzeuge, wie kann ich ihm die Eventprocedure onClick zuweisen?

Vielen Dank
Patrick

himitsu 27. Nov 2014 14:55

AW: Eventprocedur bei virtuellen Objekten
 
Zitat:

virtuell
Du erstellst die Komponente schon "real".

Das was du meinst nennt sich "dynamisch erstellen", also quasi manuell.


Es gibt das Property
Delphi-Quellcode:
DeineKomponente.OnClick
und dem weist du deine Methode zu (
Delphi-Quellcode:
x.OnEvent := EventMethode;
).

Sir Rufo 27. Nov 2014 14:57

AW: Eventprocedur bei virtuellen Objekten
 
Delphi-Quellcode:
MyNewButton := TButton.Create( ... );
MyNewButton.OnClick := MyVeryFineButtonClickMethod;

Sherlock 27. Nov 2014 14:58

AW: Eventprocedur bei virtuellen Objekten
 
Also, erstens ist der nicht virtuell erzeugt, sondern wirklich und wahrhaftig da, nur eben (jetzt kommt der korrekte Fachausdruck) dynamisch erzeugt.
Nun zur eigentlichen Frage: Du kannst einem Event wie zB
Delphi-Quellcode:
Button.OnClick
ganz einfach jede Methode zuweisen, die die korrekte Signatur hat. In diesem Fall
Delphi-Quellcode:
procedure BeleibigerName(Sender:TObject);
. Was zu
Delphi-Quellcode:
Button.OnClick := BeleibigerName;
wird.

Sherlock

Ykcim 27. Nov 2014 15:11

AW: Eventprocedur bei virtuellen Objekten
 
WOW!!! Vielen Dank für die schnellen und guten Antworten. So wird es klappen, habe noch ein paar Probleme mit den Parametern([DCC Fehler] TExcelExportUnit.pas(233): E2010 Inkompatible Typen: 'tmsUFlxFormats.TFlxFormat' und '_UFlxFormats.TFlxFormat.TFlxFormat'), die ich aber hoffentlich alleine gelöst bekomme.

Vielen Dank
Patrick

DeddyH 27. Nov 2014 15:12

AW: Eventprocedur bei virtuellen Objekten
 
Öhm... nö, es darf keine reguläre Prozedur, sondern muss eine Methode sein. Zur Not muss man sich eben eine Dummy-Klasse erstellen, die diese Methode dann implementiert.

Helmi 27. Nov 2014 15:25

AW: Eventprocedur bei virtuellen Objekten
 
Zitat:

Zitat von DeddyH (Beitrag 1281357)
Öhm... nö, es darf keine reguläre Prozedur, sondern muss eine Methode sein. Zur Not muss man sich eben eine Dummy-Klasse erstellen, die diese Methode dann implementiert.

warum eigentlich?

Über das bin ich auch schon mal geflogen - aber theoretisch könnt das doch egal sein, ob es eine reguläre Prozedur oder eine Methode ist

Sir Rufo 27. Nov 2014 15:29

AW: Eventprocedur bei virtuellen Objekten
 
Zitat:

Zitat von Helmi (Beitrag 1281359)
Zitat:

Zitat von DeddyH (Beitrag 1281357)
Öhm... nö, es darf keine reguläre Prozedur, sondern muss eine Methode sein. Zur Not muss man sich eben eine Dummy-Klasse erstellen, die diese Methode dann implementiert.

warum eigentlich?

Über das bin ich auch schon mal geflogen - aber theoretisch könnt das doch egal sein, ob es eine reguläre Prozedur oder eine Methode ist

Natürlich wäre es egal, aber wenn der Event als
Delphi-Quellcode:
TFooEvent = procedure ... of object;
deklariert ist, dann muss es eine Methode sein.

Bei den neueren Delphis könnte man auch
Delphi-Quellcode:
TFooEvent = reference to procedure ...;
nehmen, dann frisst der alles, bis auf den OI, der wird da wohl nicht mitspielen.

Helmi 27. Nov 2014 15:45

AW: Eventprocedur bei virtuellen Objekten
 
D. h. einzig die Definition ist "schuld" daran?

Ykcim 27. Nov 2014 15:48

AW: Eventprocedur bei virtuellen Objekten
 
Hallo Zusammen,

ich habe es jetzt umgesetzt bekommen. Ich musste tatsächlich eine DummyKlasse erstellen und einbinden, weil zwei TMS-Klassen in ein und derselben Unit nicht vertrugen. Zwei Mal den gleichen Namen für unterschiedliche Typen...

Aber jetzt klappt es.

Danke
Patrick

Sir Rufo 27. Nov 2014 15:49

AW: Eventprocedur bei virtuellen Objekten
 
Zitat:

Zitat von Helmi (Beitrag 1281363)
D. h. einzig die Definition ist "schuld" daran?

Ja, sehr ungewöhnlich für eine als typsicher bekannte Sprache ... :roll:

Helmi 27. Nov 2014 15:52

AW: Eventprocedur bei virtuellen Objekten
 
Zitat:

Zitat von Sir Rufo (Beitrag 1281366)
Zitat:

Zitat von Helmi (Beitrag 1281363)
D. h. einzig die Definition ist "schuld" daran?

Ja, sehr ungewöhnlich für eine als typsicher bekannte Sprache ... :roll:

Bazinga :-)

Sir Rufo 27. Nov 2014 15:53

AW: Eventprocedur bei virtuellen Objekten
 
Zitat:

Zitat von Ykcim (Beitrag 1281365)
Hallo Zusammen,

ich habe es jetzt umgesetzt bekommen. Ich musste tatsächlich eine DummyKlasse erstellen und einbinden, weil zwei TMS-Klassen in ein und derselben Unit nicht vertrugen. Zwei Mal den gleichen Namen für unterschiedliche Typen...

Aber jetzt klappt es.

Danke
Patrick

Nein, muss man nicht, wenn man den Typen exakt mit Unitnamen benutzt, dann ist das Wumpe.
Delphi-Quellcode:
uses
  Foo,
  Bar;
var
  LVar1 : TFooBar; // ist Bar.TFooBar, da Bar nach Foo in den uses
  LVar2 : Foo.TFooBar;
  LVar3 : Bar.TFooBar;
 
procedure UseFooBar( Val : Foo.TFoobar ); overload;
procedure UseFooBar( Val : Bar.TFooBar ); overload;

himitsu 27. Nov 2014 16:04

AW: Eventprocedur bei virtuellen Objekten
 
Bei Eventzeigern für Methoden kann man auch Klassen-Methoden (
Delphi-Quellcode:
class procedure
) übergeben, dann braucht man zwar immernoch eine Klasse (wobei man seinen Code natürlich schön nach OOP zusammenfasst),
aber man braucht dann nicht unbedingt eine Instanz der Klasse.

Ykcim 27. Nov 2014 16:16

AW: Eventprocedur bei virtuellen Objekten
 
Zitat:

Nein, muss man nicht, wenn man den Typen exakt mit Unitnamen benutzt, dann ist das Wumpe.
Und wieder etwas gelernt! Danke!

Ich habe es jetzt so gemacht:
Delphi-Quellcode:
unit TExcelExportUnit;

interface

uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ComObj, Grids, AdvObj, BaseGrid, Math, ShellApi,
      AdvGrid,tmsUFlxFormats, VCL.FlexCel.Core, FlexCel.XlsAdapter, FlexCel.Render,
      tmsAdvGridExcel;

type
   TExcelExport = class
      strict protected
         FExcelApp: OleVariant;
         FWorkbook: OleVariant;
         Fxls: TExcelFile;
         FAutor: string;
         FFirma: string;
         FLogo_Pfad: string;    //Pfad des Logos
         FQuer_Format: boolean; //Wenn true, dann Querformat, ansonsten Hochformat
         FSeiten_Ver: integer;
         FSeiten_Hor: integer;
         FSheet: integer;
         FSheets: Integer;
         FTitel: string;
         //Das ist die Procedure, die ich zuweise.
         procedure GridExcelCellFormat(Sender: TAdvStringGrid; const GridCol,
                   GridRow, XlsCol, XlsRow: Integer; const Value: WideString;
                   var Format: tmsUFlxFormats.TFlxFormat);
      public
         procedure OpenTemp;
         procedure ShowTemp(Pfad: string);
         procedure SaveFile(SG: TAdvStringGrid; dateiname: string);
         procedure CreateXLSFile(Sheets: integer);
         procedure Basis_Design(Sheet: integer; Titel: string);
         procedure Zellen_Groesse(SG: TAdvStringGrid);
         procedure Zellen(fmt: TFlxFormat; SG: TAdvStringGrid);
         property Autor: string read FAutor write FAutor;
         property Firma: string read FFirma write FFirma;
         property Logo_Pfad: string read FLogo_Pfad write FLogo_Pfad;
         property Quer_Format: boolean read FQuer_Format write FQuer_Format;
         property Seiten_Ver: integer read FSeiten_Ver write FSeiten_Ver;
         property Seiten_Hor: integer read FSeiten_Hor write FSeiten_Hor;
         property ExcelApp: OleVariant read FExcelApp;
         property Workbook: OleVariant read FWorkbook;
         property Anzahl_Sheets: integer read FSheets write FSheets;
         property Aktives_Sheet: integer read FSheet write FSheet;
         property Sheet_Titel: string read FTitel write FTitel;
   end;

var ExportGrid: TExcelExport;

implementation

procedure TExcelExport.GridExcelCellFormat(Sender: TAdvStringGrid; const GridCol,
  GridRow, XlsCol, XlsRow: Integer; const Value: WideString;
  var Format: tmsUFlxFormats.TFlxFormat);  //Hier musste ich den Typen mit dem Unitnamen ansprechen.
begin
   if (Sender as TAdvStringGrid).Cells[GridCol,0]='Menge' then
      Format.Format:='#,##0';
end;


procedure TExcelExport.SaveFile(SG: TAdvStringGrid; dateiname: string);
var  fmt: TFlxFormat;
      Pfad: string;
      GridExcel: TAdvGridExcelIO;
begin
   try
      Pfad:=ExtractFilePath(ParamStr(0))+'Temp\Export'+StringReplace(DateToStr(now)+'-'+TimeToStr(now),':','-',[rfIgnoreCase, rfReplaceAll])+'.xlt';
      GridExcel:= TAdvGridExcelIO.Create(nil);
      GridExcel.AdvStringGrid:=SG;
      GridExcel.GridStartRow:=0;
      GridExcel.GridStartCol:=0;
      GridExcel.OnCellFormat:=GridExcelCellFormat;   //Hier wird sie zugewiesen

      GridExcel.XLSExport(Pfad,SG.Name);
      Fxls := TXlsFile.Create(true);
      Fxls.Open(Pfad);
      DeleteFiles(Pfad);
      Basis_Design(FSheet, FTitel);
      Zellen(fmt, SG);
      if dateiname='' then begin
         Fxls.Save(Pfad);
         ShowTemp(Pfad);
         DeleteFiles(Pfad);
      end
      else begin
         //Save the file as XLS
         Fxls.Save(dateiname);
      end;
  finally
      Fxls.Free;
      GridExcel.Free;
  end
end;

initialization
   ExportGrid := TExcelExport.Create;

finalization
   if ExportGrid <> nil then
      ExportGrid.Free;

himitsu 27. Nov 2014 16:44

AW: Eventprocedur bei virtuellen Objekten
 
Man kann auch über die Reihenfolge der Units im Uses regeln, was verwendet wird. -> immer das der letzten Unit (wenn man keinen Namespace angibt)

Zitat:

Delphi-Quellcode:
if ExportGrid <> nil then
  ExportGrid.Free;

PS: Im Free ist bereits eine Prüfung eingebaut.
Du kannst also auch direkt das Free aufrufen.


Zitat:

Delphi-Quellcode:
try
      GridExcel:= TAdvGridExcelIO.Create(nil);
finally
      GridExcel.Free;
end

Ist dir noch nicht aufgefallen, daß dir der Delphi-Compiler hier zurecht eine Warnung um die Ohren haut?
Entweder das Crerate direkt vor dem Try, oder vorher die Variable initialisieren (
Delphi-Quellcode:
GridExcel:=nil;
),
denn wenn es vor oder in dem Create knallt, dann geht das Free auf die nicht-initialisierte Variable los und es knallt womöglich nochmal-
* entweder es zerschoßt dir zufällig irgendwas Anderes
* oder eine weitere Exception im Free (meistens Zugriffsverletzung) schrottet/überdeckt dir die eigentliche Fehlermeldung


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:27 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