2
votes

There is MDI-application which contains main form fMain and children forms- fChartAcc and fReal. Main form is maximized and client area of main form is limited in screen sizes. When children forms is opened, in client area of main form I can't see bottom part of children forms and appear horizontal scroll bars on childen forms. I want fully paste child form in client area of main form, in screen sizes and, accordingly, in main form sizes without need in horizontal scroll bar.

child form at design time

child form when app is run

Main form

Main form: Formstyle:MDIForm Childred forms:
Formstyle:MDIChild Align- alClient or alCustom Position-tried poDefaultPosOnly, poDefault, poDesigned
autoSize:false tried settings of size of chilled forms place in procedures OnCreate, OnShow, OnResize but no success.

Main form: Formstyle:MDIForm 
Childred forms:  
  Formstyle:MDIChild 
  Align- alClient or alCustom 
  Position-tried poDefaultPosOnly, poDefault, poDesigned  
  autoSize:false
  tried settings of size of chilled forms place in procedures OnCreate, 
    OnShow, OnResize but no success.

unit Umain;

    procedure TFmain.MDIChildCreated(const childHandle : THandle);
    begin
      mdiChildrenTabs.Tabs.AddObject(TForm(FindControl(childHandle)).Caption, TObject(childHandle));
      mdiChildrenTabs.TabIndex := -1 + mdiChildrenTabs.Tabs.Count;
    end;

    procedure TFmain.MDIChildDestroyed(const childHandle : THandle);
    var
      idx: Integer;
    begin
      idx := mdiChildrenTabs.Tabs.IndexOfObject(TObject(childHandle));
      mdiChildrenTabs.Tabs.Delete(idx);
    end;



    procedure TFmain.NChartAccClick(Sender: TObject);
    begin
      application.CreateForm(TfChartAcc, fChartAcc);
     fChartAcc.Show;
    end;

    procedure TFmain.realisatia1Click(Sender: TObject);
    begin
      application.CreateForm(TFgas, Fgas);
      Fgas.Show;
    end;

    end.

unit UChartAcc;

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


    procedure TfChartAcc.FormCreate(Sender: TObject);
    begin
     Left:=0;
     Top:=Fmain.Toolbar.Height+Fmain.MDIChildrentabs.height;
     Height:=Fmain.ClientHeight-Fmain.Toolbar.Height-Fmain.MDIChildrentabs.height-Fmain.StatusBar.Height-2*GetSystemMetrics(SM_CXEDGE);
     Width:=Fmain.ClientWidth- 2*GetSystemMetrics(SM_CXEDGE);

      FMain.MDIChildCreated(self.Handle);
    end;


    procedure TfChartAcc.FormDestroy(Sender: TObject);
    begin
     FMain.MDIChildDestroyed(self.Handle);
    end;

    procedure TfChartAcc.FormResize(Sender: TObject);
    begin
     {
     Left:=0;
     Top:=Fmain.Toolbar.Height+Fmain.MDIChildrentabs.height;
     Height:=Fmain.ClientHeight-Fmain.Toolbar.Height-Fmain.MDIChildrentabs.height-Fmain.StatusBar.Height-2*GetSystemMetrics(SM_CXEDGE);
     Width:=Fmain.ClientWidth- 2*GetSystemMetrics(SM_CXEDGE);
     }
    end;





    procedure TfChartAcc.FormShow(Sender: TObject);
    begin
     Left:=0;
     Top:=Fmain.Toolbar.Height+Fmain.MDIChildrentabs.height;
     Height:=Fmain.ClientHeight-Fmain.Toolbar.Height-Fmain.MDIChildrentabs.height-Fmain.StatusBar.Height-2*GetSystemMetrics(SM_CXEDGE);
     Width:=Fmain.ClientWidth- 2*GetSystemMetrics(SM_CXEDGE);
    end;

    end.

Project 1

1
Tom Brunberg, I edit question- added screenshots. You wrote:"Have you considered what happens if a user has a different size screen?". Yes, I want such solutions that resizes child forms when screen size is changed. - basti
Tom Brunberg, thank you very much for you attempt to help. 1) On compile(F9) it is created in maximum sizes, on full desktop. After that I make main form smaller for you, for good looking. After that I create child form. 2) I insert you code in OnCreate of child form (fChartAcc) but nothing changed. - basti
Tom Brunberg, my settings fot left, top, height and bottom gets the same results: height 881, width 1276. BoundsRect property gets the same (0,0,1276, 881). What is the difference. - basti

1 Answers

0
votes

To get current ClientRect of a MDI main form you can use WinApi.Windows.GetClientRect() function like this (adapted to your uChartAcc unit):

Add a new procedure to the FChartAcc form, e.g. MyAdjustSize. I changed the name, because AdjustSize() is a virtual method of TWinControl:

procedure TFChartAcc.MyAdjustSize;
var
  r: TRect;
begin
  if not WinApi.Windows.GetClientRect(FMain.ClientHandle, r) then
    RaiseLastOSError;
  BoundsRect := r;
end;

The window referred to by ClientHandle already excludes menu bars, tool bars etc. that are aligned to the sides of the form, so no need for further calculations.

Replace previously suggested code from TFChartAcc.FormCreate, with a call to MyAdjustSize:

procedure TFChartAcc.FormCreate(Sender: TObject);
begin
  MyAdjustSize;

  FMain.MDIChildCreated(self.Handle);
end;

Then in the main form add an event handler for the OnResize event as follows. The purpose is to call the MyAdjustSize procedure for all currently existing child forms:

procedure TFMain.FormResize(Sender: TObject);
var
  ix: integer;
  ob: TWinControl;
begin
  for ix := 0 to MDIChildrenTabs.Tabs.Count-1 do
  begin
      ob := FindControl(THandle(MDIChildrenTabs.Tabs.Objects[ix]));
      if ob is TFChartAcc then
        TFChartAcc(ob).MyAdjustSize;
  end;
end;

Because all child windows are already sized correctly, we don't need to call MyAdjust when selecting another child form.

procedure TFMain.mdiChildrenTabsClick(Sender: TObject);
var
  ix: integer;
  ob: TWinControl;
begin
  ix := MDIChildrenTabs.TabIndex;
  if ix > -1 then
  begin
    ob := FindControl(THandle(MDIChildrenTabs.Tabs.Objects[ix]));
    ob.BringToFront;
  end;
end;