5

The LA Fox Developer Newsletter
May 1998
Add a Cascade Function to
Your Window Menu
Use this generic code to give your MDI application a professional Windows feel.

Most VFP applications are MDI (multiple document interface) in nature. That means that users can open several forms at the same time and jump from one to another at will. MDI applications usually have a Window menu, with options to cascade and tile the open windows and to select specific windows. VFP has most of that functionality built in. But there is no Cascade function. If you want to let your users cascade their forms, you have to write the code yourself.

What exactly do we mean by cascade? Essentially, it means that all the open forms will appear on the screen, each offset slightly to the right and below the one before. If you examine other MDI applications, you will observe a fairly consistent behavior.

Specifically, each window (form) is resized so that it occupies three quarters of the parent window. The first window is then moved to the top left corner of the parent. Subsequent window are placed on top of the previous one, offset down and to the right by an amount equal to the height of the title bar. If a given window does not fit within the boundaries of the parent, the sequence starts again from top left corner of the parent.

The code at the end of this article implements this procedure. As it is generic, it does not know the names of the forms that it is working with. Instead, it uses _SCREEN to access the forms.

For those who haven’t worked with _SCREEN before, it is essentially, a device which allows the main VFP window to be manipulated as if it was itself a form. You can use it to alter the main window’s title, to assign an icon to the main window (see the FoxStuff article Do your application icons always show up?), to move the main window to a particular point on the screen, and, as in this case, to access the forms currently contained in the main window. It has around 70 properties and 20 methods, all of which are described in the VFP Help.

Our Cascade routine uses two properties of_SCREEN: the Forms property is an array (to be precise, a collection) of the currently open forms; and FormCount is the number of forms in this collection. Using these properties, the routine iterates through the open forms, changing their sizes and positions as it does so.

There are a couple of points to watch out for. The routine can only resize a form if its BorderStyle property is 3; other border styles are non-resizable. So we need to test the BorderStyle property each time round the loop. But before we do that, we must check that this property actually exists. That’s because the Forms collection can also hold floating toolbars, and these do not have a border style. The Type() fUnction is used to check
that the property exists.

Even if the form is resizable, it might be subject to minimum and maximum sizes, as stipulated by its MinWidth, MinHeight, MaxWidth and MaxHeight properties. If any of these properties is greater than —1, it means that a corresponding limit is in force. Our routine tests for this before resizing each form.

After the form is resized, the routine moves it to its new position. The Sysmetric(9) function, called near the start of the code, determines the height of the title bar, this being the amount of the vertical and horizontal offset for each window.

To use the code, cut and paste it to your application. Add a Cascade prompt to your Window menu, and place a suitable call (e.g. DO Cascade) in its result field.

PROCEDURE Cascade
local lnHorizOff, lnVertOff, lnNewWidth, InNewHeight, InNewLeft, lnNewTop, lnFmldx

lnHorizOff = Sysmetric(9) && horizontal offset InVertOff = Sysmetric(9) && vertical offset

lnNewWidth = 0.75 * _SCREEN.Width && new form width lnNewHeight = 0.75 * _SCREEN.Height && new form height

lnNewLeft = 0
lnNewTop = 0

FOR lnFmldx =1 TO _SCREEN.FormCount
WiTH _SCREEN.Forms(lnFmldx)
IF Type(”.Border~ty!a”}c>”tJ” AND .BorderS+yle 3
*
form has a resizable border, so adjust its dimensions,
*
subject to its mm/max height and width
.Width = ItF(.MinWidth = -1,lnNewWidth,
Max(InNewWidth,.MinWidth))
.Width = lIF(.MaxWidth = -1,lnNewWldth,
Min(lnNewWidth,.MaxWidth))
.Height = IIF(.MinHeight = -1,lnNewHeight,;
Max(lnNewHeight,.MinHeight))
.Height = ilF(.MaxHeight = -1,lnNewHelght,;
Mmn(innewHeight,.MaxHeight))
ENDIF

*
move the form to its new position
IF (lnNewTop + .Height ‘C _SCREEN.Height);
AND (InNewLeft + .Width <_SCREEN.Width)
*
the form will not overflow the main window,
*
so go ahead and move it
.Move(lnNewLeft,InNewTop)
*
calculate the position of the next form
InNewLeft = InNewLeft + inHorizOff
lnNewlop = lnNewTop + InVertOff
ELSE
*
form does overflow, so go back to top left corner
.Move(0,0)
InNewLeft = InHorlzOffset lnNewTop = InVertOffset
ENDIF
ENDW1TH
ENDFOR

ENDPROC


(Copyright Mike Lewis Consultants Ltd. 1998.)
Page

5