Difference between revisions of "Form in DLL"

From Lazarus wiki
Jump to navigationJump to search
(Created page with "The following application and library demonstrate you how to show a modal form from a DLL library. Tested on win32 with Lazarus 1.7 trunk. Main application: <syntaxhighlight>...")
 
Line 1: Line 1:
The following application and library demonstrate you how to show a modal form from a DLL library. Tested on win32 with Lazarus 1.7 trunk.
+
The following application and library demonstrate you how to show a modal and a non-modal form and create a custom component on application form from a DLL library. Tested on win32 with Lazarus 1.7 trunk.
  
 
Main application:
 
Main application:
Line 6: Line 6:
  
 
uses
 
uses
   Interfaces, Classes, LCLType, StdCtrls, Forms;
+
   Interfaces, Classes, LCLType, Controls, StdCtrls, Forms, ExtCtrls;
  
 +
type
 +
  TEnableDisableFormsCallBack = procedure(var FormList: Pointer);
 +
  TCreateButtonCallBack = procedure(Caption: PChar; OnClick: TProcedure);
 +
 +
procedure DLLDialog_Init(DisableFormsCallBack, EnableFormsCallback: TEnableDisableFormsCallBack); external 'DLLDialog.dll';
 +
procedure DLLDialog_Final; external 'DLLDialog.dll';
 
procedure DLLDialog_ShowModal(ParentWindow: HWND); external 'DLLDialog.dll';
 
procedure DLLDialog_ShowModal(ParentWindow: HWND); external 'DLLDialog.dll';
 +
procedure DLLDialog_Show(ParentWindow: HWND); external 'DLLDialog.dll';
 +
procedure DLLDialog_CreateDLLButton(ParentWindow: HWND); external 'DLLDialog.dll';
 +
procedure DLLDialog_CreateButton(CreateButtonCallBack: TCreateButtonCallBack); external 'DLLDialog.dll';
  
 
type
 
type
 
   TMainForm = class(TForm)
 
   TMainForm = class(TForm)
 +
  private
 +
    PnlParent: TPanel;
 +
 +
    procedure BtnAddDLLButtonClick(Sender: TObject);
 +
    procedure BtnAddButtonClick(Sender: TObject);
 +
    procedure ShowModalDLLDialog(Sender: TObject);
 +
    procedure ShowDLLDialog(Sender: TObject);
 
   public
 
   public
 
     constructor Create(aOwner: TComponent); override;
 
     constructor Create(aOwner: TComponent); override;
    procedure OpenDLLDialog(Sender: TObject);
 
 
   end;
 
   end;
 +
 +
var
 +
  MainForm: TMainForm;
  
 
{ TMainForm }
 
{ TMainForm }
 +
 +
procedure DisableFormsCallBack(var FormList: Pointer);
 +
begin
 +
  FormList := Screen.DisableForms(nil, TList(FormList));
 +
end;
 +
 +
procedure EnableFormsCallback(var FormList: Pointer);
 +
begin
 +
  Screen.EnableForms(TList(FormList));
 +
end;
  
 
constructor TMainForm.Create(aOwner: TComponent);
 
constructor TMainForm.Create(aOwner: TComponent);
 
var
 
var
   BtnOpen: TButton;
+
   BtnShow, BtnShowModal, BtnAddDLLButton, BtnAddButton: TButton;
 
begin
 
begin
 
   inherited CreateNew(aOwner);
 
   inherited CreateNew(aOwner);
  
 
   Position := poWorkAreaCenter;
 
   Position := poWorkAreaCenter;
   Width := 400;
+
   Width := 600;
 
   Height := 200;
 
   Height := 200;
  
   BtnOpen := TButton.Create(Self);
+
   BtnShow := TButton.Create(Self);
   BtnOpen.Parent := Self;
+
   BtnShow.Parent := Self;
   BtnOpen.Caption := 'Show DLL modal form';
+
   BtnShow.Caption := 'Show form';
   BtnOpen.AutoSize := True;
+
  BtnShow.AutoSize := True;
   BtnOpen.OnClick := @OpenDLLDialog;
+
  BtnShow.OnClick := @ShowDLLDialog;
 +
 
 +
  BtnShowModal := TButton.Create(Self);
 +
  BtnShowModal.Parent := Self;
 +
  BtnShowModal.Caption := 'Show modal form';
 +
   BtnShowModal.AutoSize := True;
 +
  BtnShowModal.OnClick := @ShowModalDLLDialog;
 +
  BtnShowModal.AnchorSide[akLeft].Control := BtnShow;
 +
  BtnShowModal.AnchorSide[akLeft].Side := asrRight;
 +
  BtnShowModal.BorderSpacing.Left := 10;
 +
 
 +
  BtnAddDLLButton := TButton.Create(Self);
 +
  BtnAddDLLButton.Parent := Self;
 +
  BtnAddDLLButton.Caption := 'Create real DLL button';
 +
  BtnAddDLLButton.AutoSize := True;
 +
   BtnAddDLLButton.OnClick := @BtnAddDLLButtonClick;
 +
  BtnAddDLLButton.AnchorSide[akLeft].Control := BtnShowModal;
 +
  BtnAddDLLButton.AnchorSide[akLeft].Side := asrRight;
 +
  BtnAddDLLButton.BorderSpacing.Left := 10;
 +
 
 +
  BtnAddButton := TButton.Create(Self);
 +
  BtnAddButton.Parent := Self;
 +
  BtnAddButton.Caption := 'Create fake DLL button';
 +
  BtnAddButton.AutoSize := True;
 +
  BtnAddButton.OnClick := @BtnAddButtonClick;
 +
  BtnAddButton.AnchorSide[akLeft].Control := BtnAddDLLButton;
 +
  BtnAddButton.AnchorSide[akLeft].Side := asrRight;
 +
  BtnAddButton.BorderSpacing.Left := 10;
 +
 
 +
  PnlParent := TPanel.Create(Self);
 +
  PnlParent.Parent := Self;
 +
  PnlParent.AnchorSide[akTop].Control := BtnShow;
 +
  PnlParent.AnchorSide[akTop].Side := asrBottom;
 +
  PnlParent.BorderSpacing.Top := 10;
 +
  PnlParent.Width := 220;
 
end;
 
end;
  
procedure TMainForm.OpenDLLDialog(Sender: TObject);
+
procedure CreateButtonCallBack(ACaption: PChar; AOnClick: TProcedure);
 
var
 
var
   DisabledList: TList;
+
   Btn: TButton;
 +
  MyMethod: TMethod;
 +
begin
 +
  Btn := TButton.Create(MainForm);
 +
  Btn.Caption := ACaption;
 +
  Btn.Left := 100;
 +
  Btn.Width := 100;
 +
  Btn.Height := 20;
 +
  MyMethod.Code := AOnClick;
 +
  MyMethod.Data := nil;
 +
  Btn.OnClick := TNotifyEvent(MyMethod);
 +
  Btn.Parent := MainForm.PnlParent;
 +
end;
 +
 
 +
procedure TMainForm.BtnAddButtonClick(Sender: TObject);
 +
begin
 +
  DLLDialog_CreateButton(@CreateButtonCallBack);
 +
end;
 +
 
 +
procedure TMainForm.BtnAddDLLButtonClick(Sender: TObject);
 +
begin
 +
  DLLDialog_CreateDLLButton(PnlParent.Handle);
 +
end;
 +
 
 +
procedure TMainForm.ShowDLLDialog(Sender: TObject);
 
begin
 
begin
   DisabledList := Screen.DisableForms(nil, nil);
+
   DLLDialog_Show(0);
  try
 
    try
 
      DLLDialog_ShowModal(Self.Handle);
 
    finally
 
      Screen.EnableForms(DisabledList);
 
    end;
 
  finally
 
    DisabledList.Free;
 
  end;
 
 
end;
 
end;
  
var
+
procedure TMainForm.ShowModalDLLDialog(Sender: TObject);
   MainForm: TMainForm;
+
begin
 +
   DLLDialog_ShowModal(Self.Handle);
 +
end;
  
 
{$R *.res}
 
{$R *.res}
Line 60: Line 139:
 
   Application.Initialize;
 
   Application.Initialize;
 
   Application.CreateForm(TMainForm, MainForm);
 
   Application.CreateForm(TMainForm, MainForm);
   Application.Run;
+
   DLLDialog_Init(@DisableFormsCallBack, @EnableFormsCallback);
 +
  try
 +
    Application.Run;
 +
  finally
 +
    DLLDialog_Final;
 +
  end;
 
end.
 
end.
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 71: Line 155:
  
 
uses
 
uses
   Interfaces, Classes, LCLType, StdCtrls, Forms, Dialogs;
+
   Interfaces, Classes, LCLType, StdCtrls, Controls, Forms, Dialogs;
  
 
type
 
type
Line 83: Line 167:
 
     ParentFormHandle: HWND;
 
     ParentFormHandle: HWND;
 
   end;
 
   end;
 +
 +
  TEnableDisableFormsCallBack = procedure(var FormList: Pointer);
 +
  TCreateButtonCallBack = procedure(Caption: PChar; OnClick: TProcedure);
 +
 +
  TApplicationCallback = class(TComponent)
 +
  private
 +
    DisableFormsCallBack: TEnableDisableFormsCallBack;
 +
    EnableFormsCallback: TEnableDisableFormsCallBack;
 +
    FormList: Pointer;
 +
  public
 +
    procedure DisableForms(Sender: TObject);
 +
    procedure EnableForms(Sender: TObject);
 +
    procedure BtnClick(Sender: TObject);
 +
 +
    constructor Create(aOwner: TComponent); override;
 +
    destructor Destroy; override;
 +
  end;
 +
 +
var
 +
  ApplicationCallback: TApplicationCallback;
 +
 +
procedure DLLDialog_Init(DisableFormsCallBack, EnableFormsCallback: TEnableDisableFormsCallBack);
 +
begin
 +
  ApplicationCallback := TApplicationCallback.Create(nil);
 +
  ApplicationCallback.DisableFormsCallBack := DisableFormsCallBack;
 +
  ApplicationCallback.EnableFormsCallback := EnableFormsCallback;
 +
end;
 +
 +
procedure DLLDialog_Final;
 +
begin
 +
  ApplicationCallback.Free;
 +
end;
  
 
procedure DLLDialog_ShowModal(ParentWindow: HWND);
 
procedure DLLDialog_ShowModal(ParentWindow: HWND);
Line 88: Line 204:
 
   DLLDialog: TDLLDialog;
 
   DLLDialog: TDLLDialog;
 
begin
 
begin
   DLLDialog := TDLLDialog.Create(nil);
+
   DLLDialog := TDLLDialog.Create(ApplicationCallback);
 
   try
 
   try
 
     DLLDialog.ParentFormHandle := ParentWindow;
 
     DLLDialog.ParentFormHandle := ParentWindow;
Line 95: Line 211:
 
     DLLDialog.Free;
 
     DLLDialog.Free;
 
   end;
 
   end;
 +
end;
 +
 +
procedure DLLDialog_Show(ParentWindow: HWND);
 +
var
 +
  DLLDialog: TDLLDialog;
 +
begin
 +
  DLLDialog := TDLLDialog.Create(ApplicationCallback);
 +
  DLLDialog.ParentFormHandle := ParentWindow;
 +
  DLLDialog.Show;
 +
end;
 +
 +
procedure DLLDialog_CreateDLLButton(ParentWindow: HWND);
 +
var
 +
  Btn: TButton;
 +
  BtnParentForm: TForm;
 +
begin
 +
  BtnParentForm := TForm.CreateNew(ApplicationCallback);
 +
  BtnParentForm.ParentWindow := ParentWindow;
 +
  BtnParentForm.Width := 100;
 +
  BtnParentForm.Height := 20;
 +
  BtnParentForm.BorderStyle := bsNone;
 +
  BtnParentForm.Visible := True;
 +
 +
  Btn := TButton.Create(ApplicationCallback);
 +
  Btn.Caption := 'Real DLL Button';
 +
  Btn.Width := BtnParentForm.Width;
 +
  Btn.Height := BtnParentForm.Height;
 +
  Btn.OnClick := @ApplicationCallback.BtnClick;
 +
  Btn.Parent := BtnParentForm;
 +
end;
 +
 +
procedure FakeBtnClick;
 +
begin
 +
  ShowMessage('You clicked a fake button from a DLL!');
 +
end;
 +
 +
procedure DLLDialog_CreateButton(CreateButtonCallBack: TCreateButtonCallBack);
 +
begin
 +
  CreateButtonCallBack('Fake DLL Button', @FakeBtnClick);
 
end;
 
end;
  
 
exports
 
exports
   DLLDialog_ShowModal;
+
   DLLDialog_Init, DLLDialog_Final, DLLDialog_ShowModal, DLLDialog_Show,
 +
  DLLDialog_CreateButton, DLLDialog_CreateDLLButton;
 +
 
 +
{ TApplicationCallback }
 +
 
 +
constructor TApplicationCallback.Create(aOwner: TComponent);
 +
begin
 +
  inherited Create(aOwner);
 +
 
 +
  Application.AddOnModalBeginHandler(@DisableForms);
 +
  Application.AddOnModalEndHandler(@EnableForms);
 +
end;
 +
 
 +
procedure TApplicationCallback.BtnClick(Sender: TObject);
 +
begin
 +
  ShowMessage('You clicked a real button from a DLL!');
 +
end;
 +
 
 +
destructor TApplicationCallback.Destroy;
 +
begin
 +
  Application.RemoveOnModalBeginHandler(@DisableForms);
 +
  Application.RemoveOnModalEndHandler(@EnableForms);
 +
 
 +
  inherited Destroy;
 +
end;
 +
 
 +
procedure TApplicationCallback.DisableForms(Sender: TObject);
 +
begin
 +
  DisableFormsCallBack(FormList);
 +
end;
 +
 
 +
procedure TApplicationCallback.EnableForms(Sender: TObject);
 +
begin
 +
  EnableFormsCallback(FormList);
 +
end;
  
 
{ TDLLDialog }
 
{ TDLLDialog }

Revision as of 23:52, 10 May 2016

The following application and library demonstrate you how to show a modal and a non-modal form and create a custom component on application form from a DLL library. Tested on win32 with Lazarus 1.7 trunk.

Main application:

program MainApp;

uses
  Interfaces, Classes, LCLType, Controls, StdCtrls, Forms, ExtCtrls;

type
  TEnableDisableFormsCallBack = procedure(var FormList: Pointer);
  TCreateButtonCallBack = procedure(Caption: PChar; OnClick: TProcedure);

procedure DLLDialog_Init(DisableFormsCallBack, EnableFormsCallback: TEnableDisableFormsCallBack); external 'DLLDialog.dll';
procedure DLLDialog_Final; external 'DLLDialog.dll';
procedure DLLDialog_ShowModal(ParentWindow: HWND); external 'DLLDialog.dll';
procedure DLLDialog_Show(ParentWindow: HWND); external 'DLLDialog.dll';
procedure DLLDialog_CreateDLLButton(ParentWindow: HWND); external 'DLLDialog.dll';
procedure DLLDialog_CreateButton(CreateButtonCallBack: TCreateButtonCallBack); external 'DLLDialog.dll';

type
  TMainForm = class(TForm)
  private
    PnlParent: TPanel;

    procedure BtnAddDLLButtonClick(Sender: TObject);
    procedure BtnAddButtonClick(Sender: TObject);
    procedure ShowModalDLLDialog(Sender: TObject);
    procedure ShowDLLDialog(Sender: TObject);
  public
    constructor Create(aOwner: TComponent); override;
  end;

var
  MainForm: TMainForm;

{ TMainForm }

procedure DisableFormsCallBack(var FormList: Pointer);
begin
  FormList := Screen.DisableForms(nil, TList(FormList));
end;

procedure EnableFormsCallback(var FormList: Pointer);
begin
  Screen.EnableForms(TList(FormList));
end;

constructor TMainForm.Create(aOwner: TComponent);
var
  BtnShow, BtnShowModal, BtnAddDLLButton, BtnAddButton: TButton;
begin
  inherited CreateNew(aOwner);

  Position := poWorkAreaCenter;
  Width := 600;
  Height := 200;

  BtnShow := TButton.Create(Self);
  BtnShow.Parent := Self;
  BtnShow.Caption := 'Show form';
  BtnShow.AutoSize := True;
  BtnShow.OnClick := @ShowDLLDialog;

  BtnShowModal := TButton.Create(Self);
  BtnShowModal.Parent := Self;
  BtnShowModal.Caption := 'Show modal form';
  BtnShowModal.AutoSize := True;
  BtnShowModal.OnClick := @ShowModalDLLDialog;
  BtnShowModal.AnchorSide[akLeft].Control := BtnShow;
  BtnShowModal.AnchorSide[akLeft].Side := asrRight;
  BtnShowModal.BorderSpacing.Left := 10;

  BtnAddDLLButton := TButton.Create(Self);
  BtnAddDLLButton.Parent := Self;
  BtnAddDLLButton.Caption := 'Create real DLL button';
  BtnAddDLLButton.AutoSize := True;
  BtnAddDLLButton.OnClick := @BtnAddDLLButtonClick;
  BtnAddDLLButton.AnchorSide[akLeft].Control := BtnShowModal;
  BtnAddDLLButton.AnchorSide[akLeft].Side := asrRight;
  BtnAddDLLButton.BorderSpacing.Left := 10;

  BtnAddButton := TButton.Create(Self);
  BtnAddButton.Parent := Self;
  BtnAddButton.Caption := 'Create fake DLL button';
  BtnAddButton.AutoSize := True;
  BtnAddButton.OnClick := @BtnAddButtonClick;
  BtnAddButton.AnchorSide[akLeft].Control := BtnAddDLLButton;
  BtnAddButton.AnchorSide[akLeft].Side := asrRight;
  BtnAddButton.BorderSpacing.Left := 10;

  PnlParent := TPanel.Create(Self);
  PnlParent.Parent := Self;
  PnlParent.AnchorSide[akTop].Control := BtnShow;
  PnlParent.AnchorSide[akTop].Side := asrBottom;
  PnlParent.BorderSpacing.Top := 10;
  PnlParent.Width := 220;
end;

procedure CreateButtonCallBack(ACaption: PChar; AOnClick: TProcedure);
var
  Btn: TButton;
  MyMethod: TMethod;
begin
  Btn := TButton.Create(MainForm);
  Btn.Caption := ACaption;
  Btn.Left := 100;
  Btn.Width := 100;
  Btn.Height := 20;
  MyMethod.Code := AOnClick;
  MyMethod.Data := nil;
  Btn.OnClick := TNotifyEvent(MyMethod);
  Btn.Parent := MainForm.PnlParent;
end;

procedure TMainForm.BtnAddButtonClick(Sender: TObject);
begin
  DLLDialog_CreateButton(@CreateButtonCallBack);
end;

procedure TMainForm.BtnAddDLLButtonClick(Sender: TObject);
begin
  DLLDialog_CreateDLLButton(PnlParent.Handle);
end;

procedure TMainForm.ShowDLLDialog(Sender: TObject);
begin
  DLLDialog_Show(0);
end;

procedure TMainForm.ShowModalDLLDialog(Sender: TObject);
begin
  DLLDialog_ShowModal(Self.Handle);
end;

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TMainForm, MainForm);
  DLLDialog_Init(@DisableFormsCallBack, @EnableFormsCallback);
  try
    Application.Run;
  finally
    DLLDialog_Final;
  end;
end.

DLL with a form:

library DllDialog;

{$mode objfpc}{$H+}

uses
  Interfaces, Classes, LCLType, StdCtrls, Controls, Forms, Dialogs;

type
  TDLLDialog = class(TForm)
  protected
    procedure CreateParams(var Params: TCreateParams); override;
  public
    procedure BtnShowMessageClick(Sender: TObject);
    constructor Create(aOwner: TComponent); override;
  public
    ParentFormHandle: HWND;
  end;

  TEnableDisableFormsCallBack = procedure(var FormList: Pointer);
  TCreateButtonCallBack = procedure(Caption: PChar; OnClick: TProcedure);

  TApplicationCallback = class(TComponent)
  private
    DisableFormsCallBack: TEnableDisableFormsCallBack;
    EnableFormsCallback: TEnableDisableFormsCallBack;
    FormList: Pointer;
  public
    procedure DisableForms(Sender: TObject);
    procedure EnableForms(Sender: TObject);
    procedure BtnClick(Sender: TObject);

    constructor Create(aOwner: TComponent); override;
    destructor Destroy; override;
  end;

var
  ApplicationCallback: TApplicationCallback;

procedure DLLDialog_Init(DisableFormsCallBack, EnableFormsCallback: TEnableDisableFormsCallBack);
begin
  ApplicationCallback := TApplicationCallback.Create(nil);
  ApplicationCallback.DisableFormsCallBack := DisableFormsCallBack;
  ApplicationCallback.EnableFormsCallback := EnableFormsCallback;
end;

procedure DLLDialog_Final;
begin
  ApplicationCallback.Free;
end;

procedure DLLDialog_ShowModal(ParentWindow: HWND);
var
  DLLDialog: TDLLDialog;
begin
  DLLDialog := TDLLDialog.Create(ApplicationCallback);
  try
    DLLDialog.ParentFormHandle := ParentWindow;
    DLLDialog.ShowModal;
  finally
    DLLDialog.Free;
  end;
end;

procedure DLLDialog_Show(ParentWindow: HWND);
var
  DLLDialog: TDLLDialog;
begin
  DLLDialog := TDLLDialog.Create(ApplicationCallback);
  DLLDialog.ParentFormHandle := ParentWindow;
  DLLDialog.Show;
end;

procedure DLLDialog_CreateDLLButton(ParentWindow: HWND);
var
  Btn: TButton;
  BtnParentForm: TForm;
begin
  BtnParentForm := TForm.CreateNew(ApplicationCallback);
  BtnParentForm.ParentWindow := ParentWindow;
  BtnParentForm.Width := 100;
  BtnParentForm.Height := 20;
  BtnParentForm.BorderStyle := bsNone;
  BtnParentForm.Visible := True;

  Btn := TButton.Create(ApplicationCallback);
  Btn.Caption := 'Real DLL Button';
  Btn.Width := BtnParentForm.Width;
  Btn.Height := BtnParentForm.Height;
  Btn.OnClick := @ApplicationCallback.BtnClick;
  Btn.Parent := BtnParentForm;
end;

procedure FakeBtnClick;
begin
  ShowMessage('You clicked a fake button from a DLL!');
end;

procedure DLLDialog_CreateButton(CreateButtonCallBack: TCreateButtonCallBack);
begin
  CreateButtonCallBack('Fake DLL Button', @FakeBtnClick);
end;

exports
  DLLDialog_Init, DLLDialog_Final, DLLDialog_ShowModal, DLLDialog_Show,
  DLLDialog_CreateButton, DLLDialog_CreateDLLButton;

{ TApplicationCallback }

constructor TApplicationCallback.Create(aOwner: TComponent);
begin
  inherited Create(aOwner);

  Application.AddOnModalBeginHandler(@DisableForms);
  Application.AddOnModalEndHandler(@EnableForms);
end;

procedure TApplicationCallback.BtnClick(Sender: TObject);
begin
  ShowMessage('You clicked a real button from a DLL!');
end;

destructor TApplicationCallback.Destroy;
begin
  Application.RemoveOnModalBeginHandler(@DisableForms);
  Application.RemoveOnModalEndHandler(@EnableForms);

  inherited Destroy;
end;

procedure TApplicationCallback.DisableForms(Sender: TObject);
begin
  DisableFormsCallBack(FormList);
end;

procedure TApplicationCallback.EnableForms(Sender: TObject);
begin
  EnableFormsCallback(FormList);
end;

{ TDLLDialog }

constructor TDLLDialog.Create(aOwner: TComponent);
var
  BtnShowMessage: TButton;
begin
  inherited CreateNew(aOwner);

  Caption := 'This form is in a DLL !!!';
  Position := poWorkAreaCenter;
  Width := 200;
  Height := 100;

  BtnShowMessage := TButton.Create(Self);
  BtnShowMessage.Parent := Self;
  BtnShowMessage.Caption := 'Show message';
  BtnShowMessage.AutoSize := True;
  BtnShowMessage.OnClick := @BtnShowMessageClick;
end;

procedure TDLLDialog.BtnShowMessageClick(Sender: TObject);
begin
  ShowMessage('Hello from DLL!');
end;

procedure TDLLDialog.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);

  Params.WndParent := ParentFormHandle;
end;

begin
  Application.Initialize;
end.