Board index » delphi » FormStyle?

FormStyle?

Hallo,

Which formstyles are necessary to realize this:
- inside one main window I want to open some child windows
- each child window should not get out of the main window frame
- each child window should be shown in the taskbar when opened

I don't want to use MDIForm/MDIChild styles, because I've read, that the
classic MDI style is out.

Regards
Stephan

 

Re:FormStyle?


Quote
In article <3eba66a...@newsgroups.borland.com>, Stephan Schneider wrote:
> Which formstyles are necessary to realize this:
> - inside one main window I want to open some child windows
> - each child window should not get out of the main window frame
> - each child window should be shown in the taskbar when opened

There is no way to achieve this. Only top-level windows can have taskbar
buttons, so MDI is out, classical child windows are out, too. So you can
*either* have your "child windows" contained in the host windows frame,
*or* you can have taskbar buttons for the child windows.

Unless you are prepared to do some coding, that is. There seems to be a
way to get a rather convincing fake of what you are after. You need code
in both the child window and the main window. Here is a form class you can
use as a base class (via visual form inheritance) for the children:

unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs,
  ComCtrls, StdCtrls;

type
  TWMSizing = TWMMoving;
  TForm3 = class(TForm)
    StatusBar: TStatusBar;
  private
    { Private declarations }
    procedure WMGetMinMaxInfo( var msg: TWMGetMinMaxInfo ); message
WM_GETMINMAXINFO;
    procedure WMMOving( var msg: TWMMoving ); message WM_MOVING;
    procedure WMSizing( var msg: TWMSizing ); message WM_SIZING;
    Function GetWorkspace: TRect;
    procedure ModifyDragRect(var dragrect: TRect);
  public
    Procedure CreateParams( var params: TCreateParams ); override;
    Procedure SetBounds(ALeft: Integer; ATop: Integer; AWidth: Integer;
      AHeight: Integer); override;
  end;

implementation

uses Types;

{$R *.DFM}

{ TForm3 }

procedure TForm3.CreateParams(var params: TCreateParams);
begin
  inherited;
  params.ExStyle := params.ExStyle or WS_EX_APPWINDOW;
  params.WndParent := Application.MainForm.Handle;
end;

function TForm3.GetWorkspace: TRect;
begin
  result:= Application.MainForm.ClientRect;
  MapWindowPoints( Application.MainForm.Handle, 0, result, 2 );
end;

procedure TForm3.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
var
  r: TRect;
begin
  r:= GetWorkspace;
  If aLeft < r.Left Then
    aLeft := r.Left;
  If aTop < r.Top Then
    aTop := r.Top;
  If (aLeft+aWidth) > r.Right Then
    aWidth := r.Right - aLeft;
  If (aTop + AHeight) > r.Bottom Then
    AHeight := r.Bottom - aTop;
  inherited;
end;

procedure TForm3.WMGetMinMaxInfo(var msg: TWMGetMinMaxInfo);
var
  r: TRect;
begin
  inherited;
  r:= GetWorkspace;
  msg.MinMaxInfo^.ptMaxPosition := r.TopLeft;
  msg.MinMaxInfo^.ptMaxTrackSize :=
    Point( r.Right - Left, r.Bottom - Top );
  OffsetRect( r, -r.Left, -r.Top );
  msg.MinMaxInfo^.ptMaxSize := r.BottomRight;
end;

procedure TForm3.ModifyDragRect( Var dragrect: TRect );
var
  r: TRect;
begin
  r:= GetWorkspace;
  If DragRect.left < r.left Then
    OffsetRect( DragRect, r.left - DragRect.left, 0 );
  If DragRect.top < r.top Then
    OffsetRect( DragRect, 0, r.top - DragRect.top );
  If DragRect.right > r.right Then
    OffsetRect( DragRect, r.right - DragRect.right, 0 );
  If DragRect.bottom > r.bottom Then
    OffsetRect( DragRect, 0, r.bottom - DragRect.bottom );
end;

procedure TForm3.WMMOving(var msg: TWMMoving);
begin
  ModifyDragRect( msg.DragRect^ );
  inherited;
end;

procedure TForm3.WMSizing(var msg: TWMSizing);
begin
  ModifyDragRect( msg.DragRect^ );
  inherited;
end;

end.

Do not autocreate instances of the child forms, like MDI children they
should be created on demand, e.g. from a menu item on the main form:

procedure TForm1.Open1Click(Sender: TObject);
begin
  Tform3.Create( Application ).Show;
end;

If you play with this setup you will see that there is one thing not
handled yet: you can drag and resize the main form with children open and
this way get the children out of the main forms client area. Do deal with
that you need handlers for WM_SIZING and WM_MOVING on the main form as
well and there take appropriate action (e.g. prevent the form from getting
smaller than the combined bounding rect of the children, or moving/sizing
the children to keep them in the client area). What you cannot do with
this setup is *clip* the child windows on the main forms client area.
Minimizing the main form hides the child forms, but you can show them
independent of the main form by clicking on their button, this is also
something one would have to deal with (e.g. by calling Application.Restore
if the child window is shown while the main form is hidden).

There is still some work to do, but the scheme looks more feasable on
second glance than i originally thought.

--
Peter Below (TeamB)  
Use the newsgroup archives :
http://www.mers.com/searchsite.html
http://www.tamaracka.com/search.htm
http://groups.google.com
http://www.prolix.be

Re:FormStyle?


First of all thx for our answer. I'll test it out.

But where is the type TWMMoving declared?

Greetings
Stephan Schneider

"Peter Below (TeamB)" <100113.1...@compuXXserve.com> schrieb im Newsbeitrag
news:VA.00009dfb.0092af60@antispam.compuserve.com...

Quote
> In article <3eba66a...@newsgroups.borland.com>, Stephan Schneider wrote:
> > Which formstyles are necessary to realize this:
> > - inside one main window I want to open some child windows
> > - each child window should not get out of the main window frame
> > - each child window should be shown in the taskbar when opened

> There is no way to achieve this. Only top-level windows can have taskbar
> buttons, so MDI is out, classical child windows are out, too. So you can
> *either* have your "child windows" contained in the host windows frame,
> *or* you can have taskbar buttons for the child windows.

> Unless you are prepared to do some coding, that is. There seems to be a
> way to get a rather convincing fake of what you are after. You need code
> in both the child window and the main window. Here is a form class you can
> use as a base class (via visual form inheritance) for the children:

> unit Unit3;

> interface

> uses
>   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
> Dialogs,
>   ComCtrls, StdCtrls;

> type
>   TWMSizing = TWMMoving;
>   TForm3 = class(TForm)
>     StatusBar: TStatusBar;
>   private
>     { Private declarations }
>     procedure WMGetMinMaxInfo( var msg: TWMGetMinMaxInfo ); message
> WM_GETMINMAXINFO;
>     procedure WMMOving( var msg: TWMMoving ); message WM_MOVING;
>     procedure WMSizing( var msg: TWMSizing ); message WM_SIZING;
>     Function GetWorkspace: TRect;
>     procedure ModifyDragRect(var dragrect: TRect);
>   public
>     Procedure CreateParams( var params: TCreateParams ); override;
>     Procedure SetBounds(ALeft: Integer; ATop: Integer; AWidth: Integer;
>       AHeight: Integer); override;
>   end;

> implementation

> uses Types;

> {$R *.DFM}

> { TForm3 }

> procedure TForm3.CreateParams(var params: TCreateParams);
> begin
>   inherited;
>   params.ExStyle := params.ExStyle or WS_EX_APPWINDOW;
>   params.WndParent := Application.MainForm.Handle;
> end;

> function TForm3.GetWorkspace: TRect;
> begin
>   result:= Application.MainForm.ClientRect;
>   MapWindowPoints( Application.MainForm.Handle, 0, result, 2 );
> end;

> procedure TForm3.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
> var
>   r: TRect;
> begin
>   r:= GetWorkspace;
>   If aLeft < r.Left Then
>     aLeft := r.Left;
>   If aTop < r.Top Then
>     aTop := r.Top;
>   If (aLeft+aWidth) > r.Right Then
>     aWidth := r.Right - aLeft;
>   If (aTop + AHeight) > r.Bottom Then
>     AHeight := r.Bottom - aTop;
>   inherited;
> end;

> procedure TForm3.WMGetMinMaxInfo(var msg: TWMGetMinMaxInfo);
> var
>   r: TRect;
> begin
>   inherited;
>   r:= GetWorkspace;
>   msg.MinMaxInfo^.ptMaxPosition := r.TopLeft;
>   msg.MinMaxInfo^.ptMaxTrackSize :=
>     Point( r.Right - Left, r.Bottom - Top );
>   OffsetRect( r, -r.Left, -r.Top );
>   msg.MinMaxInfo^.ptMaxSize := r.BottomRight;
> end;

> procedure TForm3.ModifyDragRect( Var dragrect: TRect );
> var
>   r: TRect;
> begin
>   r:= GetWorkspace;
>   If DragRect.left < r.left Then
>     OffsetRect( DragRect, r.left - DragRect.left, 0 );
>   If DragRect.top < r.top Then
>     OffsetRect( DragRect, 0, r.top - DragRect.top );
>   If DragRect.right > r.right Then
>     OffsetRect( DragRect, r.right - DragRect.right, 0 );
>   If DragRect.bottom > r.bottom Then
>     OffsetRect( DragRect, 0, r.bottom - DragRect.bottom );
> end;

> procedure TForm3.WMMOving(var msg: TWMMoving);
> begin
>   ModifyDragRect( msg.DragRect^ );
>   inherited;
> end;

> procedure TForm3.WMSizing(var msg: TWMSizing);
> begin
>   ModifyDragRect( msg.DragRect^ );
>   inherited;
> end;

> end.

> Do not autocreate instances of the child forms, like MDI children they
> should be created on demand, e.g. from a menu item on the main form:

> procedure TForm1.Open1Click(Sender: TObject);
> begin
>   Tform3.Create( Application ).Show;
> end;

> If you play with this setup you will see that there is one thing not
> handled yet: you can drag and resize the main form with children open and
> this way get the children out of the main forms client area. Do deal with
> that you need handlers for WM_SIZING and WM_MOVING on the main form as
> well and there take appropriate action (e.g. prevent the form from getting
> smaller than the combined bounding rect of the children, or moving/sizing
> the children to keep them in the client area). What you cannot do with
> this setup is *clip* the child windows on the main forms client area.
> Minimizing the main form hides the child forms, but you can show them
> independent of the main form by clicking on their button, this is also
> something one would have to deal with (e.g. by calling Application.Restore
> if the child window is shown while the main form is hidden).

> There is still some work to do, but the scheme looks more feasable on
> second glance than i originally thought.

> --
> Peter Below (TeamB)
> Use the newsgroup archives :
> http://www.mers.com/searchsite.html
> http://www.tamaracka.com/search.htm
> http://groups.google.com
> http://www.prolix.be

Re:FormStyle?


Quote
In article <3ebb4...@newsgroups.borland.com>, Stephan Schneider wrote:
> First of all thx for our answer. I'll test it out.

> But where is the type TWMMoving declared?

In the Messages unit, at least in D7. It may be missing from older versions.

  TWMMoving = packed record
    Msg: Cardinal;
    Edge: Integer;
    DragRect: PRect;
  end;

--
Peter Below (TeamB)  
Use the newsgroup archives :
http://www.mers.com/searchsite.html
http://www.tamaracka.com/search.htm
http://groups.google.com
http://www.prolix.be

Other Threads