Solved

Form in DLL is Invisible

Posted on 2003-11-25
7
339 Views
Last Modified: 2010-04-05
Hi all,

I've got a problem when creating a form from within a DLL. I want my host application to call the DLL to provide a form, and the host should then display the returned form as a child of the host applications main form.

I've had a look at the examples offered in the following question:
http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20081197.html

and am now passing through the host applications handle through to the DLL. I've got everything pretty much working (ie: no AV's), EXCEPT that if I set the parent property of the DLL-provided form to be the Main form the child form remains invisble after calling show. Not setting the parent property allows the child form to become visible, but it is no longer a child of the main form which is what I require. I suspect that there is more going on than just the child form not being visible, because scrollbars appear on the main form and they don't respond as expected.

ie:
  NewForm := MyDLL.GenerateForm(Application.Handle);
  NewForm.Parent := MainForm;   // <---- Commenting this out makes the form visible
  NewForm.Top := 10;
  NewForm.Left := 10;
  NewForm.Show;


If the child form is provided by the host application instead of a DLL, there is no problem with making the child form a child of the main form, so I figure that the problem must have something to do with using a DLL.

If anyone has got any suggestions, I'd really like to hear them,

Cheers,
Greg

PS. I'm using Delphi 7 personal ed.
0
Comment
Question by:gwhite012597
7 Comments
 
LVL 5

Accepted Solution

by:
snehanshu earned 84 total points
Comment Utility
Have you done what ITugay suggested in the link:
http://www.gnomehome.demon.nl/uddf/pages/dll.htm#dll3
i.e. dynamically loading the DLL, changing the DLL's APPlication Handle etc.?
Pls provide your DLL code here.
...Shu
0
 
LVL 5

Assisted Solution

by:Darth_helge
Darth_helge earned 83 total points
Comment Utility
this is what's inside my DLL with a form:

function ShowDllIRForm(hApp: THandle): TCustomForm; stdcall;
begin
 Application.Handle := hApp;
  if not assigned(IRForm) then
    IRForm := TIRForm.Create(Application);
  result := IRForm;
end;

and this is what that calls my dllform from the mainform:

ShowDllIRForm(MainForm.Handle).ParentWindow := MainPanel.Handle;
ShowDllIRForm(MainForm.Handle).Show;
SetForegroundWindow(ShowDllIRForm(MainForm.Handle).Handle);

and this works just fine!
0
 

Author Comment

by:gwhite012597
Comment Utility
Hi guys,

Thanks for the input... I've written a basic app to test this functionality before implementing it in my main project. Below is the code from this test app...

----------------------------------------------
 here is the DLL code:
----------------------------------------------
library formlibrary;

uses
  forms,
  ULibraryForm in 'ULibraryForm.pas' {Form1};

function CreateForm : TForm; stdcall;
begin
  result := TForm1.Create(nil);
end;

exports
  CreateForm;

begin
end.

----------------------------------------------
 here is the child form unit - there is nothing special about this form. The only property changed after creation by the IDE was the visible property to false. This is so the form doesn't become visible until after
I assign the parent property:
----------------------------------------------
unit ULibraryForm;

interface

uses
  Classes, Forms;

type
  TForm1 = class(TForm)
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  end;

implementation

{$R *.DFM}

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;


----------------------------------------------
 here is my test app's main form:
----------------------------------------------
unit UMainForm;

interface

uses
  Controls, Forms, StdCtrls, Classes;

type
  TMainForm = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  end;

  function CreateForm : TForm; stdcall; external 'FormLibrary.DLL';
var
  MainForm: TMainForm;

implementation

{$R *.DFM}

procedure TMainForm.Button1Click(Sender: TObject);
var
  NewForm : TForm;
begin
  NewForm := CreateForm;
  NewForm.Caption := 'DLL Form';
  NewForm.Parent := self;
  NewForm.Top := 60;
  NewForm.Left := 10;
  NewForm.Show;
  {At this point NewForm should now be visible as a child of the main form - unfortunately it is not}
end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  while(ControlCount > 0) do
    Controls[0].Free;
end;
end.


Cheers,
Greg

0
 

Author Comment

by:gwhite012597
Comment Utility
Hi again,

I've now come up with a solution to the problem.... calling the UpdateControlState method of the mainform makes the child form visible. I'm guessing that when the NewForms parent property is set, Delphi adds the NewForm to the list of child controls of the MainForm - and calling the UpdateControlState method forces it to refresh the child control - of course I'm only guessing. The main thing is I've now got a work around for this behaviour.

----------------------------------------------
 Calling the UpdateControlState makes the form visible
----------------------------------------------
procedure TMainForm.Button1Click(Sender: TObject);
var
  NewForm : TForm;
begin
  NewForm := CreateForm;
  NewForm.Caption := 'DLL Form';
  NewForm.Parent := self;
  NewForm.Top := 60;
  NewForm.Left := 10;
  NewForm.Show;

  UpdateControlState;
end;


Thanks again for your time,

Cheers,
Greg

0
 
LVL 22

Assisted Solution

by:mnasman
mnasman earned 83 total points
Comment Utility
Hello

  I think you need to pass the application and screen variables

and you Application.CreateForm to create the MDIForm

here's a sample

// dll libaray

library MyDll;
uses
  SysUtils,
  Classes,forms, windows,
   MyForm in 'MyForm.pas' {Form1};

{$R *.res}
var
  oApp : TApplication;
  oScr : TScreen;

procedure MyDLLProc(Reason: Integer);
begin
  if Reason = DLL_PROCESS_DETACH then
  begin
    Application := oApp;
    Screen := oScr;
  end;
end;

procedure ShowFrm(App:TApplication; Scr : TScreen); stdcall;
begin
  Application := App;
  Screen := Scr;
  App.CreateForm(TMyChildFrm, MyChildFrm);
  MyChildFrm.Show;
end;

exports
  ShowFrm;

begin
  oApp := Application;
  oScr := Screen;
  DLLProc := @MyDLLProc;
end.

==================

// test form

procedure ShowFrm(App: TApplication;Scr: TScreen); stdcall;

var
  Form2: TForm2;

implementation

procedure ShowFrm(App: TApplication;Scr: TScreen); external 'MyDll.dll' name 'ShowFrm';

{$R *.dfm}

procedure TForm2.NewForm1Click(Sender: TObject);
begin
    ShowFrm(Application, Screen);
end;

you can look for these question for more info
http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20653308.html
http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20665112.html
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now