Delphi og DLL'ere

Tags:    delphi

Hej

På en DLL med en form har jeg en Combobox, en edit og 2 buttons (OK og CANCEL).

Jeg har nu 2 spørgsmål:

1: Hvordan lægger jeg fra mit hovedprogram data ind i denne Combobox, og når jeg trykker på OK-knappen skal den indtastede tekst i EDIT-boksen overføres til hovedprogrammet ?

Jeg har prøvet MDI metoden med WM_MESSAGE-metoden, men det er for ustabilt - ca. 10% går galt.

At lave DLL'en er ingen problem (ej heller med form), men dataoverførslen begge veje er et problem (odet gør mig ENDNU mere gråhåret - siger min kone...!). Og som I ved, man må ikke fornærme damerne ... !

Kris







6 svar postet i denne tråd vises herunder
1 indlæg har modtaget i alt 3 karma
Sorter efter stemmer Sorter efter dato
Du skal se en DLL fil som en ekstern del at dit hovedprogram som indeholder simple funktioner.

Hvis du eventuelt har en form i en DLL (eller en anden komponent) skal du sikre dig at din form fungere uafhængig af dit hoved program. Ellers er der ingen idé med at havde den i en DLL. Hvis du nu eksempelvis ville kommunikere med din form vil du havde brug for et interface. Dette interface skal kunne genkendes af både dit hoved program og din DLL. Et eksempel kunne være at du ville skrive til din form's Caption (Vindue tittelen). I din DLL ville du skulle skrive en funktion der kunne hedde: "SetFormCaption", det vil dermed se således ud.

procedure SetFormCaption( const Text : String ); stdcall;
begin
Form1.Caption := Text;
end;

exports SetFormCaption; //Eksporter funktionen

Da denne funktion er inde i din DLL skal du skrive en korrekt Calling Convention. I dette tilfælde vil jeg antage at en stdcall kan bruges. Jeg har dog ikke testet det!

I dit hovedprogram skal du nu skrive en interface der matcher med dine funktioner i din DLL. I dette tilfælde er der kun en funktion. Du skriver derfor:

procedure SetFormCaption( const Text : String ); stdcall; external 'DinDLLFil.dll';

Du kan nu fra dit hovedprogram kalde:

SetFormCaption( 'Test' );

Der skulle dernæst gerne stå 'Test' på formen (i din DLL fil) vindue titel. Hvis du kan få en funktion til at virke med din DLL gør det lige meget om det er en funktion der arbejder sammen med Windows komponenter eller noget helt andet. Det der er utrolig vigtigt i forbindelse med DLL er din Calling Convention. Den SKAL være korrekt for at det kommer til at virke.



Kan du ikke bare skrive nogle funktioner i din DLL fil som kan kaldes fra dit hoved program? Eksempelvis:

char * GetTextInEditBox();

Den vil så returnere den første karakter i din Edit box.

Hvorfor egenlig overhovedet lægge det i en DLL? Er der nogen speciel grund til det eller er det blot for at gøre det så kompleks som muligt? :)



HEJ,

Tak for svaret.

Det kan diskuteres om det er komplekst eller ikke, men hele programmet er opbygget af ca. 25 forms, fylder ca. 3,3 MB i kompileret kode og bruger et utal af biblioteker (dynamisk ca. 10) med hver fra 2 - 50 filer og et enkelt med omkr. 150 filer.

Jo, det er stort.

Ved at anvende DLL'er kan jeg modularisere det meget mere. Reducere størrelsen og dermed vedligeholdelsen bliver nemmere. Derfor jeg vil "DDL'e" det så meget som muligt.

Det skitserede problem er bare for at finde de nødvendige rutiner (indlæsning og udlæsning) til/fra DDL'en.

Iøvrigt anvender jeg IKKE-FORMS DLL'er hvor det er muligt, men det er ikke ret maget.

Nu vil du sikkert spørge om hvorfor jeg ikke bruger PLUG-IN's, svaret hertil er, at jeg endnu ikke har fundet ud af hvordan jeg på en pålidelig måde kan få en MDI-child til at returnere de ønskede data.

(PS: Grundet økonomi kører jeg stadig Delphi-6
Enterprise Udgaven..)

KRIS



Javel ja, som du vil. Men det burde ikke være den store problem at udveksle data fra en DLL til et hoved program. Det bliver dog nødt til at gøres via DLL'ens lidt "primitive" interface. Jeg har tidligere brugt DLL'er som Plugins med stor success i min spilmotor. Så længe dine komponenter køre i samme tråd kan jeg ikke se, hvorfor overførelsen af data mellem DLL og hovedprogram (uanset datatype) ikke skulle være pålidelig. Held og Lykke.




HEJ igen og tak for svaret.

Har du et eller flere links til web-side(r) hvor jeg kan læse/lære lidt mere om det "primitive" DLL-interface ?

Eller bedre: Som et kode eksempel på hvordan det fungerer.

Det lyder ihvertfald bedre end den (endnu mer primitive) løsning jeg havde tænkt at prøve at løse problemet på.

Kris

(Hvis DET er løsningen er du 75 UP / point rigere... !)






Hej igen,

Tak for din tilbagemelding.

Jeg har været flittig og har nu en DDL UDEN FORM men med en selvstændig Interface fil kørende (og det kører som den sødeste drøm da jeg fik rettet alle interfacelinierne til de rette Upper/Lower-case linier. Jeg anede ikke at Delphi var så sensibel her (suk og suk og atter suk) ...


DLL en på eksperimental basis og skal tages som sådan.

Selve DDL filen hedder MyDLL (og en .DPR fil)
Den indeholder kun EXport-kommandoerne for de relevante funkt og procs og en reference til min FORM. Jeg bruger SHAREMEN i denne, men skal senere må FastMM4...)

library MyDLL;

uses
ShareMem,
SysUtils,
Classes,
UDll in 'UDll.pas',
MyNewUnit in 'MyNewUnit.pas' {MyNewDLLform};
(* NOTE 1 *)

{$R *.res}

Exports
DisplayMsg,
MinTest,
BoxProperties,
Flettext,
InsetText,
ShowForm;

begin
end.

Filen UDll som refereres til ser sådan ud:

unit UDll;

interface
Uses
Sharemem, Windows, Dialogs;
(* NOTE 2 *)


Function DisplayMsg(S : String) : Boolean; Stdcall;
Function MinTest : Boolean; Stdcall;
function BoxArea(L, H, W : Double) : Double; Stdcall;
function BoxVolume(L, H, W : Double) : Double; Stdcall;
function BundAreal(L, W : Double) : Double; Stdcall;
procedure BoxProperties(L, H, W : Double; var A, V, B : Double); Stdcall;
Procedure FletText(A1 : String; VAR C1 : String); stdcall;
Function InsetText(S1 : String) : Boolean; stdcall;
Function ShowForm : Boolean; stdcall;

implementation

Function DisplayMsg(S : String) : Boolean; Stdcall;
BEGIN
ShowMessage(S);
Result := True;
END;


Function MinTest : Boolean; Stdcall;
BEGIN
ShowMessage('HEJ MED DIG');
Result := True;
END;

function BoxArea(L, H, W : Double) : Double;
begin
Result := 2 * ((L*H) + (L*W) + (H*W));
end;

function BoxVolume(L, H, W : Double) : Double;
begin
Result := L * H * W;
end;

function BundAreal(L, W : Double) : Double;
begin
Result := L * W;
end;

procedure BoxProperties(L, H, W : Double; var A, V, B : Double); stdcall;
begin
A := BoxArea(L, H, W);
V := BoxVolume(L, H, W);
B := BundAreal(L, W);
end;

Procedure FletText(A1 : String; VAR C1 : String); Stdcall;
begin
A1 := A1 + ' 123456789';
C1 := A1;
end;

Function InsetText(S1 : String) : Boolean; stdcall;
BEGIN
ShowMessage('Her skrives til filen: ' + S1);
Result := True;
END;

Function ShowForm : Boolean; stdcall;
BEGIN
ShowMessage('FORMEN VISES HER ');
Result := True;
END;

BEGIN
END.

Jeg vil nu gerne referere til den ønskede form ( MyNewUnit in 'MyNewUnit.pas' {MyNewDLLform}; ) NOte 1.

men lægger jeg en refernce ind i UDLL ved NOTE 2 "brokker" kompileren sig som bare hel... og jeg kan ikke bare oprette formen "on the fly"..

At der er et eller andet jeg mangler eller gør forkert i UDDL'en er åbenbart (mangler referencen il MyNewUnit) men hvordan får jeg denne reference og hvor skal den være beliggende.


Forøvrigt har du været meget behjælpelig, jeg har ikke kunne komme så langt som jeg er nu uden din hjælp - TAK FOR DET.

Kristian





t