Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Get Name of Selected Page on PageFrame

Status
Not open for further replies.

stanlyn

Programmer
Sep 3, 2003
945
US
Hi,

VFP9

I need to get the name of the selected page on a pageframe. I know that the pageframe has a ActivePage property that holds the number for the active page. There is no corresponding page property that indicates that it is selected or active. I need the page.name so I can do things with it and I do not see any property that gives me that info.

How would this be best achieved?

Thanks,
Stanley

 
The pageframe object has a Pages[] array to hold references to its pages. So, pageFrame.Pages[pageFrame.ActivePage].Name gets you the name of the active page in pageframe.
 
Stanley, are you sure you mean the name of the page (which is usually Page1, Page2, .....)? Or do you mean the caption (that is, the text that appears in the tab)?

If the latter, it is similar to what Antlope said, but you access the approptiate property:

[tt] pageFrame.Pages[pageFrame.ActivePage].Caption[/tt]

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Well, it's not that simple, addressing the pages array with Activepage as index only works, if you never changed page order (literally PageX.PageOrder).

For the general case ActivePage is not like Recno the invariant page number, but the PageOrder of the active page. Or vice versa, if you set Pageframe.ActivePage = 3 you activate the 3rd page in the pages visible order, not necessarily page3 or pages[3], which also is what you usually intend to do, so it never occurs to you there is something wrong with ActivePage activating an unexpected page. This feature also makes it simple to retrofit a new page into a pageframe, which you don't want to appear as last page but somewhere else, perhaps even as a new starting page.

You can get the page N in pageorder by iterating the pages array and finding the page, where [tt]Page.PageOrder = Pageframe.ActivePage[/tt].

To have a simple access, you could let each Page store itself (THIS) into a pageframe property, eg set [tt]THIS.PARENT.oActivePage = THIS[/tt] within the [tt]Activate[/tt] Event. You need your own pageframe class for this, to be able to create a new property oActivePage. And better yet also have your own page class to have this Activate Event code and not need to write it into every new page you add in the form designer. The key to that is to set the pageframe.MemberClass and MemberClassLibrary properties, so every page is not the native base pase class, but yours.

Oh, and not to miss telling the simplest case, if you need the active page name or caption in the code of the page itself, that's simply [tt]This.Name[/tt] or [tt]This.Caption[/tt], and within controls on the page, one parent level up: [tt]This.Parent.Name[/tt] and [tt]This.Parent.Caption[/tt].

Bye, Olaf.
 
Another rather tricky thing you may use:

Code:
LOCAL lnTop, lnLeft, loPage, loActivePage

#Define cnBorderWidth    SYSMETRIC(3)
#Define cnBorderHeight   SYSMETRIC(4)
#Define cnTitlebarHeight SYSMETRIC(9)

loPage = THISFORM.Pageframe1.Pages(1)

lnTop  = OBJTOCLIENT(thisform,1)+OBJTOCLIENT(loPage,1)+cnBorderHeight+cnTitlebarHeight
lnLeft = OBJTOCLIENT(thisform,2)+OBJTOCLIENT(loPage,2)+cnBorderWidth 

loActivePage = SYS(1270, lnLeft, lnTop)

IF VarType(loActivePage)="O"
   IF loActivePage.Baseclass = "Page"
      MESSAGEBOX("Currently active page is "+ loActivePage.Name+":"+loActivePage.Caption)
   ELSE
      MESSAGEBOX("MloActivepage Baseclass is not a page, please adjust lnLeft, lnTop positioning")
   ENDIF 
ENDIF

With the SYSMETRIC sizes it does take different Wiondows Versions, Themes and styles into account, but you should nevertheless thoroughly test, whether this gives you the correct page object. The whole thing is based on SYS(1270,x,y) returning an object reference for the object under that position. The lnLeft,lnTop position should be the upper left pixel of a page, so there should be no control you put exactly into that corner, leave a margin to the leftmost uppermost control of all pages. I have only tried under Win10, you might get different results, therefore the secondary message telling you SYS(1270) didn't result in a page object, most probably you then got the pageframe object with the coordinates too far up or the form with the coordinates left of the pageframe

Surely not the simplest approach to get the active page object, even iterating the pages array has less code, but SYS(1270) can become quite useful, eg while you debug a form simply hover the mouse over a form or any object of interest and execute o = SYS(1270) in the command window without coordinate parameters and you get the object under the mouse. Then add "o" to the watch window of the debugger and you can inspect properties and drill down the whole objects tree of sub objects.

Bye, Olaf.
 
Hi,

Mike said:
Stanley, are you sure you mean the name of the page (which is usually Page1, Page2
I need the name of the page so I can set properties and call methods on that page. Having the caption will NOT allow me to access the page's pems'. Having the page's name such as thisform.pageframe1.page3.xx allows full control over it.

If the fox team had only gave us a selectedpage property for the pageframe, then we could easily do
thisform.pageframe1.selectedpage.backcolor=whatever

Thanks atlopes, as your suggestion works for what I need... I still think a pageframe.SelectedPage property would be simpler without iterating through the array looking for the activepage.

What I'm building is a tabbed interface for vfpusing a pageframe with pages as tabs. I need to create them at will and remove the selected one at will. This behavior messes us the pageorder whereas a deleted page3 would place page4 into page3's old position. To delete the selected page I need to change the order of it by placing it at the end and then set pageframe.pagecount = pageframe.pagecout-1. Now once a page has been deleted, the remaining pages are out of order and now there is no page3 and page4 is in page3's old position. For this reason, I need to get the page's actual name. The closing tab X is on the right side of the image where it closes the selected tab/page. Here is the image...

Picture0003_pfxiyb.png


Thanks, Stanley
 
Hi,

Olaf said:
For the general case ActivePage is not like Recno the invariant page number, but the PageOrder of the active page. Or vice versa, if you set Pageframe.ActivePage = 3 you activate the 3rd page in the pages visible order, not necessarily page3 or pages[3]

Yes, this explains the behavior was getting which is NOT wanted behavior, so it looks as if atlopes solution will not work, but I will test it first.

Thanks,
Stanley
 
stanlyn said:
If the fox team had only gave us a selectedpage property for the pageframe

You can always create your own new Form Property "SelectedPage" and write the Page Caption into it on the Tab Page Click method (or any other method used to change to a different Tab Page).

Then, whenever you needed it you could always access it as ThisForm.SelectedPage.

Good Luck,
JRB-Bldr

 
You don't need the name of the page to access it. Olaf showed you how to use the ActivePage property to get an object reference to the active page.

Tamar
 
Yes JR, you are right and I know how to do that. I'm lazy and thought SelectedPage makes sense and should have been included natively. It probably would have been if VFP could have lived a little longer...

Sorry for not updating this thread as "finished and working as expected". Below is the "close selected button" code...

Code:
With Thisform.pf1
	If .ActivePage = 1 .Or. .ActivePage = .PageCount
	Else
		Do Case
			Case .Pages(2).PageOrder = .ActivePage
				dd = '.Pages(2).PageOrder = ' + Alltrim(Str(.PageCount))

			Case .Pages(3).PageOrder = .ActivePage
				dd = '.Pages(3).PageOrder = ' + Alltrim(Str(.PageCount))

			Case .Pages(4).PageOrder = .ActivePage
				dd = '.Pages(4).PageOrder = ' + Alltrim(Str(.PageCount))

			Case .Pages(5).PageOrder = .ActivePage
				dd = '.Pages(5).PageOrder = ' + Alltrim(Str(.PageCount))

			Case .Pages(6).PageOrder = .ActivePage
				dd = '.Pages(6).PageOrder = ' + Alltrim(Str(.PageCount))

			Case .Pages(7).PageOrder = .ActivePage
				dd = '.Pages(7).PageOrder = ' + Alltrim(Str(.PageCount))

			Case .Pages(8).PageOrder = .ActivePage
				dd = '.Pages(8).PageOrder = ' + Alltrim(Str(.PageCount))
		Endcase

		&dd
		.PageCount = .PageCount - 1
	Endif
Endwith

And yes, I know I can shorten it by using an array and iterating it, but this is "proof of concept" code and I will rework once completed.

Thanks,
Stanley

 
Stanley said:
I can shorten it by using an array and iterating it
You already have the PAges array, all you need is a counter
Code:
LOCAL lnPage 
With Thisform.pf1
   FOR lnPage= 1 To .PageCount
       IF .Pages(lnPage).PageOrder = .ActivePage
          .Pages(lnPage).PageOrder = .PageCount
          .PageCount=.PageCount-1
          Exit
       Endif
   ENDFOR
EndWith
No need for macro substitution, why so complicated, Stanlyn?
And I also told you already that and how you could add the SelectedPage property yourself.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top