Board index » delphi » Put a form inside another form - no MDI approach

Put a form inside another form - no MDI approach

Hi ppl. I'm trying to which seems impossible... Let me tell the history
behind it. Please be patient.

  I'm working on a big project. We want to modularize our code, breaking up
the main system in many medium sized DLL's. We have many reasons to do it,
some technical, some commercial.
  We know the that our approach involves some tradeoffs. In particular, the
DLL will contain duplicates of the VCL which will make our system a bit :-)
larger.
  Our problem: put some forms in a DLL. We can do it right now, but the result
are some floating forms that we found to be confusing for our customers. We
want to have only one window visible. This seems to lead to an MDI interface.
However, we felt that the MDI interface can be confusing too. Even Microsoft
acknowledges it and is dropping MDI support.
  We did some research over the Delphi docs, Windows docs, Internet newsgroups
and Delphi WWW pages. We found that some people before us had the same problem.
The reasons are similar. However, most people chose to follow the MDI approach.
Even if wanted to do it, we can't put an MDI child on a DLL for technical
reasons - you cant do it in Delphi without rewriting some of the VCL code.
  However, we can't be defeated that easy. We found that we could open another
form inside the main form. Turn off the border and the main title, and to the
user it seems like a single form. OLE2 inplace editing works this way.
  We decided to try to use OLE. It seems simple: write an OLE automation server.
Activate it inside an OLE container, and here is you form inside another form.
But we need to implement a lot of interfaces to do it, and the resulting code
is big and slow.
  Then we decided to hack it anyway. We put a simple form with many components
inside another form, using a simple hack. Look at the pseudo code below:

  { MainForm has a panel component called Panel1 }

  procedure MainForm.CreateFormInsidePanel;
  var Form1 : TForm;
  begin
    Form1 := TOurForm.Create(MainForm);
    Form1.Parent := Self.Panel1;
  end;

  This way Form1 becomes clipped inside the Panel1 component. The resulting
window has a strange behavior. Everything seems to be fine, but some
components - notably the edit control - cant be selected with the mouse. This
seems to be related to some problem with the message handler of MainForm.

  The test seemed promising, but the lack of documentation makes things harder.
We are looking now for alternatives. We have some to enumerate:

  - Implement the external forms in DLL's, and open them inside the Panel.
    Look at the code of the message dispatcher and hack it until it works.
  - Implement the external forms in components, convert these components
    in OCX. Use the resulting OCX inside an OLE container. To do it we need
    some info about writing an OCX.
  - Create the components at runtime inside the panel, Use the definition of
    the form that is stored in the DLL. It's simply a matter of loading the
    right resources. The tricky part is to associate the event handlers
    inside the DLL with the new components create inside the main form.

  We are inviting any Delphi programmer to join us to solve this problem. We
think this can be a big step toward the deliverance of modular Delphi apps,
much like you can do today with Power Builder or C++.

  Thanks in advance. You can reply to the group or directly to me via email.

Carlos Ribeiro
cribe...@acesso.com.br

 

Re:Put a form inside another form - no MDI approach


Quote
In article <4p54n3$...@doc.zippo.com>, cribeiro@acesso,com.br wrote:

[on putting forms in other forms]

Create a form without borders, as follows. The SubForm will be owned and
contained in Form.

{somewhere in a Form method}
  with SubForm.Create(Self) do
  begin
    Parent := Self;
    {Setbounds to the containing area on Form}
    Show;
  end;
{note: you may want to store references to the forms in a List, for easy
reference}

{routine which handles resize of containing form}
  {if a subform is visible, then resize it to bounds of its containing are}

I can't see any reason why this won't work across DLL boundaries, with the
forms/subforms being declared in different compilation units.

--
Brad Aisa <ba...@tor.hookup.net>  http://www.hookup.net/~baisa/

"The highest responsibility of philosophers is to serve as the
guardians and integrators of human knowledge."   -- Ayn Rand

Re:Put a form inside another form - no MDI approach


Quote
cribeiro@acesso,com.br wrote:
>Hi ppl. I'm trying to which seems impossible... Let me tell the history
>behind it. Please be patient.
>  I'm working on a big project. We want to modularize our code, breaking up
>the main system in many medium sized DLL's. We have many reasons to do it,
>some technical, some commercial.
>  We know the that our approach involves some tradeoffs. In particular, the
>DLL will contain duplicates of the VCL which will make our system a bit :-)
>larger.

If this is going to be a database application written in D1 with the
code in the DLLs accessing the database, you'll need to do some
homework on getting around the fact that Session is declared as a
global.  A data access object in a DLL will reference a different
TSession than data access objects in the main EXE and other DLLs.  

Re:Put a form inside another form - no MDI approach


Quote
cklinc...@worldnet.att.com (Chris Lincoln) wrote:
> cribeiro@acesso,com.br wrote:
> >  I'm working on a big project. We want to modularize our code, breaking up
> >the main system in many medium sized DLL's. We have many reasons to do it,
> >some technical, some commercial.
> >  We know the that our approach involves some tradeoffs. In particular, the
> >DLL will contain duplicates of the VCL which will make our system a bit :-)
> >larger.

> If this is going to be a database application written in D1 with the
> code in the DLLs accessing the database, you'll need to do some
> homework on getting around the fact that Session is declared as a
> global.  A data access object in a DLL will reference a different
> TSession than data access objects in the main EXE and other DLLs.  

Ok, I'll bite, where/how does one start?  We're basically doing the
same thing.  The 'main' app has the TDatabase component, the DLL's are
loaded on demand and the TQuerys within them are programmatically 'pointed'
to the TDatabase (its passed as a parm - did I mention I'm in D2? :-) )
We can't quite seem to accomplish this smoothly and always have to type
the username and pasword over and over and over again.  Not desired as the
goal is to only have ONE connection to the database (oracle over SQL Links,
BTW).

Any thoughts?  Anyone?  There's more info in "D2 TDatabase/TQuery DLL
Split" if anyones interested...

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Chris Kasten
Programmer/Analyst

#include <std/disclaimer.h>
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Re:Put a form inside another form - no MDI approach


Quote
kas...@brookings.net (Chris Kasten) wrote:
>cklinc...@worldnet.att.com (Chris Lincoln) wrote:
>> cribeiro@acesso,com.br wrote:
>> >  I'm working on a big project. We want to modularize our code, breaking up
>> >the main system in many medium sized DLL's. We have many reasons to do it,
>> >some technical, some commercial.
>> >  We know the that our approach involves some tradeoffs. In particular, the
>> >DLL will contain duplicates of the VCL which will make our system a bit :-)
>> >larger.

>> If this is going to be a database application written in D1 with the
>> code in the DLLs accessing the database, you'll need to do some
>> homework on getting around the fact that Session is declared as a
>> global.  A data access object in a DLL will reference a different
>> TSession than data access objects in the main EXE and other DLLs.  

>Ok, I'll bite, where/how does one start?  We're basically doing the
>same thing.  The 'main' app has the TDatabase component, the DLL's are
>loaded on demand and the TQuerys within them are programmatically 'pointed'
>to the TDatabase (its passed as a parm - did I mention I'm in D2? :-) )
>We can't quite seem to accomplish this smoothly and always have to type
>the username and pasword over and over and over again.  Not desired as the
>goal is to only have ONE connection to the database (oracle over SQL Links,
>BTW).

I tried the "TDatabase in the main app with TQueries in DLL" trick in
D1 and had to code some real cluges to get around the fact that the
DLL based stuff would refer to the wrong instance of the global
Session.  I have noticed that D2 takes a somewhat different approach
to referencing a TSession instance from within the TDatabase and
TDataset objects.  But---there are still a bunch of references to the
global Session in the VCL.  Search for DB.Session.xxx in DB.PAS.  I
*think* you may be able to get by with one connection, but you'll have
to pour over the VCL source files DB.PAS and DBTABLES.PAS to make sure
that the Session global bound into your main exe is the only one
referenced, and not the Session globals that will be bound into the
DLL(s).  

Good luck!

Chris Lincoln
Ultrax_Inc();

Other Threads