Wiki Home

Page Frame


Namespace: VFP
The Visual FoxPro visual base class that provides a tabbed dialog user interface. It may contain zero or more Page objects.
When creating generic subclasses of the Page Frame class define them with .PageCount = 0. This will allow the users of the classes to freely set the .PageCount and the names of the contained pages when they use the subclass. If instead you create the subclass with a non-zero .PageCount the names you give the Page objects are fixed and the user can not change them. The user can increase the PageCount but they can not decrease it at design time. The user could at runtime use .RemoveObject() to get rid of the unneeded pages, but it runs the risk of crashing the Page Frame class if it has any code that references the pages by name.
Thanks for this info - I had given up on using Page Frame and Page subclasses because of the naming problem. Here's a gotcha which took me quite a while to figure out. If you store a form definition in a class library and that form has a subclassed Page Frame on it, in the class designer the ActivePage property of the Page Frame will show 1 after you have increased the PageCount to whatever value you need. However, when you create a form based on the class defined in the class library, the ActivePage property will revert to 0, which causes the Page Frame to appear greyed-out on the form in both the form designer and in runtime. To get the desired behavior, you must manually overwrite the ActivePage property in the class designer to 1. -- Jim Vahl
To get tabs on the sides or bottom of a Page Frame see the article on Tab Strip.

Beginning in VFP 8, the Page Frame has a TabOrientation property that lets you put the tabs on any of the four sides of the Page Frame.
A VFP idiom: When you refresh a Form with a Page Frame on it, only the .ActivePage gets refreshed. This is by design and is desireable for video performance reasons. Thus, whenever the Page.Activate() method fires, you should do a This.Refresh().
It's really a PITA to remember to put a This.Refresh into the Activate method of each page. See Auto Page Refresher for a suggestion on how to implement this behavior in your base page frame class. -- Mike Feltman
Unfortunately, activepage doesn't give you the index of the active page in the pages-collection, but the pageorder of the active page.
So a property (e. g. activepageindex) with an access-method in a pageframe-baseclass with following code is usefull:
LOCAL i
FOR i = 1 TO THIS.PageCount
  IF THIS.Pages(i).PageOrder = THIS.ActivePage
    RETURN i
  ENDIF
ENDFOR

As long as you don't resort the pages activepage = activepageindex, but ...
-- Kurt Grassl
Up through VFP 8 SP 1, there is a bug in the Page Frame with .TabStretch set to 0 (multiple rows). If you add or remove pages, or shorten or lengthen page captions at runtime, and this changes the number of tab rows being displayed, the Page Frame's Height will change--BUT the changed value is not readable from Page Frame.Height. Since you can't directly control the number of tab rows on a Page Frame, and you can't reliably predict whether changing the PageCount or page captions will force a change in the number of rows, this means you can't easily determine if the number of rows has changed.

The workaround for this is to position some invisible control below the Page Frame, keep its vertical position relative to the Page Frame constant before and after changing PageCount or captions, and compare its new .Top value to its original .Top value to detect whether the number of tab rows changed.

This bug is FIXED in VFP 9.

-- Ken Dibble
Actually Ken, I'm using VFP 9 SP1 and I still have exactly the same problem, so this bug appears not to be fixed in 9.

I have a situation where I need to keep the pageframe size static, but resize controls on the pages according to the amount that the new tabs have changed the internal page heights by. So I record the height before I start, then check that against the height I have after manipulating the tabs, so I now have a difference for resizing my internal controls - here's an example. I have some employee names that I want to use for each of my tabs in a pageframe:

* take a reading of current height
nHeight = .planEmployeePages.Height

* Adjust page count to no of employess
.PlanEmployeePages.PageCount = Alen(aEmployees,1)

* make all tab captions the employee names
For i = 1 to Alen(aEmployees,1)
   .PlanEmployeePages.Pages(i).Caption = Trim(AEmployees[i,1])
Next

* record the difference
nDifference = .planEmployeePages.Height - nHeight

* Change the pageframe height back to what it was
.planEmployeePages.Height = nHeight

* Later in the code adding a grid to each page ...

* resize according to difference
.addObject("gridevents","gridevents")
With .gridEvents
   .top = 4
   .left = 4
   .height = .height - nDifference
endWith


--- Mick Powell
See Also: Grid Lines On Page Frame
Category VFP Controls
( Topic last updated: 2007.12.10 09:39:02 PM )