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!

Allow a form that was opened, to remember the size it was opened before and when open again to be 5

Status
Not open for further replies.
Jan 20, 2007
237
US
Hi everyone,
as a continue education, would like to know, if it is possible when i have a form, let's called main form and then from there i can call another form to open and if this second form can be resized, is there anything i can do on this lastone to remember it is size, so the next time , i open it, will be shown as previously ?
is there any property or custom code for this to happen, or i will need a form class ?

Thanks a lot in advance
 
Why do you think you need a form class? The proper method to initialize your form position and size is the init method, no matter if it's a class of a vcx, a class in a prg or an SCX, you can always have code in init, that loads previously saved data, including such "metadata" about the form size and position.

It's just data users don't enter but define by moving and resizing the form, but it's still easy to store and load it, as with any data in tables. So what exactly are you struggling with?

Bye, Olaf.

 
We had a similar question a few days ago, in thread184-1784888. That discussion concerned storing the contents of certain controls and restoring them as defaults the next time the form was opened. But it's the same principle as your question.

In fact, all my forms by default save and restore their sizes and positions. There's no specific property or method to do that within VFP, but you can code it yourself fairly easily.

You will need a table to store the relevant information. The table should have the following fields: the name of the form (that is, its Name property, not the SCX name); and the values of its Top, Left, Height and Width. In the Destroy method of your form class, save those details from the current form into the table. If there is already a record in the table with the relevant form name, overwrite it with the new information. Otherwise, append a new record.

In the Init of your form class, search the table for the relevant form name, and set the forms Top, Left, Height and Width accordingly. If there is no record with the relevant form name, open the form with its default size and position (this will happen the first time a user opens a given form). That's all there is to it.

Actually, there are a couple of minor complications. Before setting the form's Top and Left, check to make sure that form will appear within the bounds of the outer VFP window (_SCREEN). If it doesn't, don't restore those properties; instead place the form in the upper left corner. This can happen if the user changes the resolution of their monitor - or moves to a different computer with a different monitor.

Also, add an override switch. In other words, allow specific forms to always open with a default position and size instead of saving and restoring. You probably won't use that very often, but it might come in handy occasionally.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Well, in the other thread I just recommended Hide() and Show(), which only works during a session, but then requires no saving and restoring of information, that was only your recommendation. But taken that way the solution for storing form position and size is similar to storing form control data, yes.

One easy way to store the form properties is given by GATHER NAME THISFORM if the table you prepare has some fields 1:1 named as the properties you want to save and you have selected it and positioned on the record for it, later SCATTER NAME THISFORM ADDITIVE restores the information to the newly started form. ADDITIVE here is needed so SCATTER knows it doesn't need to create a new object, but act on the properties of the specified object already existing, it will also add properties not existing yet, so in that part of the code, you can specify the properties you want to restore. For example, you will not want to have a field called "Name", especially not a char field, as you would then scatter a name with trailing spaces to the form.name, which could cause complications because of trailing spaces, but even if you did add such a field, you could SCATTER... FIELDS Width, Height, Top, Left only. Any char property you would like to save should be saved into varchar fields, for the reason of trailing spaces.

Notice, GATHER NAME Object only looks at first level properties, ao that's not storing anything like thisform.textbox1.value, also it doesn't store objects. If you would like to save some controls values, the solution is by using their controlsource to bind them to table fields, as always.

Bye, Olaf.
 
Hi Landfla,
I use this idea to manage the main window size, but it could easily be applied to others.
I have a table called STARTUP.DBF that has fields WINTOP, WINLEFT, WINHEIGHT, WINWIDTH.
At the start of the .EXE very early call, I open this DBF, read in its values and then use them to set the initial area with:

lnWinPositionTop = STARTUP.WINTOP
lnWinPositionLeft = STARTUP.WINLEFT
lnWinPositionHeight = STARTUP.WINHEIGHT
lnWinPositionWidth = STARTUP.WINWIDTH

I have a single record in my STARTUP.DBF, but what you could do is add a field like "WINDOWNAME" and then every time a window is opened, you could find it's WINDOWNAME and then make it's sizes that of the values in the STARTUP.DBF.

STARTUP is a free table, that you just open and close when you need it, so it's kind of a place I "stash" global variable (without making them PUBLICs). Just use when I need them. Then when the window is closed, at it's DEACTIVATE code, just do something like:

Code:
IF NOT USED("STARTUP")
   SELECT 0
   USE DBFS\STARTUP
   SET ORDER TO WINDOWNAME && sets the index, but you'll need to create that index
ELSE
   SELECT STARTUP
   SET ORDER TO WINDOWNAME
ENDIF
*
SEEK THISFORM.NAME && (be careful to change the DEFAULT value of the name of a form, or they will all be the same)
REPLACE STARTUP.WINTOP with ThisForm.Top
REPLACE STARTUP.WINLEFT with ThisForm.Left
REPLACE STARTUP.WINHEIGHT with ThisForm.Height
REPLACE STARTUP.WINWIDTH with ThisForm.Width
*
SELECT STARTUP
USE


Now this does one thing you haven't mentioned... it also retains WHERE the window is so if you arrange your open windows in a particular way then it will retain that as well. Just make sure you change the default form name, as they will default to something like Form1 or <classname1> and they will all be the same in the STARTUP.DBF, so just make sure they are unique, and this should work fine.


Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Name your fields without the Win Prefix (yes that means using reserved words for field names, but here it's intentional) and then...

...in Destroy (for storing):
Code:
*Code opening the startup table
SEEK Thisform.Name
GATHER NAME Thisform FIELDS Top, Left, Width, Height

...in Init (for restoring):
Code:
*Code opening the startup table
SEEK Thisform.Name
SCATTER FIELDS Top, Left, Width, Height NAME Thisform ADDITIVE

Instead of Form name you could also determine SYS(1271, THISFORM) for SCX forms and use Class and ClassLibrary property values for VCX forms. These are distinct without the need to specify specific Names in the form designer. I agree it's a good thing to give your forms names on the object level, too, not just on the file level, but people are lazy and the project manager also uses this information to list forms and form classes, of course.

Bye, Olaf.
 
Hi Olaf,
I guess I moved away from the "SCATTER/GATHER" strategy when migrating to DBCs and TABLEUPDATE().
I know it can still be used, and there are good use cases for it, at the time (back in VFP5/6 days) it was one of those things that was being pushed to "abandon". But since this is a free table, that doesn't really apply, and probably is a good case for it. So yeah, it makes it a little easier with your example.
-S

Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
The very good case for it is the NAME clause, that's new since VFP9. Working with scatter objects and even gathering and scattering to forms. In this case it's not reverting to outdated ways, it's the most modern way to work on multiple properties in one go. It's actually very near to object-relational mapping (ORM). So no reason to reject it. Just don't mistake it as reverting to the overall SCATTER/GATHER technique that was mostly replaced by the controlsource and tableupdate. form properties are not bindable to data, that's the very reason you do it with code, but then why do all single replaces and assignments when you can scatter/gather, Scott? You're avoiding something out of the wrong reasons. On that matter I could also start to talk about replace vs SQL-Update...

Bye, Olaf.
 
Wow, I didn't realize that. That's something I missed all together. When I stepped "out" of VFP it was around VFP 8, and even by then I was only doing a few things, most of which were rooted in VFP6 with VFP3/5 thinking... Had no idea this difference existed, but I see your point on its usefulness. I'll have to try to remember this for cases that are like this.
-S

Best Regards,
Scott
MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top