I have done this successfully - with many forms.

I'm a little busy right now to explain how all this works, but if you 
ask questions I'll try to answer them.

Doug
P.S. I don't think that this particular DLL uses the form, but others do.


Here is a typical DLL:   (below is how to load)

----------s74244.dpr-------------------------------------------------------------
library s74244;
uses
  ShareMem,
  SysUtils,
  Classes,
  Windows,
  Messages,
  Graphics,
  Controls,
  Forms,
  Dialogs,
  U74244 in 'U74244.pas' {Generic},
  Model in 'Model.pas';
{$E .mdl}
function GetSimClass : CSimModel; export; stdcall;
  begin
  result := TMC74245;
  end;
exports
   GetSimClass;
begin
end.
---------------U74244.pas------------------------------------------------------------
unit U74244;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Model;
const
  PartName = '74244';
  AttribList = 'Name';
  PinCount = 20;
  BoxWidth = 60;
  PinList = 
'#1OE,1D0,2O0,1D1,2O1,1D2,2O2,1D3,2O3,GND,2D3,1O3,2D2,1O2,2D1,1O1,2D0,1O0,#2OE,VCC';
  PinNums : Array[0..PinCount-1] of Integer = 
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20);
  PinPos : Array[0..PinCount-1] of Record Pos : Integer; OnLeft : 
Boolean; end =
     ((Pos:0;OnLeft:True)
     ,(Pos:1;OnLeft:True)
     ,(Pos:2;OnLeft:True)
     ,(Pos:3;OnLeft:True)
     ,(Pos:4;OnLeft:True)
     ,(Pos:5;OnLeft:True)
     ,(Pos:6;OnLeft:True)
     ,(Pos:7;OnLeft:True)
     ,(Pos:8;OnLeft:True)
     ,(Pos:9;OnLeft:True)

     ,(Pos:9;OnLeft:False)
     ,(Pos:8;OnLeft:False)
     ,(Pos:7;OnLeft:False)
     ,(Pos:6;OnLeft:False)
     ,(Pos:5;OnLeft:False)
     ,(Pos:4;OnLeft:False)
     ,(Pos:3;OnLeft:False)
     ,(Pos:2;OnLeft:False)
     ,(Pos:1;OnLeft:False)
     ,(Pos:0;OnLeft:False)
     );
const
  AV : Array[False..True] of Array[False..True] of Byte = ((0,6), (3,3));
type
  TMC74245 = class(TsimModel)
    procedure FormShortCut(var Msg: TWMKey; var Handled: Boolean);
  private
    _InstanceName : String;
    I1, I2, O1, O2 : Array[0..3] of Boolean;
    NE1, NE2 : Boolean;
    PinNames : TStringList;
  public
    function Run(TimeStep : Word; AccumulatedTime : LongWord) : Boolean; 
override;
    function GetInstance : String; override;
    function GetPin(Ndx : Integer) : Byte ; override;
    function GetPinCount : Integer; override;
    function GetPinName(Ndx : Integer) : String;override;
    function GetPinNumber(Name : String) : Integer; override;
    procedure PutInstance(Name : String); override;
    procedure PutPin(Ndx : Integer; Value : Byte); override;
    Property InstanceName : String read GetInstance write PutInstance;
    class function GetStatus : String; Override;
    class function GetAttributeNames : String; Override;
    class function GetLibraryName : String; Override;
    Property PinCount : Integer read GetPinCount;
    Property PinName[Ndx : Integer] : String read GetPinName;
    Property PinNumber[Name : STring] : Integer read GetPinNumber;
    Property Pin[Ndx : Integer] : Byte read GetPin write PutPin;
    function GetPinLoc(Ndx : Integer) : TPoint; Override;
    function GetShapeSize : TPoint; Override;
    Property PinLoc[Ndx : Integer] : TPoint read GetPinLoc;
    Property ShapeSize : TPoint read GetShapeSize;
    function GetDevicePinNumber(Ndx : Integer) : Integer; override;
    Property DevicePinNumber[Ndx : Integer] : Integer read 
GetDevicePinNumber;
  end;
implementation
{$R *.DFM}
var
  PinNames : TStringList;
function TMC74245.GetDevicePinNumber(Ndx : Integer) : Integer;
  begin
  if (Ndx < 0) or (Ndx > PinCount-1) then
    result := -1
  else
    result := PinNums[Ndx];
  end;
function TMC74245.GetPinLoc(Ndx : Integer) : TPoint;
  begin
  if (Ndx < 0) or (Ndx > PinCount-1) then
    result := MakePoint(0, 0)
  else
    result := CalcPin(PinPos[Ndx].Pos, BoxWidth, PinPos[Ndx].OnLeft);
  end;
function TMC74245.GetShapeSize : TPoint;
  var
    i, L, R : Integer;
  begin
  L := 0;
  R := 0;
  for i := 0 to PinCount-1 do
    begin
    if PinPos[i].OnLeft then
      begin
      if PinPos[i].Pos+1 > L then L := PinPos[i].Pos+1;
      end
    else
      begin
      if PinPos[i].Pos+1 > R then R := PinPos[i].Pos+1;
      end;
    end;
  result := CalcBox(L, R, BoxWidth);
  end;
function TMC74245.GetInstance : String;
  begin
  result := _InstanceName;
  end;
function TMC74245.GetPinCount : Integer;
  begin
  result := PinNames.Count;
  end;
function TMC74245.GetPinName(Ndx : Integer) : String;
  begin
  if Ndx < 0 then result := ''
  else if Ndx < PinNames.Count then result := PinNames[Ndx]
  else result := '';
  end;
function TMC74245.GetPinNumber(Name : String) : Integer;
  begin
  result := PinNames.IndexOf(Name);
  end;
class function TMC74245.GetStatus : String;
  begin
  result := 'Functional';
  end;
class function TMC74245.GetAttributeNames : String;
  begin
  result := AttribList;
  end;
class function TMC74245.GetLibraryName : String;
  begin
  result := PartName;
  end;
//  0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  
17  18   19
//#1OE,1D0,2O0,1D1,2O1,1D2,2O2,1D3,2O3,GND,2D3,1O3,2D2,1O2,2D1,1O1,2D0,1O0,#2OE,VCC
function TMC74245.Run(TimeStep : Word; AccumulatedTime : LongWord) : 
Boolean;
  var
    i : Integer;
  begin
  for i := 0 to 3 do
    begin
    O1[i] := I1[i];
    O2[i] := I2[i];
    end;
  result := False;
  end;
function TMC74245.GetPin(Ndx : Integer) : Byte ;
  begin
  case Ndx of
    2: result := AV[NE2, O2[0]];
    4: result := AV[NE2, O2[1]];
    6: result := AV[NE2, O2[2]];
    8: result := AV[NE2, O2[3]];
    17: result := AV[NE1, O1[0]];
    15: result := AV[NE1, O1[1]];
    13: result := AV[NE1, O1[2]];
    11: result := AV[NE1, O1[3]];
    0, 1, 3, 5, 7, 9, 10, 12, 14, 16, 18, 19: result := 3;
    else result := 7;
    end;
  end;
procedure TMC74245.PutPin(Ndx : Integer; Value : Byte);
  begin
  case Ndx of
    0: NE1 := Value > 3;
    1: I1[0] := Value > 3;
    3: I1[1] := Value > 3;
    5: I1[2] := Value > 3;
    6: I1[3] := Value > 3;
    10: I2[3] := Value > 3;
    12: I2[2] := Value > 3;
    14: I2[1] := Value > 3;
    16: I2[0] := Value > 3;
    18: NE2 := Value > 3;
    else;
    end;
  end;
procedure TMC74245.FormShortCut(var Msg: TWMKey; var Handled: Boolean);
  begin
  case Msg.CharCode of
    112: // F1
      begin
      end;
    113: // F2
      begin
      Handled := True;
      end;
    114: // F3
      begin
      Handled := True;
      end;
    115: // F4
      begin
      Handled := True;
      end;
    116: // F5
      begin
      Handled := True;
      end;
    117: // F6
      begin
      Handled := True;
      end;
    118: // F7 handled by MainForm
      begin
      Handled := False;
      end;
    119: // F8 handled by MainForm
      begin
      Handled := False;
      end;
    120: // F9 handled by MainForm
      begin
      Handled := False;
      end;
    121: // F10
      begin
      Handled := True;
      end;
    122: // F11
      begin
      Handled := True;
      end;
    123: // F12
      begin
      TForm(Owner).SHow;
      Handled := True;
      end;
    27: // ESC
      begin
      Close;
      Handled := True;
      end;
    else
      begin
//    MessageDlg(IntToStr(Msg.CharCode)+' '+IntToStr(Msg.KeyData), 
mtInformation, [mbOK], 0);
      Handled := False;
      end;
    end;
  end;
procedure TMC74245.PutInstance(Name : String);
  var
    P : Integer;
    i : Integer;
    L : TStringList;
  begin
  if _InstanceName <> '' then Exit;
  L := TStringList.Create;
  _InstanceName := Name;
  L.CommaText := Name;
  P := Pos(' -', Caption);
  if P <> 0 then Caption := Copy(Caption, 1, P-1);
  L.CommaText := Name;
  for i := 0 to L.Count-1 do
    begin
    case i of
      0:
    begin
    Caption := Caption+' - '+L[i];
    end;
      else;
      end;
    end;
  PinNames := TStringList.Create;
  PinNames.CommaText := PinList;
  Visible := False;
  L.Free;
  end;
var
  PosPin : Integer;
procedure B(N : String; OnLeft : Boolean);
  var
    i : Integer;
  begin
  i := PinNames.IndexOf(N);
  PinPos[i].Pos := PosPin;
  PinPos[i].OnLeft := OnLeft;
  end;
procedure A(L, R : String);
  begin
  if L <> '' then B(L, True);
  if R <> '' then B(R, False);
  Inc(PosPin);
  end;
begin
PosPin := 0;
PinNames := TStringList.Create;
PinNames.CommaText := PinList;
A('', 'VCC');
A('', '');
A('1D3', '1O3');
A('1D2', '1O2');
A('1D1', '1O1');
A('1D0', '1O0');
A('#1OE', '');
A('', '');
A('2D3', '2O3');
A('2D2', '2O2');
A('2D1', '2O1');
A('2D0', '2O0');
A('#2OE', '');
A('', 'GND');
end.


---------------------model.pas------------------------------------------------------------------
unit Model;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
  TRunSimCmnd = (rscStart, rscStop, rscStep, rscSlowStart, rscSlowStop, 
rscShow, rscHide);
  TRunSim = Procedure(Cmnd : TRunSimCmnd) of object;
  TSimModel = class(TForm)
  private
  public
    RunSim : TRunSim;
    class function GetStatus : String; virtual; abstract;
    class function GetLibraryName : String; virtual; abstract;
    class function GetAttributeNames : String; virtual; abstract;
    function GetInstance : String; virtual; abstract;
    function GetPin(Ndx : Integer) : Byte ; virtual; abstract;
    function GetPinCount : Integer; virtual; abstract;
    function GetPinName(Ndx : Integer) : String;virtual; abstract;
    function GetPinNumber(Name : String) : Integer; virtual; abstract;
    function Run(TimeStep : Word; AccumulatedTime : LongWord) : Boolean; 
virtual; abstract;
    procedure PutInstance(Name : String); virtual; abstract;
    procedure PutPin(Ndx : Integer; Value : Byte); virtual; abstract;
    Property InstanceName : String read GetInstance write PutInstance;
    Property Pin[Ndx : Integer] : Byte read GetPin write PutPin;
    Property PinCount : Integer read GetPinCount;
    Property PinName[Ndx : Integer] : String read GetPinName;
    Property PinNumber[Name : String] : Integer read GetPinNumber;
    function GetPinLoc(Ndx : Integer) : TPoint; virtual; abstract;
    function GetShapeSize : TPoint; virtual; abstract;
    Property PinLoc[Ndx : Integer] : TPoint read GetPinLoc;
    Property ShapeSize : TPoint read GetShapeSize;
    function GetDevicePinNumber(Ndx : Integer) : Integer; virtual; abstract;
    Property DevicePinNumber[Ndx : Integer] : Integer read 
GetDevicePinNumber;
  end;
  CSimModel = Class of TSimModel;
  function CalcPin(Pin, Width : Integer; IsLeft : Boolean) : TPoint;
  function CalcBox(Left, Right, Width : Integer) : Tpoint;
  function MakePoint(X, Y : Integer) : Tpoint;
implementation
uses Math;
function MakePoint(X, Y : Integer) : Tpoint;
  var
    P : TPoint;
  begin
  P.x := X;
  P.y := Y;
  result := P;
  end;
function CalcPin(Pin, Width : Integer; IsLeft : Boolean) : Tpoint;
  var
    P : TPoint;
  begin
  if IsLeft then
    P.x := 0
  else
    P.x := Width-1;
  P.y := (Pin + 2) * 10;
  result := P;
  end;
function CalcBox(Left, Right, Width : Integer) : Tpoint;
  var
    P : TPoint;
  begin
  P.x := Width;
  P.y := (Max(Left, Right) + 3) * 10;
  result := P;
  end;
end.



This is how I load the DLL

------- extracted method from main 
.exe--------------------------------------------------------
function TBOX.AddLIB(Fn: TFileName): Integer;
  var
     Name, Status : String;
     DllHandle: THandle;
     Model : CSimModel;
     GetSimClass : TGetSimClass;
  begin
  result := -1;
  DllHandle := LoadLibrary(PChar(Fn));
  GetSimClass := GetProcAddress(DllHandle, 'GetSimClass');
  if GetSimClass <> nil then
    begin
    try
      Model := GetSimClass();
      Name := Model.GetLibraryName;
      Status := Model.GetStatus;
      result := LIB.Items.Add(Name);
      LIBmodel[result] := Model;
      LIB.Update;
      DrawForm.AddModel(Name, Longint(Model));
    except
      end;
    end;
  end;


























Paul Bennett wrote:
> Hi all,
>
> A little bit of background first...
>
> I have a small application which basically consists of a MDI form 
> which acts as host to a series of plugin forms. The application is 
> relatively immature and subject to change. 
>
> The application is only used at one site and all users have access to 
> a shared directory on the network where the most up to date versions 
> of the plugins are kept, this means it is relatively easy to check 
> that the application always has the latest versions of the plugins.
>
> Recently I have suffered from a bit of 'project creep', and I was 
> looking at a way of applying the same system of updating the 
> applications main form.
>
> The Problem...
>
> I decided to move all of the MDI Form (ie pretty much the whole 
> application) into a dll, create a Loader program which checks the 
> (local) dll version number against the (network) dll and downloads it 
> as necessary and then loads the dll and opens the form.
>
> This all seems to work fine, except... when the MDI form is closed 
> the application crashes with an unknown exception. 
>
> I've checked the MDI Form and as far as I can tell every object that 
> is created as the form loads is freed and it unloads.
>
> The following is the Code for the Library Project.
>
> library FEBAPI;
>
> uses
>   ShareMem,
>   madExcept,
>   madLinkDisAsm,
>   Forms,
>   Dialogs,
>   MainUI in 'Source\MainUI.pas' {FrameworkUI};
>
> {$R *.res}
>
> procedure RunFEB; stdcall;
> var
>   FrameworkUI: TFrameworkUI;
> begin
>   FrameworkUI := TFrameworkUI.Create(nil);
>   FrameworkUI.ShowModal;
>   FrameworkUI.Release;
> end;
>
>   exports RunFEB;
>
> begin
> end.
>
> When stepping through the RunFEB method, after FrameworkUI.Release is 
> called, there are repeated calls to stdWinProc (around 5 at last 
> count) until the Application crashes with an unknown exception.
>
> Any pointers most gratefully received.
>
> Paul Bennett
>
>
>
> ------------------------------------
>
> -----------------------------------------------------
> Home page: http://groups.yahoo.com/group/delphi-en/
> To unsubscribe: [email protected]! Groups Links
>
>
>
>   
> ------------------------------------------------------------------------
>
>
> No virus found in this incoming message.
> Checked by AVG - www.avg.com 
> Version: 8.5.339 / Virus Database: 270.12.80/2187 - Release Date: 06/19/09 
> 06:53:00
>
>   



[Non-text portions of this message have been removed]

Reply via email to