PDA

View Full Version : Delphi 6 Tutorial (Chapter 11)


_I_Play_Chess
11-08-2003, 09:30 AM
Your First MDI Delphi Project
-----------------------------------

Learn how to create a powerful "multiple document interface" application using Delphi.

Welcome to the eleventh chapter of the FREE online programming course:
A Beginner’s Guide to Delphi Programming.
Learn how to create a "multiple document interface" application using Delphi.

It's time for your second Delphi project! This time we'll explore building MDI applications using Delphi. After you have created your first Delphi game, you could start developing your own set of Delphi games... Then, why not create one "big" Delphi application to host all your games!

Multiple Document Interface Applications

In simple words, in an MDI application, more than one document or child window can be opened within a single parent window. This is a common situation in applications such as spreadsheets or word processors - one window, usually called the MDI parent or MDI container, contains many other windows, usually called child forms.

In our scenario, MDI parent form would be the host to all your games developed as single form (window) MDI child forms.

What is MDI?

MDI stands for multiple document interface. In an MDI application, more than one document or child window can be opened within a single parent window. This is common in applications such as spreadsheets or word processors - one window, usually called the MDI parent or MDI container, contains many other windows, usually called child forms.

Every MDI application usually has three basic parts:


One (and only one) MDI container (parent) form,
One or more (usually more) MDI child forms,
The MDI main menu.

1- MDI "mother"
----------------------
In a MDI application we can have only one MDI container form to a project, and that form will, mostly, be the start up form.
To create the main window for an MDI application, follow these steps:

Start Delphi and select File | New Application... Delphi will create a new project with one form called form1, by default.
Assign a Name property such as frMain to the form.
Set the FormStyle property to fsMDIform.
Save this project (name the project as you like, e.g. prMDIExample), along with uMain.pas in a newly created folder.
As we can see, to make an MDI container form, we set the FormStyle property of the main form (i.e. any form that we want to be the MDI container) to be fsMDIform. Only one form per application can be fsMDIform.

2- MDI "children"
-----------------------
Every MDI "mother" needs at least one child. MDI child forms are just simple forms, but unlike windows as an AboutBox, MDI child windows are restricted to appearing inside the "mothers" window boundaries. Moreover, if the child form is minimized, its icon appears inside the MDI parent form, rather than in the Windows desktop ( only the parent window's icon appears in the task bar).

Now, we'll create some additional forms - MDI child forms, precisely. Simply choose File | New Form. This will create a new form object called form1, by default. With the Object Inspector change form1's Name property to frChild, and more important set FormStyle property to fsMDIChild. Save this form with it's associated unit as uchild.pas. Note: we can also turn an existing form into an MDI child form by adjusting this property.
Your application can include many MDI child forms of similar or different types.

Note: MDI application can also include standard, non-MDI forms that are not contained in the MDI form. A typical use of a standard form in an MDI application is to display a modal dialog box (such as about box, or custom file handling dialog).

As we can see, at design time both parent and child form look the same - it's hard to tell which one is "the boss".

A child widow in an MDI applications is like any other "normal" window in a non MDI (that is: SDI) application. Child forms can contain any components like Grids, Memos and Pictures. Traditionally, objects like status bars and toolbars usually appear in the MDI parent window.

Auto create -> Available
Next we'll make some adjustments to the project. Select Project | Options, this will open the Project Options dialog. Select the frChild from the left pane ("Auto-create forms"), and move it to the right one (Available forms). The right pane lists those forms that are used by your application but are not automatically created. In a MDI application, by default, all child forms are automatically created and are displayed inside their container. There will be nothing wrong if we don't perform this adjustment, however, standard Windows behavior is that MDI applications create their child window under program (user) control.

Create and show...
Once we have set that the Child form is not automatically created, we'll need some code that creates (one) instance of a frChild form object. The following CreateChildForm function needs to be placed inside the main (MDI parent) form's unit (along with the header in the interface's private part):
___________________
uses uchild;
...
procedure TfrMain.CreateChildForm
(const childName : string);
var Child: TfrChild;
begin
Child := TfrChild.Create(Application);
Child.Caption := childName;
end;
______________________

Note 1: For now, it's enough to know that this code will create one child form with childName caption.
Note 2: Don't forget that "uses uchild" part.

Close don't minimize!

Closing the child window in a MDI application only minimizes it in parent's client area. Therefore we have to provide an OnClose procedure, and set the Action parameter to caFree:
-------------------------------
procedure TfrChild.FormClose
(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
-------------------------------

Note: If a form is an MDI child form, and its BorderIcons property is biMinimize (default), then the default Action is caMinimize. If a MDI child form does not have these settings, the default Action is caNone, meaning that nothing happens when the user attempts to close the form.

3- MDI parent menu
-------------------------
Every MDI application should have a main menu with, if nothing more, window arrange/cascade.. options. As we have previously moved the child form ,from Auto-create forms to Available forms, we'll need some code that (menu item) will create child forms.

If you know how to work with TMainMenu component, than just drop one on the frMain (MDI parent) and let the menus look like:

leblitzer
11-08-2003, 09:31 AM
Originally posted by _i_play_chess
Your First MDI Delphi Project
-----------------------------------

Learn how to create a powerful "multiple document interface" application using Delphi.

Welcome to the eleventh chapter of the FREE online programming course:
A Beginner’s Guide to Delphi Programming.
Learn how to create a "multiple document interface" application using Delphi.

It's time for your second Delphi project! This time we'll explore building MDI applications using Delphi. After you have created your first Delphi game, you could start developing your own set of Delphi games... Then, why not create one "big" Delphi application to host all your games!

Multiple Document Interface Applications

In simple words, in an MDI application, more than one document or child window can be opened within a single parent window. This is a common situation in applications such as spreadsheets or word processors - one window, usually called the MDI parent or MDI container, contains many other windows, usually called child forms.

In our scenario, MDI parent form would be the host to all your games developed as single form (window) MDI child forms.

What is MDI?

MDI stands for multiple document interface. In an MDI application, more than one document or child window can be opened within a single parent window. This is common in applications such as spreadsheets or word processors - one window, usually called the MDI parent or MDI container, contains many other windows, usually called child forms.

Every MDI application usually has three basic parts:


One (and only one) MDI container (parent) form,
One or more (usually more) MDI child forms,
The MDI main menu.

1- MDI "mother"
----------------------
In a MDI application we can have only one MDI container form to a project, and that form will, mostly, be the start up form.
To create the main window for an MDI application, follow these steps:

Start Delphi and select File | New Application... Delphi will create a new project with one form called form1, by default.
Assign a Name property such as frMain to the form.
Set the FormStyle property to fsMDIform.
Save this project (name the project as you like, e.g. prMDIExample), along with uMain.pas in a newly created folder.
As we can see, to make an MDI container form, we set the FormStyle property of the main form (i.e. any form that we want to be the MDI container) to be fsMDIform. Only one form per application can be fsMDIform.

2- MDI "children"
-----------------------
Every MDI "mother" needs at least one child. MDI child forms are just simple forms, but unlike windows as an AboutBox, MDI child windows are restricted to appearing inside the "mothers" window boundaries. Moreover, if the child form is minimized, its icon appears inside the MDI parent form, rather than in the Windows desktop ( only the parent window's icon appears in the task bar).

Now, we'll create some additional forms - MDI child forms, precisely. Simply choose File | New Form. This will create a new form object called form1, by default. With the Object Inspector change form1's Name property to frChild, and more important set FormStyle property to fsMDIChild. Save this form with it's associated unit as uchild.pas. Note: we can also turn an existing form into an MDI child form by adjusting this property.
Your application can include many MDI child forms of similar or different types.

Note: MDI application can also include standard, non-MDI forms that are not contained in the MDI form. A typical use of a standard form in an MDI application is to display a modal dialog box (such as about box, or custom file handling dialog).

As we can see, at design time both parent and child form look the same - it's hard to tell which one is "the boss".

A child widow in an MDI applications is like any other "normal" window in a non MDI (that is: SDI) application. Child forms can contain any components like Grids, Memos and Pictures. Traditionally, objects like status bars and toolbars usually appear in the MDI parent window.

Auto create -> Available
Next we'll make some adjustments to the project. Select Project | Options, this will open the Project Options dialog. Select the frChild from the left pane ("Auto-create forms"), and move it to the right one (Available forms). The right pane lists those forms that are used by your application but are not automatically created. In a MDI application, by default, all child forms are automatically created and are displayed inside their container. There will be nothing wrong if we don't perform this adjustment, however, standard Windows behavior is that MDI applications create their child window under program (user) control.

Create and show...
Once we have set that the Child form is not automatically created, we'll need some code that creates (one) instance of a frChild form object. The following CreateChildForm function needs to be placed inside the main (MDI parent) form's unit (along with the header in the interface's private part):
___________________
uses uchild;
...
procedure TfrMain.CreateChildForm
(const childName : string);
var Child: TfrChild;
begin
Child := TfrChild.Create(Application);
Child.Caption := childName;
end;
______________________

Note 1: For now, it's enough to know that this code will create one child form with childName caption.
Note 2: Don't forget that "uses uchild" part.

Close don't minimize!

Closing the child window in a MDI application only minimizes it in parent's client area. Therefore we have to provide an OnClose procedure, and set the Action parameter to caFree:
-------------------------------
procedure TfrChild.FormClose
(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
-------------------------------

Note: If a form is an MDI child form, and its BorderIcons property is biMinimize (default), then the default Action is caMinimize. If a MDI child form does not have these settings, the default Action is caNone, meaning that nothing happens when the user attempts to close the form.

3- MDI parent menu
-------------------------
Every MDI application should have a main menu with, if nothing more, window arrange/cascade.. options. As we have previously moved the child form ,from Auto-create forms to Available forms, we'll need some code that (menu item) will create child forms.

If you know how to work with TMainMenu component, than just drop one on the frMain (MDI parent) and let the menus look like:

can u put all lesson on your site bruz?

_I_Play_Chess
11-08-2003, 09:40 AM
(continued)
We'll use "New child" menu item to construct new child forms to our application. The second menu (Window menu) will be used to arrange the child windows inside the MDI parent window-form.

...Create and show
------------------------
Finally we can write some code to create a MDI child form. The application's File | New Child menu item, procedure NewChild1Click calls CreateChildForm procedure, to create (next) instance of the frChild form.
-------------------------
procedure TfrMain.NewChild1Click(Sender: TObject);
begin
CreateChildForm('Child '+IntToStr(MDIChildCount+1));
end;
-------------------------
Note: Newly created child forms will have "Child x" caption, where x represents the number of child forms inside a MDI form, as discussed below.

Close All
-----------
When working with multiple document interface applications, like this one, it's always preferable to have some code that will close all child forms.
-------------------------
procedure TfrMain.CloseAll1Click(Sender: TObject);
var i: integer;
begin
for i:= 0 to MdiChildCount - 1 do
MDIChildren[i].Close;
end;
-------------------------
Note: You should check if there are some information inside each child form that needs to be saved before closing. The best is to use OnCloseQuery event handler for such purposes.

MdiChildCount, MDIChildren

Since these are the first MDI-only-meaningful properties we are addressing for now, let's see what do they do. MdiChildCount read only property contains the number of created child forms. If no child windows are created this property is 0. We often use MdiChildCount along with MDIChildren array. MDIChildren is zero based array which contains created TForm object references to all child windows.

Note: the index of the most-recently-created MDI child is always 0, and the index of the first-created MDI child is always MDIChildCount - 1.

The Window menu

Delphi provides most of the commands that are likely to be placed inside a Window menu item. Commands like: tile, cascade and arrange all are used to rearrange, non minimized, child windows inside the parent. We simply call these methods like:
-------------------------
procedure TfrMain.Cascade1Click(Sender: TObject);
begin
Cascade;
end;

procedure TfrMain.Tile1Click(Sender: TObject);
begin
Tile;
end;

procedure TfrMain.ArrangeAll1Click(Sender: TObject);
begin
ArrangeIcons;
end;

(see pic below and in the next illustration)

_I_Play_Chess
11-08-2003, 09:42 AM
See below

_I_Play_Chess
11-08-2003, 09:50 AM
Extending your MDI development knowledge
---------------------------------------------------------
Now, I'll provide two more code samples you could find useful in an MDI application.

• Create New or Show Already Created Child Form?

Assume, for the minute, that you have an MDI application with more than one type of child forms. What I mean, is that you can have your Delphi MDI parent form host one child form designed to be able to display graphic files (TGraphicChildForm) and another form (TMemoChildForm) designed to display some text inside, for example, a Memo component. Now, think of a situation when you have more than a dozen of various types of MDI child forms.
What you might want to have in your application, is the ability to decide whether a new instance of the specified child form is to be created or the previous instance should be brought to front - if one exists.

The following code snippet solves the above "problem":
---------------------------
procedure TMainForm.CreateMDIChild(frm : TFormClass);
const
sMDIChildFormCreated =
'Form "%s" already created. Select OK to
switch to it, Yes to create a new form instance.';
var
i:integer;
bCreated:boolean;
f:TForm;
begin
bCreated:=False;
for i:= 0 to MainForm.MDIChildCount-1 do
begin
if MainForm.MDIChildren[i] is frm then
begin
f:=MainForm.MDIChildren[i] as frm ;
bCreated:=True;
Break;
end;
end;

if not bCreated then
begin
frm.Create(Application);
end
else
begin
case MessageDlg(Format(sMDIChildFormCreated,
[f.caption]), mtConfirmation,
[mbOk, mbYes, mbCancel],0) of
mrOK: f.Show;
mrYes: frm.Create(Application);
mrCancel: //do notingg
end; //case
end;
end;
-----------------------------

To call the above procedure you can use the following code:

CreateMDIChild(TGraphicChildForm);
//or
CreateMDIChild(TMemoChildForm);

-----------------------------

Let's see what the above code does... First, you send to the CreateMDIChild procedure the name of the child form class as the parameter. Then, in the CreateMDIChild procedure, the code looks for an already created MDI child form of the provided class, if the one is not found, one gets created. If, on the other hand, the instance (at least one) of the child form is already created, the message dialog asks the user whether to create a new instance or to bring to front that previously created form.
Again, more or less a not_for_beginner type of code, but you should be able to understand the way it works.

• Hide MDI child form when minimized

As you know by now, when you try to close an MDI child form, the form only gets minimized. You are however, able to set the Action parameter of the OnClose event method to caFree to really close it; or even set to caNone - to "mark" that the form cannot be closed.
--------------------------
procedure TMDIChild.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caNone;
end;
--------------------------

However, as stated, the default behavior for MDI child form OnClose event is to become minimized. Now, if you want to hide the form when it gets minimized you can use the next trick:
--------------------------
procedure TMDIChild.WMSize(var M:TWMSIZE);
begin
if M.SizeType=Size_Minimized then
ShowWindow(Handle,Sw_Hide);
end;
--------------------------

Note 1: You'll need to add the procedure header to the private part of the form type declaration:

private
procedure WMSize(var M : TWMSIZE); Message WM_Size;

Note 2: Even though this procedure relies on Windows Messages and handling them, don't be afraid to use it. The truth is that you are *beginner* developer, but you are trying to become an expert ;)

Some exercises for you...
As in all the chapters of this course, I'll provide an idea for you to try to use the gathered knowledge in a real situation. This is what you could do: build an MDI application and make your Delphi TicTacToe game from the previous chapter to be the child form of the created MDI project.
To the next chapter: A Beginner's Guide to Delphi Programming
This is the end of the eleventh chapter

_I_Play_Chess
11-12-2003, 05:52 PM
Hope u still learning the DELPHI?

we need you later on There is amny project in here on this web site.

Let me know where r u at?

_I_Play_Chess
11-12-2003, 05:53 PM
Well no News from you GUYS Means GOOD NEWS!!!!!!!!!!

$hAWn
11-13-2003, 05:44 AM
ZzZzZzZzZz

_I_Play_Chess
11-13-2003, 12:58 PM
We are a seriuos section in here!

leblitzer
11-13-2003, 01:58 PM
Originally posted by _i_play_chess
Extending your MDI development knowledge
---------------------------------------------------------
Now, I'll provide two more code samples you could find useful in an MDI application.

• Create New or Show Already Created Child Form?

Assume, for the minute, that you have an MDI application with more than one type of child forms. What I mean, is that you can have your Delphi MDI parent form host one child form designed to be able to display graphic files (TGraphicChildForm) and another form (TMemoChildForm) designed to display some text inside, for example, a Memo component. Now, think of a situation when you have more than a dozen of various types of MDI child forms.
What you might want to have in your application, is the ability to decide whether a new instance of the specified child form is to be created or the previous instance should be brought to front - if one exists.

The following code snippet solves the above "problem":
---------------------------
procedure TMainForm.CreateMDIChild(frm : TFormClass);
const
sMDIChildFormCreated =
'Form "%s" already created. Select OK to
switch to it, Yes to create a new form instance.';
var
i:integer;
bCreated:boolean;
f:TForm;
begin
bCreated:=False;
for i:= 0 to MainForm.MDIChildCount-1 do
begin
if MainForm.MDIChildren[i] is frm then
begin
f:=MainForm.MDIChildren[i] as frm ;
bCreated:=True;
Break;
end;
end;

if not bCreated then
begin
frm.Create(Application);
end
else
begin
case MessageDlg(Format(sMDIChildFormCreated,
[f.caption]), mtConfirmation,
[mbOk, mbYes, mbCancel],0) of
mrOK: f.Show;
mrYes: frm.Create(Application);
mrCancel: //do notingg
end; //case
end;
end;
-----------------------------

To call the above procedure you can use the following code:

CreateMDIChild(TGraphicChildForm);
//or
CreateMDIChild(TMemoChildForm);

-----------------------------

Let's see what the above code does... First, you send to the CreateMDIChild procedure the name of the child form class as the parameter. Then, in the CreateMDIChild procedure, the code looks for an already created MDI child form of the provided class, if the one is not found, one gets created. If, on the other hand, the instance (at least one) of the child form is already created, the message dialog asks the user whether to create a new instance or to bring to front that previously created form.
Again, more or less a not_for_beginner type of code, but you should be able to understand the way it works.

• Hide MDI child form when minimized

As you know by now, when you try to close an MDI child form, the form only gets minimized. You are however, able to set the Action parameter of the OnClose event method to caFree to really close it; or even set to caNone - to "mark" that the form cannot be closed.
--------------------------
procedure TMDIChild.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caNone;
end;
--------------------------

However, as stated, the default behavior for MDI child form OnClose event is to become minimized. Now, if you want to hide the form when it gets minimized you can use the next trick:
--------------------------
procedure TMDIChild.WMSize(var M:TWMSIZE);
begin
if M.SizeType=Size_Minimized then
ShowWindow(Handle,Sw_Hide);
end;
--------------------------

Note 1: You'll need to add the procedure header to the private part of the form type declaration:

private
procedure WMSize(var M : TWMSIZE); Message WM_Size;

Note 2: Even though this procedure relies on Windows Messages and handling them, don't be afraid to use it. The truth is that you are *beginner* developer, but you are trying to become an expert ;)

Some exercises for you...
As in all the chapters of this course, I'll provide an idea for you to try to use the gathered knowledge in a real situation. This is what you could do: build an MDI application and make your Delphi TicTacToe game from the previous chapter to be the child form of the created MDI project.
To the next chapter: A Beginner's Guide to Delphi Programming
This is the end of the eleventh chapter
its pretty good when will u post theses stuff on your site ipc?

_I_Play_Chess
11-13-2003, 05:22 PM
I do not have anymore site as I already told you.

My only site that is mine is the business one!


There I do not present how to work with delphi!!!!!!

leblitzer
11-14-2003, 02:14 PM
ya i saw your site down , whats the point?

_I_Play_Chess
11-14-2003, 03:17 PM
Yahoo asked me to change the name from www.geocities.com/_i_play_ches (http://www.geocities.com/_i_play_ches) to

www.geocities.com/index.html (http://www.geocities.com/index.html)

and that isn't easy and had no time for that and because i do not want to pay for the 1st title .it's like 10 american dollars if u want to keep the name as i had it

So bye bye web site!!!

leblitzer
11-14-2003, 03:49 PM
well i will pay your stuff bruz