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 Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Application main program

Status
Not open for further replies.

Davidp41

Programmer
Sep 17, 2023
16
GB
I have got to the point of building the application for my club producing monthly invoices. I am trying, and failing to find a sample starting program. I seem to remember that I first used the Tastrade example when I first did my only other app but this was probably around thirty years ago.
I remember that it had an Include FoxproH, various Set commands and a READ EVENTS. I would be grateful for a sample to use.
 
Well, it can be as simple as

Code:
DO yourmenu.mpr && generated by genmenu from yourmenu.mnu
READ EVENTS

It would be advisable to have a menu item "Exit/Quit" that does CLEAR EVENTS.

The other most simple main.prg could be
Code:
DO mainform.scx
Especially if the main form is modal it won't need a READ EVENTS, as the prg then will only get after the DO mainform.scx when the user closes that and thereby exits the application.

You can add to that with things like ON ERROR to establish an error handler, ON SHUTDOWN to define the reaction to a) a computer shutdown (so literally a shutdown event) or also b) to clicking the _screen window X button. In the simplest case ON SHUTDOWN QUIT.

then obviously also SET PATH to help the process find any file it needs external from the EXE. You can also program the main.prg with debugging of the development in mind, i.e. after CLEAR EVENTS also clear up things so the IDE itself is in a usable default state again. That indeed is very helpful to have a comfortable starting point for all your testing, too, instead of starting single forms or reports you start a test/development session with your main.prg and have a menu to start forms you currently develop and want to test, etc., which means you include the end-user experience and perspective in your development.

You can do more, it depends really on what you want and need and nobody can tell you. One normal thing is also to start the main form. Maybe you also don't have a menu and only one form, then the user obviously can't start forms from the menu and you need a DO FORM.

There are sample projects, too. Well, for one the solution application in HOME()+"Samples\Solution\Solution.pjx" which has a short and good main.prg sample including to set the default path, which also is a good idea. An error-handling function is defined within the solution.pjx main.prg and set with ON ERROR.

Further PJXes with theirmain.org are in the source code of all the wizards and builders of VFP, the IDE has lots of features that are themselves programmed in VFP, but those projects have no typical main.prg as they build components for the IDE. There is one Wizard though, that produces projects: The application wizard.

If you go through the application wizard, it will create a project based on the FFC (Foxpor foundation classes), but that would have been a route for you if you were at the start of your endeavor, because you could have built a project from scratch with many things already solved, like the main.prg

You find it in the menu tools->Wizard-applicaion wizard but also in the component catalog in the menu Tools-Component Gallery. There pick "Visual FoxPro Catalog" then "Templates" and finally "Applications", then there is the Application Wizard, but also templates for books, contacts and another generic wizard "New application".

They all create projects based on the FFC.

You obviously will need to adapt to your needs. But as said, nobody can tell you your needs. One other thing very typical for an OOP project is generating the application main class goApp. Which may then offer all functionality generally needed by an application like a form handler, a data access foundation, etc.

And then you can program anything into it that you want, a splash screen is one thing not so common anymore, but like always you can do anything you want. You seem to think of the main.prg as a necessity. No, it's just the starting point, so you know this is what executes first. You want our application not to quit immediately, well that mainly needs a form to start and stay open. And that's either a modal form needing to be closed by the user before it ends or a non-modal form plus a READ EVENTS, but you're free to do and establish anything else you want.

It would have been more natural in application development to start with this and not end here.

Chriss
 
There actually are only a few things needed to know about the main.prg

1. It is the starting point of your code. Emphasis on your. There is absolutely nothing that needs to be in there as initilisation for VFP to work, the runtime environment already started, the first line of main.prg already is your line.

2. When main.prg ends, no matter if by a RETURN, a QUIT, a CANCEL or simply by ending, the process ends and the VFP runtime unloads.


And that's it.

Point 2 is the only thing that requires you to put something in main.prg. You can do an empty main.prg, but then your application of course quits. But as already shown above a DO mainform.scx can already be enough, you're not forced to put in a READ EVENTS at all, that requirement has established itself as a "myth", because it's usually the solution to not end main.prg. You could also simply set this SCX Form as the main project item and it also gets started without a DO FORM. It will need to be modal, then.

But starting a normal non-modal form (yes, non-modal and "in top level" forms are the default) will mean VFP continues. That means the form just establishes and then the code after DO FORM picks up and if that means main.prg runs to the end you get the infamous "VFP immediately quits after the main form just shortly blinks".

And that's just lacking knowledge about what a modal form is and what not, also what a top-level form is, and that it by definition is non-modal, even if you set it modal. And there you get the myth. The only viable solution then is a READ EVENTS.

If you run VFP itself and develop the command window is what keeps the IDE from closing. A main.prg that starts a non-modal form means the command window reappears and waits for your input, after the started form is shown and also waits for your input (or other event like mouse usage, but that's also true for the ID menus and toolbars and windows). So during the development, the command window is what makes READ EVENTS optional. In an EXE the command window does not exist, though, that's only part of the IDE, not the EXE runtime. And so without a command window and a READ EVENTS, if you don't have a modal form you immediately end after starting the form.

Well, and anything else like making some settings, establishing error handling, establishing a menu, toolbars or other generally available user interface, all that is optional.

Chriss
 
In very simple terms, the main program should look like this:

Code:
Initialisation
  Set search path
  Create global object
  Set up error handler
  Other configuration settings
  Etc. etc.

Launch main user interface
  This might be menu, or a (modeless) form

[b]READ EVENTS[/b]

Clean up
  Release global object
  Etc. etc.

In addition, the "main user interface" needs to execute CLEAR EVENTS. This should be executed from whatever part of the interface the user uses to signal that they want to close down: typically a menu option or a QUIT button on the main form.

The thing to remember is that CLEAR EVENTS transfers control to the line after the READ EVENTS, that is, the clean up code.

This has been my model for the main program in every VFP application I have written.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
The longer I think about it, the more comes up.

One more mechanism you should know is that at the start of an EXE VFP accepts some command line switches, even if you don't program anything like that in your code.
The help topic How to: Use Command-Line Options When Starting Visual FoxPro tells that

help said:
...or any Visual FoxPro-created .exe file.
At first, it reads as if these switches are only available for VFP9.exe (or other VFP versions), but you inherit them in any EXE you build with VFP.

Then VFP also looks for a config.fpw file at start, see Special Terms for Configuration Files

You cannot only make some settings, but one of the possible entries in such a config file is COMMAND = cVisualFoxProCommand, which also could be a backdoor you want to keep closed, which means you would create a config.fpw file and instead of putting it side to side with the EXE, which would allow editing it and actually making use of that backdoor, you include this file to be compiled into the EXE and put in the option ALLOWEXERNAL OFF to close that backdoor.

You can also learn that you have the option SCREEN = ON | OFF, which reminds me I should have already stated that also an EXE you build will usually show the SCREEN. That is the same main window the VFP IDE also has, (maintained by the system variable _SCREEN). And that would hold the menu you could start in my main.prg sample #1. That's not at all natural for any programming language.

Usually, you define a main form in say a Winformss C# or VB.NET project or in C++ Builder and others. If you go for my sample #2 that will also use this SCREEN and start your form inside of it. The SCREEN is the usual top-level form of a VFP process and that's the main window you expect to show up if you start any EXE in Windows.

If you like, you could say VFP takes this topic from VFP developers, they don't have to specify a main window at all in the main.prg as that's there by default. So that's not even a task you need to do in a VFP project, you always will have the SCREEN and that'll be what a Windows Win32 application Process requires to have a main HWND Windows handle to which the major communication with the Windows OS happens. And closing that HWND mainly closes the process, as with any Windows EXE.

You can decide to override VFPs SCREEN and make your main form such a form class, too. That's done by setting the ShowWindw property of your form to 2, which means "As top-level form". That's the type of Windows in the Windows OS that mainly defines a Windows application. But you could also decide to not do that and even include the line SCREEN=OFF so that the main VFP Window doesn't even show and your main.prg could be code that does something without any user interface.

So let's add these points as 3 and 4. They are not directly only about the main.prg, but about the start of a VFP EXE, so surely important to take this into account.

1. It is the starting point of your code. Emphasis on "your". There is absolutely nothing that needs to be in there as initialization for VFP to work, the runtime environment already started, the first line of main.prg already is your line.

2. When main.prg ends, no matter if by a RETURN, a QUIT, a CANCEL or simply by ending, the process ends and the VFP runtime unloads.

3. Command line switches and a config.fpw side by side or embedded within your EXE can make some settings including topics like foxuser.dbf, language resource DLL used by the VFP runtime and to allow or disallow users to use the config.fpw mechanisms themselves.

4. Your task in main.prg is to either establish a user interface or decide to have a process without a user interface that just does whatever you program and then ends whenever that code finishes (as stated in point 2)

An example of an EXE without a user interface could be, to program something like a mail sender which you then could run from your normal EXE by Run /N sendamail.exe <parameters>. So You could make use of that for parallel running code that doesn't require a user interaction while it's processing, only in advance. And your Windows application could be there for the next thing the user wants to do without needing to wait for the mail sending to finish.

Chriss
 
I would say you have enough input to come up with your own main.prg and if you still have trouble with it, post it and your problem here.

It should have become clear when you need a READ EVENTS and when not.

In itself READ EVENTS is the command that tells VFP "and now wait for events to happen", not just for the first event, but for all further events, until CLEAR EVENTS instructs VFP to stop waiting. So VFP will only execute whatever you code into events like button clicks, etc. This means, READ EVENTS has to come after you establish the user interface. The only other thing to know is that events include what VFP separates from methods, so a button click is an event. That's the whole idea of simplifying programming Windows applications, as you don't need to program all that low-level stuff about the Windowss´message queue, you just program what a button should do when it's clicked into the button click event, the programming language runteim cares for how to detect that. But events of READ EVENTS include more events than those VFP makes programmable for us.

Events meant by READ EVENTS include the VFP runtime reacting to operating system messages sent to an application Window. For a menu that also means events VFP doesn't offer us to program, like the core usage of the keyboard to navigate the menu, that's simply working. Also included are any mouse and keyboard events the OS and the VFP runtime simply handle. In some of them you have a hook, like the KeyPress event, but you, fortunately, don't have to program something so keyboard input becomes the text/value of a textbox, for example, that's all automatic. All that is under the hood of the READ EVENTS. Not that this was necessary to program in legacy VFP or in C or C++, but just to explain how many things are meant by events.

CLEAR EVENTS is the counterpart that tells VFP to not wait for and process events anymore and to continue after READ EVENTS. Multiple READ EVENTS make no sense, one would just replace the other, by the way. I say that because for legacy FoxPro code there also are wait states caused by the simpler READ command, which was there to only wait for the input of a single input/textbox, for example, so legacy code often was meant to control all the single steps of the workflow a user has through a screen from one input to the next. In VFP all READs are unnecessary and are subsumed into the one READ EVENTS. The form elements and even multiple forms become usable in parallel. And a modal form actually does the same, There's a bit more to it than READ EVENTS, though, there is a control and limitation built into a modal state, as a modal form hinders usage of anything outside the form, with the exception of anything that's not the same application, though. A non-modal form in combination with READ EVENTS, and then also further non-modal forms, if your application offers to start multiple forms, means you allow the user a lot of parallel usage and that's mainly improving the usability, though some also like the strict forcing of all the detail interactions one step after the other. The whole concept of Windows is the parallelism of multiple application windows, also for interactions with drag&drop, clipboard and more. That's also why Mike has a point about using modeless forms in conjunction with READ EVENTS, I don't speak up against that. Overall it has a lot of advantages of empowering users to make parallel usage of multiple modeless forms. I just wrote this to explain the mechanism of READ/CLEAR EVENTS.

Chriss
 
Thanks to you both. I hope that I can manage noe.
David
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top