COM / OLE / Automation / ActiveX

Delphi makes it easy to create a multi-tiered program. More information about how Delphi and MIDAS work with COM is found at the MIDAS technical overview page.

1. How can I access a function on a Remote Server from within my client program ?

In this code example I assume that you've already declared you're function on a Remote DataModule. Make sure you've build an run the Remote Server before continuing.

The function at the Remote DataModule is called 'MyRemoteProcedure'. At the client-side you use this code the connect to the Remote Server Object:

procedure MainForm1.MyFunctionClick(Sender: TObject);
  // Connect to the remote server by setting the TRemoteServer connect property to TRUE.
  MyRemoteServer.Connected := True;

2. How to send a memo through a COM function call ?

To send a memo over a COM interface you'll have to use a so called variant. A variant is a COM-type that can hold all the COM-datatypes that exists. When you use this datatype then be aware of the fact that it's actually a big union of types. In short if you create a variant you create a big basket that consists of compartments for every single COM- compatible datatype and you end up using only one specific type, but you do use memory for all datatypes. So this is not a very efficient solution for huge chunks of data, but it will do fine for this application.

The scheme you have to use is to pack each line off a memo in a varOleStr and pack all these strings in a varArray. At the client side of your application you use code like this:

procedure MainForm1.SendMemoClick(Sender:TObject);
var i: longint;
  MyVariantArray: VarArray;
  // MyMemo is a component on TMainForm
  // Create Variant Array with the proper dimensions
  MyVariantArray := VarArrayCreate( [0,MyMemo.Lines.Count-1], varOleStr );
  for i:=0 to MyMemo.Lines.Count-1 do
   // Pack a memo line in the varArray
   MyVariantArray[i] := MyMemo.Lines[i];
  // See example 1 for an explanation on the underlying code.
  // SendMemo is a function on a Remote Server
  MyRemoteServer.Connected := True;
  MyRemoteServer.AppServer.SendMemo( MyVariantArray );

At the server side you use some similar code. The only difference is that you have to unpack the varArray and determine how much it contains at the same time. Here comes the code:

procedure RemoteServer1.SendMemo( varMemo: Variant );
var I: longint;
  if VarArrayDimCount(varMemo) <> 1 then
   raise Exception.Create('One-dimensional variant array expected');
  for I := VarArrayLowBound(varMemo, 1) to VarArrayHighBound(varMemo, 1) do
   // SeverMemo is a TMemo and resides on a server form it could also send the text to a printer or put it into a file.
   ServerMemo.Lines.Add( varMemo[i] );

Last but not at least a bit of code extracted from the Delphi helpfiles which is optimized to read an entire file into a varAray at once.

Using the VarArrayLock standard function and the VarArrayUnlock standard procedure you can gain direct access to the data in a variant array. The VarArrayLoadFile function shown below loads the contents of a file into a variant array of bytes. It uses VarArrayLock and VarArrayUnlock to read the file directly into the array.

function VarArrayLoadFile(const FileName: string): Variant;
  F: file;
  Size: Integer;
  Data: PChar;
  AssignFile(F, FileName);
  Reset(F, 1);
   Size := FileSize(F);
   Result := VarArrayCreate([0, Size - 1], varByte);
   Data := VarArrayLock(Result);
    BlockRead(F, Data^, Size);