Link to home
Start Free TrialLog in
Avatar of PeterZG
PeterZG

asked on

To all DLL experts

To all DLL experts:

I have number of applications, which are using the same copy of DataModule.
Applications grow in size (as usually they do...) and I would like to create DLL, and move the DataModule there.
More easy maintenance is also the reason.
I need some help how to do it, well I'm rather beginner with DLLs and I don't know if its possible, because of specific way that forms communicate with DataModule and back.
All edit components on all forms are created dynamically, when user selects startup parameters (like ContractCode, ModuleName...) - created from within DataModule by Form.CreateComponent(<ComponentNameTakenFromDB>).. and then all necessary properties are assigned.
DataModule constantly "communicates" with those components by Form.FindComponent(<ComponentNameTakenFromDB>)....
This communication includes writing and reading values to and from components, also changing some of their properties like Color, Enabled, Visible, etc.
None of components is connected directly to DataSets, updates are made by executing functions from DataModule. Those functions scan then through forms, get required data and update DB. The data type used is various; mostly strings, widestrings and integers, but blobs as well.
All necessary messages, which may be needed during DB updates are also generated by code within DataModule.

My questions are:
1. Is it possible and how?
2. Could it slow down the applications? (not that I want it :))


Cheers,
Avatar of Goodangel Matope
Goodangel Matope
Flag of Zambia image

I have used DLLs with validation functions and procedures, but I have never used a DLL which directly affects form controls. using a DLL that affects form controls can be rather tricky because you might make another application that does not have those controls, and if the DLL HAS to use them it will not work. Thats why I use DLLs for validation purposes and other procedures that do not affect form controls.

DLLS will not slow down the application if you load them at application startup. Even if you load them when they are needed, it will hardly slow down the applicaiton. I will post an example of my validation Dll for u to have a look at.

Start Delphi and select File --> New ... DLL. This will create a new DLL template in the editor window. Select the default text and replace it with the next piece of code:

//------------------------
library MessageDLL;

uses SysUtils, Classes, Dialogs;

procedure DisplayMessage; export;
begin
 ShowMessage('This is from my dll');
end;

exports DisplayMessage;

end.
//---------------------------

compile and build, and a DLL will be created.

Now for the main application:

Put this code in the type declerations in your main Application:


procedure DisplayMessage; external 'MessageDLL.dll'

To call the procedure  from your application just write this code in an onclick event or any other event of your choice.

DisplayMessage;

I hope this gives u an idea how to use DLLs

regards.

Gee!
Avatar of PeterZG
PeterZG

ASKER

Cheers Goodangel,

Little more explanation; all details about controls are stored in DB, not in DataModule. Controls on forms (and forms themselves) are created based on application parameters like Name, Version. Then each control has it's own Name and Version as well, so I can actually have different screens (versions) of "the same" application working on one DB.
I think that the risk of calling non-existing control is ~0 (well, DB needed to get corrupted).

I need to know about limitations of DLLs. Will I be able for example pass blob values between EXE and DLL? If not, is there any other way?

Look at this arcile, it may help you to create and be familiar with the making DLL in delphi
http://delphi.about.com/library/weekly/aa041100a.htm?terms=dll

Peter,

The main limitation with using dll's is using strings over 255 chars. If you will be using large strings then Borland recommend using the Sharemem unit, which in turn means you have to distribute borlndmm.dll. If you use this approach then you need to ensure that Sharemem is the first unit in the PROJECT uses clause of your dll and your exe. If this isn't an option then you have to resort to using PChars :-{
Dates, booleans, numbers etc.. shouldn't cause you a problem. How do you pass blob data between form and datamodule at the moment. In theory you should be able to pass a reference to a stream object to a dll.

Of course if you wanted to make life easier you could consider putting your DM in a delphi package and using that as a shared dll (which is essentially what it is). We used to store all our modules in externall dll's but are going to be using packages.

Hope some of this helps

Jo
"We used to store all our modules in externall
dll's ..."

All running over the same single TDatabase or each using its own TDatabase? i.e. do you have cross-DLL links between TQuery (or such) and TDatabase?

F.

fva -
We used DOA controls so it was a single TOracleSession that was passed to a dll when the dll was explicitly loaded.
Oh, that's another kind of fish :)
With classic TDatabase's I think it would have been a little more awkward, that's why I asked (just curious how did you get through).

F.
Avatar of PeterZG

ASKER

How do I pass info between forms and DM:
I run set of procedures and functions (which are in DM) OnFormCreate event or when certain data need to be updated.
The procedure below is cutted down version of original one.
It resides in DM and its available to each unit in the project by uses clause.


//A form calls the procedure and passes itself as Form variable.
procedure TDM.GetPickupLists(Form: TScrollingWinControl);
var
   ind: integer;
begin
     with D_SysParams do
     begin
          if Active then Close;
          Prepared := false;
          //FormParams is StrHolder (RxLib) and is used to pass information about the form to DM (like ContractCode, ApplicationCode, FormVersion...).
          Parameters.ParamByName('@ContractCode').Value := (Form.FindComponent('FormParams') as TStrHolder).MacroByName('SYS_ContractCode').Text;
          Parameters.ParamByName('@ApplCode').Value     := (Form.FindComponent('FormParams') as TStrHolder).MacroByName('SYS_AppCode').Text;
          Parameters.ParamByName('@ApplVer').Value      := (Form.FindComponent('FormParams') as TStrHolder).MacroByName('SYS_AppVer').Text;
          Parameters.ParamByName('@FormCode').Value     := (Form.FindComponent('FormParams') as TStrHolder).MacroByName('SYS_FormCode').Text;
          Parameters.ParamByName('@FormVer').Value      := (Form.FindComponent('FormParams') as TStrHolder).MacroByName('SYS_FormVer').Text;
          Prepared := true;
          Open;
          //The procedure gets info about controls that need pickup lists (using D_SysParams - ADODataSet) and SQL code (from field ValidationScript) which then is passed as CommandText to D_PickupList (ADODataset as well).
          while not EOF do
          begin
               if FieldByName('IsValidated').Value = '1'
               then begin
                         if D_PickupList.Active then D_PickupList.Close;
                         D_PickupList.Prepared := false;
                         D_PickupList.CommandText := FieldByName('ValidationScript').Value;
                         //attaching values to parameters
                         for ind:=0 to D_PickupList.Parameters.Count-1 do
                         D_PickupList.Parameters[ind].Value := (Form.FindComponent('FormParams') as TStrHolder).MacroByName(D_PickupList.Parameters[ind].Name).Text;
                         D_PickupList.Prepared := true;
                         D_PickupList.Open;
                         (Form.FindComponent(FieldByName('VCLName').Value) as TdxPickEdit).Items.Clear;
                         //D_PickupList retrieves list values (in field PickupValue) and adds them directly to a pickup control on the form
                         //this way I don't need to repeat the same code over and over on almost every form
                         while not D_PickupList.EOF do
                         begin
                              (Form.FindComponent(FieldByName('VCLName').Value) as TdxPickEdit).Items.Add(D_PickupList.FieldByName('PickupValue').Value);
                              D_PickupList.Next
                         end;
                    end;
               Next //D_SySparams
          end;
          if Active then Close;
          if D_PickupList.Active then Close
     end;
end;



Creation of controls on the forms is done in simillar way, DB updates as well (OnSave event fires procedure from within DM and scans form for controls,
which values should be saved in DB. All validation of data type, length, required or not, and few others are done then.

All data from and to controls is read and written from within DM.


This is the best explanation of the process I can give at the moment (spend about 30hrs flat in front of the notebook :~(
Hope that someone can give me a solution now, I'm going to make some coffee

cheers,
Avatar of PeterZG

ASKER

bloody formatting of the code...
Avatar of PeterZG

ASKER

bloody formatting of the code...
Avatar of PeterZG

ASKER

??
ASKER CERTIFIED SOLUTION
Avatar of nnbbb09
nnbbb09

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of PeterZG

ASKER

cheers nnbbb09,
I'll try it..

Actually you don't need to remove it from the exe. The other benefit of using a package is that you can access any method/procedure in the DM without having to write exported procedures.