Solved

Saving/loading MDI forms

Posted on 2004-04-26
4
307 Views
Last Modified: 2010-04-05
I am trying to create a MDI application. Here's what I've got so far:

procedure TForm1.NewItemClick(Sender: TObject);
var
  Child: TPage;
begin
  { New Child }
  Inc(Count);
  Child := TPage.Create(Self);
  Child.Caption := Child.Caption + ' ' + IntToStr(Count);
end;

I need to know how to:

1. Save the current page.
2. Save all the pages.
3. Load a file.

Any help would be greatly appreciated. I am giving the maximum 500 points for this as it is URGENT. I am using Delphi 6.
0
Comment
Question by:rincewind666
4 Comments
 
LVL 3

Expert Comment

by:Kunfufaresi
ID: 10916591
hello you can loop through available children with

  for i := 0 to MDIForm.MDIChildCount - 1 do
  begin
    listbox1.add(MDIForm.MDIChildren[i].Caption);
  end;

  you can access the components on the child form with

var
 DataFromOtherForm:String;

with (MDIForm.MDIChildren[I] as TMDIChildForm).Edit1 do
      DataFromOtherForm := Text;

Kunfu Faresi
0
 
LVL 3

Assisted Solution

by:MikProg
MikProg earned 250 total points
ID: 10916893
Preferrable to implement required functions in TPage class

TPage = ....
....
function Save(FileName: string): boolean; // must retrun result success/fail
function Load(FileName: string): boolean; // must retrun result success/fail
end;

function TPage.Save(FileName: string): boolean;
begin
    // You can use here FileSaveAs dialog to assign FileName or use existing value
    // Open file and save contents you need
end;

function TPage.Load(FileName: string): boolean;
begin
    // You can use here FileOpen dialog to assign FileName or use existing value
    // Open file and load contents.
end;

In main MDI form you need to insert into menu commands Save and SaveAll
procedure TForm.SaveActive(Sender: TObject);
begin
  if Assigned(ActiveMDIChild) and (ActiveMDIChild is TPage) then
    TPage(ActiveMDIChild).Save(ActiveMDIChild.Caption);
end;

procedure TForm.SaveAll(Sender: TObject);
var
  i: integer
begin
  for i := 0 to MDIChildCount - 1 do
    if (MDIForm.MDIChildren[i] is TPage) then
      TPage(MDIForm.MDIChildren[i]).Save(MDIForm.MDIChildren[i].Caption);
end;
and (if you need) implement OnClose.

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
  i: integer
begin
  for i := 0 to MDIChildCount - 1 do
    if (MDIForm.MDIChildren[i] is TPage) then
      if not TPage(MDIForm.MDIChildren[i]).Save(MDIForm.MDIChildren[i].Caption) then
      begin
        Action:=caNone;
        Exit;
     end;
end;
0
 
LVL 22

Accepted Solution

by:
Ferruccio Accalai earned 250 total points
ID: 10918183
My version using Form streaming....

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Page};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

//unit1.dfm  MDImain

object Form1: TForm1
  Left = 192
  Top = 107
  Width = 696
  Height = 480
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  FormStyle = fsMDIForm
  Menu = MainMenu1
  OldCreateOrder = False
  OnClose = FormClose
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object MainMenu1: TMainMenu
    Left = 124
    Top = 38
    object File1: TMenuItem
      Caption = 'File'
      object NewPage1: TMenuItem
        Caption = 'New Page'
        OnClick = NewPage1Click
      end
    end
    object AvailableWindows1: TMenuItem
      Caption = 'Available Windows'
    end
  end
end

//unit1.pas

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus,IniFiles,Unit2;

type
  TForm1 = class(TForm)
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    NewPage1: TMenuItem;
    AvailableWindows1: TMenuItem;
    procedure MyClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure NewPage1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure WriteToIni(Form: TPage);
  end;
var
  Form1: TForm1;
  Ini: TInifile;
  Count: Integer;
  list: TStrings;
implementation


{$R *.dfm}
procedure TForm1.WRiteToIni(Form: TPage);
var
  MemStr : TMemoryStream;
  FileStr : TFileStream;
begin

  MemStr := TMemoryStream.Create;
  FileStr := TFileStream.Create(('c:\'+Form.Caption+'.dat'),fmCreate);  //use your preferred path
  try
    Ini.WriteString('Forms',Form.Caption,Form.Caption+'.dat');
    MemStr.WriteComponent(Form);
    MemStr.Position := 0;
    ObjectBinaryToText(MemStr, FileStr);
  finally
    MemStr.Free;
    FileStr.Free;
  end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
Item: TMEnuItem;
begin
   Ini := TiniFile.Create('c:\Forms.ini');
   List := TStringlist.create;
   try
      ini.ReadSection('Forms',List);
      for i := 0 to LIst.Count-1 do
         begin
            Item := TMenuItem.Create(self);
            Item.Caption := List[i];
            Item.OnClick := MyClick;
            AvailableWindows1.Add(Item);
         end;
   finally
      Count := List.Count;
   end;
end;

procedure TForm1.MyClick(Sender: TObject);
function RemoveAmpersand(Text: String):String;
   begin
      Result := StringReplace(Text,'&','',[]);
   end;
var
MemStr : TMemoryStream;
FileStr : TFileStream;
begin
Application.CreateForm(TPage, Page);
With Page do
   begin
   FileStr := TFileStream.Create(('c:\'+RemoveAmpersand(TMenuItem(sender).Caption)+'.dat'),fmOpenRead);
   MemStr:= TMemoryStream.Create;
   try
    ObjectTextToBinary(FileStr,MemStr);
    MemStr.position := 0;
    MemStr.ReadComponent(Page);
   finally
    MemStr.Free;
    FileStr.Free;
  end;
   Show;
  end;
end;

procedure TForm1.NewPage1Click(Sender: TObject);
var
  Child: TPage;
  item: TMenuItem;
begin
  { New Child }
  inc(Count);
  Child := TPage.Create(Self);
  Child.Name := Child.Name+IntToStr(Count);
  WriteToIni(Child);
  Item := TMenuItem.Create(self);
  Item.Caption := Child.Caption;
  Item.OnClick := MyClick;
  AvailableWindows1.Add(Item);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
List.Free;
Ini.Free;
end;

end.

// unit2.dfm TPage
object Page: TPage
  Left = 192
  Top = 107
  Width = 696
  Height = 480
  Caption = 'Page'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  FormStyle = fsMDIChild
  OldCreateOrder = False
  Position = poDefault
  Visible = True
  OnClose = FormClose
  PixelsPerInch = 96
  TextHeight = 13
end
//unit2.pas

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TPage = class(TForm)
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Page: TPage;

implementation

uses Unit1;

{$R *.dfm}

procedure TPage.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Form1.writetoini(Self);
  action := CaFree;
end;
end.
0
 

Author Comment

by:rincewind666
ID: 10958087
Many thanks for your help.
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

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 my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

708 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

16 Experts available now in Live!

Get 1:1 Help Now