| Autor |
Beitrag |
fishhed
      
Beiträge: 77
Delphi 7
|
Verfasst: Di 06.03.07 13:56
Hallo zusammen,
hier noch ne Anfängerfrage zu DLLs:
Ich möchte eine DLL erstellen, die externe Komponenten (List&Label 11 von der Firma combit) verwendetet.
Geht das?
Hier mein Konkretes Beispiel. Ich möchte eine DLL haben die bei Aufruf genau das Gleiche ausführt, das passiert wenn man Button2 drückt. Ich möchte also dieses Mini-Programm in eine DLL umwandeln:
(Leider ist LL nicht openSource, von daher werdet Ihr es wohl nicht genau so ausprobieren können.)
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: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68:
| unit main;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, l11, cmbtLL11, StdCtrls;
type TForm1 = class(TForm) LL: TL11_; Button2: TButton; procedure LLDefineVariables(Sender: TObject; UserData: Integer; IsDesignMode: Boolean; var Percentage: Integer; var IsLastRecord: Boolean; var EventResult: Integer); procedure Button2Click(Sender: TObject); private public end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.LLDefineVariables(Sender: TObject; UserData: Integer; IsDesignMode: Boolean; var Percentage: Integer; var IsLastRecord: Boolean; var EventResult: Integer);
begin LL.LlDefineVariable('vAnzahl', '2'); LL.LlDefineVariable('vLizenzArt', 'Monatslizenz'); LL.LlDefineVariable('vProdukt', 'AutoBINGOOO'); LL.LlDefineVariable('vFirma', 'Autohaus Müller'); LL.LlDefineVariable('vAnrede', 'Herr'); LL.LlDefineVariable('vNachname', 'Müller'); LL.LlDefineVariable('vStrasse', 'Tiefenseestr. 11'); LL.LlDefineVariable('vPlz', '49696'); LL.LlDefineVariable('vOrt', 'Molbergen'); LL.LlDefineVariable('vLand', 'Deutschland'); LL.LlDefineVariable('vStkPreis', '16,83'); LL.LlDefineVariable('vBrutto', '20,00'); LL.LlDefineVariable('vNetto', '35,66'); LL.LlDefineVariable('MwST', '19'); LL.LlDefineVariable('vLizkey', 'UWR70-FMQRE-GGGG-GGGG'); LL.LlDefineVariable('vVon', '12.02.2007'); LL.LlDefineVariable('vBis', '13.02.2008'); LL.LlDefineVariable('vRechnungsnummr', 'ABM234567');
if not IsDesignMode then begin Percentage := 100; IsLastRecord := true; end; end;
procedure TForm1.Button2Click(Sender: TObject); var CurPath: string; ExporterName: string; FileName: string; begin
LL.Print(0, LL_PROJECT_LABEL, 'Etiket2.lbl', false, LL_PRINT_EXPORT, LL_BOXTYPE_NORMALWAIT, handle, 'Print labels to printer', false, ''); ShowMessage(IntToStr(handle)); end;
end. |
|
|
Chryzler
      
Beiträge: 1097
Erhaltene Danke: 2
|
Verfasst: Di 06.03.07 15:13
Ich weiß jetzt nicht, ob man zum dynamischen Erstellen dieser Komponente eine Form braucht. Du musst halt die Komponente in der DLL dynamisch erstellen, ohne Formular.
|
|
fishhed 
      
Beiträge: 77
Delphi 7
|
Verfasst: Di 06.03.07 15:26
Chryzler hat folgendes geschrieben: | | Du musst halt die Komponente in der DLL dynamisch erstellen, ohne Formular. |
Danke für den Tipp. Und wie geht das? Gibt es irgendwo eine kleine Anleitung oder ein Tutorial?
|
|
Chryzler
      
Beiträge: 1097
Erhaltene Danke: 2
|
Verfasst: Di 06.03.07 16:18
| Zitat: |
Wie kann ich Komponenten zur Laufzeit des Programms dynamisch erstellen?
von Sven Künzler 10. September 1998 [ab D1]
Man kann sämtliche Properties aus dem Designer auch im Quelltext setzen. Wichtig ist, dass man als Parent die Form angibt, auf der die Komponente erstellt werden soll.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| Procedure TMyForm.Labelmachen; var ALabel: TLabel Begin ALabel:=TLabel.Create(self); ALabel.Parent:=self; ALabel.Caption:='Beschriftung'; ALabel.Visible:=True; End; |
|
Wie du siehst, muss man dem Konstruktor und der Parent-Eigenschaft die Form zuweisen. Ich wüsste jetzt nicht wie man die irgendwie weglassen könnte.
Bei ner DLL gibts ja keine Forms.
|
|
fishhed 
      
Beiträge: 77
Delphi 7
|
Verfasst: Do 08.03.07 11:48
Okay, das scheint mir logisch. Ich werde es mal ausprobieren...
Nun dazu eine weitere Frage:
Wie kann ich die Ereignisse einer Komponente verändern?
Im speziellen Fall möchte ich bei 'OnCreate' eine Prozedur ausführen.
|
|
wulfskin
      
Beiträge: 1349
Erhaltene Danke: 1
Win XP
D5 Pers (SSL), D2005 Pro, C, C#
|
Verfasst: Do 08.03.07 12:00
Chryzler hat folgendes geschrieben: | Wie du siehst, muss man dem Konstruktor und der Parent-Eigenschaft die Form zuweisen. Ich wüsste jetzt nicht wie man die irgendwie weglassen könnte.
Bei ner DLL gibts ja keine Forms. |
Erstell doch in der Bibliothek eine Methode, welcher du das Formular übergeben kannst, auf welchem die Komponente erstellt werden soll. Dieses [Formular] kannst du ja global speichern.
Zu deiner letzten Frage:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| procedure MyOnCreate(Sender: TObject); begin ShowMessage('HALLo'); end;
OnCreate := MyOnCreate; | Gruß Hape!
|
|
fishhed 
      
Beiträge: 77
Delphi 7
|
Verfasst: Do 08.03.07 12:20
Hmm, ich habe es probiert. Bei mir lässt sich der DLL-Code nicht kompilieren.
Fehlermeldung: "Undefinierter Bezeicherner 'MyOnClick'".
Was mache ich falsch? Hier der komplette Quelltext:
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: 27: 28: 29: 30: 31: 32: 33: 34: 35:
| library dllPdf;
uses SysUtils, Classes, l11, cmbtLL11, Controls, StdCtrls, Dialogs, Forms, Windows;
{$R *.res} var Form1: TForm;
function erzeugePdf(sName: string): PChar; stdcall; begin Form1 := TForm.Create(nil); Form1.Show; Form1.OnClick := MyOnClick;
Result := 'abgeschlossen'; end; exports erzeugePdf;
procedure MyOnClick(Sender: TObject); begin ShowMessage('HALLO'); end;
begin end. |
|
|
fishhed 
      
Beiträge: 77
Delphi 7
|
Verfasst: Do 08.03.07 12:43
Okay, habe es selber hinbekommen. Danke für eure Hilfe!
Das war die Lösung:
Delphi-Quelltext 1:
| Form1.OnClick := Form1.MyOnClick; |
|
|
HelgeLange
      
Beiträge: 735
Erhaltene Danke: 6
Windows 7
Delphi7 - Delphi XE
|
Verfasst: Do 08.03.07 15:02
Wie es gibt keine Forms in DLLs ? Mach ich da jetzt irgendwas falsch, weil ich x-viele Forms in DLLs habe ? Und die auch alle wunderbar funktionieren?
Mal ernsthaft.. ich habe noch nie eine visuelle oder nicht visuelle Komponente getroffen, die sich drüber beschwert hat, nicht auf einem Form erzeugt wurden zu sein. Keine halbwegs vernünftig programmierte Komponente würde das tun, da man ja auch mit einem nil-owner erzeugen kann. In Deiner Routine "ErzeugePdf" brauchst du keine Form, erzeuge einfach Deine List&Label-Komponente und mach, was du machen willst. Zumindest mir scheint es so, als würde die Funktion des Pdfs erzeugen nicht-visuell zu sein (im Gegensatz zum Ergebnis  )
_________________ "Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
|
|
wulfskin
      
Beiträge: 1349
Erhaltene Danke: 1
Win XP
D5 Pers (SSL), D2005 Pro, C, C#
|
Verfasst: Fr 09.03.07 14:31
HelgeLange hat folgendes geschrieben: | | Mal ernsthaft.. ich habe noch nie eine visuelle oder nicht visuelle Komponente getroffen, die sich drüber beschwert hat, nicht auf einem Form erzeugt wurden zu sein. |
Was macht ein Button ohne Form für einen Sinn?
Gruß Hape!
|
|
HelgeLange
      
Beiträge: 735
Erhaltene Danke: 6
Windows 7
Delphi7 - Delphi XE
|
Verfasst: Fr 09.03.07 16:03
ich rede nicht von Sinn oder Unsinn, sondern ob es möglich ist oder nicht. Und man kann einen Button erzeugen, ohne ihn auf ein Form zu legen. und wenn ich das richtig sehe, dann nimmt er den Button ja nur, um das Print anzuschubsen. Kann er ja auf seiner form weiterhin machen, aber eben statt dem print anschubsen einfach in die DLL gehen und es dort anschubsen, richtig?
_________________ "Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
|
|
Chryzler
      
Beiträge: 1097
Erhaltene Danke: 2
|
Verfasst: Sa 10.03.07 13:09
HelgeLange hat folgendes geschrieben: | | ich rede nicht von Sinn oder Unsinn, sondern ob es möglich ist oder nicht. Und man kann einen Button erzeugen, ohne ihn auf ein Form zu legen. und wenn ich das richtig sehe, dann nimmt er den Button ja nur, um das Print anzuschubsen. Kann er ja auf seiner form weiterhin machen, aber eben statt dem print anschubsen einfach in die DLL gehen und es dort anschubsen, richtig? |
Yep.
Wusste nicht, dass man als Owner einfach nil nehmen kann. Wenn nämlich die Kompo auf sein Parent zugreift, dann gibts ne schöne Access Violation.
|
|
HelgeLange
      
Beiträge: 735
Erhaltene Danke: 6
Windows 7
Delphi7 - Delphi XE
|
Verfasst: Sa 10.03.07 13:34
Komponenten baut man so, dass sie NIChT auf ihren parent zugreifen, wenn diser Nil ist. Das gleiche gilt übrigends auch für den Owner oder andere Member-Objeckte 
_________________ "Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
|
|
guido
      
Beiträge: 22
ME
Delphi 3 / 5
|
Verfasst: Do 13.08.09 05:41
Hallo,
habe das selbe Problem, bin nur leider nicht in der Lage das Ergebnis meines "Vorposters" nachzuvollziehen.
- DLL erzeugt Formular , Darauf kommt ein Button mit Parent"Formular" der bei OnClick eine Prozedur oder Funktion anspringen soll..
Code:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| Procedure erzeuge_Formular; begin Formular := TForm.Create(nil); Formular.Show;
MyButton:=TButton.create(Formular); Mybutton.top:=10; Mybutton.left:=10; Mybutton.show; Mybutton.OnClick:=formular.MyOnCLick; end;
Procedure MyOnClick; begin ShowMessage('HALLO'); end;
begin
end. |
Auch wenn ich die Prozedur oben mit "formular.mybutton.click=MyOnClick" definiere passiert nix. Mit fehlt da wohl ein "Anstoss...". Hab versucht diverse Interntergenisse nachzuvollziehen, leider ohne Erfolg.
Gruss
Guido
Moderiert von Narses: Delphi-Tags hinzugefügt
Moderiert von Narses: Überflüssige Zeilenumbrüche/Leerzeilen entfernt.
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 13.08.09 09:54
Das Ereignis erwartet eine Methode, d.h. eine Prozedur innerhalb einer Klasse (z.B. einer Formularklasse). Denn da wird anders als bei normalen Prozeduren noch ein Zeiger auf das Objekt mitgeführt, zu dem die Methode gehört.
Ohne Klasse kann die Zuweisung so also auch nicht gehen.
|
|
jaenicke
      
Beiträge: 19346
Erhaltene Danke: 1754
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 18.08.09 03:37
Auf Rückfrage per PN einmal noch eine kleine Ergänzung:
Es gibt einen Unterschied zwischen einer normalen Prozedur: Delphi-Quelltext 1: 2: 3: 4:
| procedure Foo(Sender: TObject); begin
end; | Und einer Methode einer Klasse: Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| type TFoo = class private procedure Foo(Sender: TObject); end;
... implementation ...
procedure TFoo.Foo(Sender: TObject); begin
end; | Wenn du jetzt eine solche Methode an OnClick zuweist, dann wird dabei auch ein Zeiger auf die Instanz der Klasse (hier TFoo) mit gespeichert. So dass du innerhalb deiner Methode mit Self z.B. auf diese Instanz zugreifen kannst.
Wenn du eine normale Prozedur hast wie im ersten Beispiel, dann hast du ja kein zugehöriges Objekt. OnClick-Ereignisse müssen aber eines haben. Und deshalb funktioniert die Zuweisung nicht.
Du musst also eine eigene Klasse deklarieren wie im zweiten Beispiel und dann eine Instanz davon erzeugen. Die Methode aus der Instanz der Klasse, dem Objekt im Speicher also) kannst du dann dem OnClick-Ereignis zuweisen.
|
|
|