Solved

Form in DLL is Invisible

Posted on 2003-11-25
7
345 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
ID: 9822598
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
ID: 9824546
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
ID: 9833480
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
ID: 9833502
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:Mohammed Nasman
Mohammed Nasman earned 83 total points
ID: 9834118
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
With the power of JIRA, there's an unlimited number of ways you can customize it, use it and benefit from it. With that in mind, there's bound to be things that I wasn't able to cover in this course. With this summary we'll look at some places to go…
As a trusted technology advisor to your customers you are likely getting the daily question of, ‘should I put this in the cloud?’ As customer demands for cloud services increases, companies will see a shift from traditional buying patterns to new…

862 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

28 Experts available now in Live!

Get 1:1 Help Now