?
Solved

Form in DLL is Invisible

Posted on 2003-11-25
7
Medium Priority
?
372 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
7 Comments
 
LVL 5

Accepted Solution

by:
snehanshu earned 336 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 332 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 332 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

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

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…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
If you’ve ever visited a web page and noticed a cool font that you really liked the look of, but couldn’t figure out which font it was so that you could use it for your own work, then this video is for you! In this Micro Tutorial, you'll learn yo…
In this video, Percona Solution Engineer Dimitri Vanoverbeke discusses why you want to use at least three nodes in a database cluster. To discuss how Percona Consulting can help with your design and architecture needs for your database and infras…
Suggested Courses
Course of the Month14 days, 19 hours left to enroll

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