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!

What are the alternates for DEFINE WINDOW in forms? 3

Status
Not open for further replies.

Venkatvc

Programmer
Dec 18, 2019
24
IN
Hello guys,

I'm back with a question again.

My client has a History Sheet of vehicles admitted in his garage. (The garage is a Government owned, so their style of working is little different.)

I need to show them the History if they input the vehicle Number.

For example:
If they input the vehicle number as MX 11B 18356 I have to show them two windows, one window showing the names of officers who have used from time to time, and the other window showing the repairs carried out to the vehicle from time to time.​

I have seen the option 'Microsoft Rich Text Box', but it looks that the source should be a memo field or a file only. (I have browsed some topics and understood that way.) But, the data I have to display is a collection of fields from a table and various records. (Simply saying, the vehicle might have been used by only one person in its entire life or might have been used by more than 4 or 5 officers in it's life. I need to fetch it and display as a paragraph. Also I need to show the current owner as Bold or highlighted text.)

Previously in DOS version, I used to define windows and manage this situation. Now, is there any option for me in VFP 9?

-------------
Looking for knowledge from anyone, anywhere.
 
You seem to be asking some different questions here.

First, where we used DEFINE WINDOW in old versions of FoxPro, we would now normally use a pageframe. Place a pageframe on your main form, and use each page to host the controls relating to a different aspect of the main subject of the form. In this case, that would be the names of the officers and the record of the repairs.

This has got nothing to do with the rich text box. That is basically a way of displaying free-form text with a variety of formatting, such as bold, italic, different fonts and colours, etc.

If you want to display the officer names and the repair records in a compact form, the obvious way to do that would be to use grids. Each row of the grid would correspond to one officer or repair, and the user would be able to scroll vertically to see them all.

However, if a grid is too rigid a design for you, and you want the data to appear as free-flowing text, the easiest way to do that is with an editbox. But the disadvantage is that, within a given editbox, all the text has to have the same formatting (fonts, colours, etc.) If that's no good for you, then you can either use the rich text box, or, better, a web browser control. But both those options are complicated, and both will take more programming.

I suggest you get the basic shape of the form sorted first, and then come back to question of how to show formatted text - if that is indeed what you want to do.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I need to show the current owner as Bold or highlighted text

I just noticed that part of your question.

If you use a grid to show the owners, it's easy to highlight the current owner - assuming, of course, the data is available to indicate which owner is current. Take a look at the Dynamicxxx properties, such as DynamicFontBold, DynamicForeColor, etc. (these are properties of the grid's columns).

Having read your question again, I'm fairly convinced that a grid would be your best solution. Or, rather, two grids: one for the history and one for the officers. Putting each grid on a separate page of the pageframe would make the whole thing look less cluttered.

Mikd

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
As define window actually creates a form, the 1:1 technical equivalent would be a form. Since you only use a window area for displaying info this doesn't give it a full-blown form character with title bar min/max/close buttons etc. And the equivalent to a rectangle, which could contain anything, just like a form canvas, is a container.

Mike has suggested Pageframe and Grid. And they are also natural solutions for different cases. A pageframe itself especially gives it a place on the form used with multiple layers, the pages, each accessible by a tab. It's not unusual to turn off tabs and then only programmatically switch between pages. Since VFP8 (I think) you also have the page class, which rather compares to a container, albeit it's only able to become a member of a pageframe, while you can use a container anywhere a control is usable (this includes containers can be part of containers). Before we had the page member class the solution was to use containers you added to empty pages, so composing a pageframe of varying pages at runtime is possible simply ba using the pageframe as empty structure only and after incrementing the pagecount simply add a container object for whatever specific record to display. So you design a container for a set of fields and can use it repeatedly on pages of a pageframe. Of course, if a container is small enough, it may also fit on the form directly multiple times, for example, I did a form with label previews of several label types with and without barcodes on the basis of containers.

And then, last not least, the container as template window will seem like a subform (of you know MS Access) when you use a grid with a single column and add that control to column1 and set currentcontrol to that container. Mike has not talked of that usage of a grid, he rather thought you use the usual columns for displaying records and could use their properties like DynamicFontBold.

Anyway, it would also be a strange first usage of a grid not using its usual multiple columns and textboxes for the cells. like you know from the browse.

Using a container in the only grid column you throw away grid data binding, ie the binding of column1.controlsource has no target control, when column1's active control is a container, as a container has no controlsource and value properties. And this also doesn't mean the column binding is inherited to the control with taborder1 in the container. No instead you'd need to use the data binding of the individual controls to do the data binding. The grid will still need a datasource anyway, as you only get a row = a container per record of the grids recordsource workarea.

Overall, especially if you don't compose your output very individially with @say and positions, but have qa usual record schema of a control per field you can desigm a record form but for usage within a form better a container. That's always the basis for something inside some rectangle: Protip: Just have a basecontainer class that you set to borderwith 0 and transparent, so the container itself has no visual impact and only is the rectangle of whatever you design into it.

For most ease of designing a record container you can first create an SCX form, use its data environment to add the relevant tables, then add the fields you want to bind to one by one, so the form desinger creates a label+textbox for char and int fields, editbox for memos, etc. and then finally select the controls and use "Save as class" with the option "Selected controls". Thios creaets a container class with these controls and the data binding already in place. Whenever you later use that container on a form or page of a pageframe or column of a grid, the only prerequisite is, of course, this table has to be a used workarea for the data binding to work.

You can of course also create controls and code to binding yourself. The drag&drop method for example does not create comboboxes when you drag in a foreign key field from a table, th drag&drop mechanism only orients irself on the data type. Which control it adds to a form is defined in Tools-> options dialgo->Field mapping tab.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Also, always remember that many times customers will tell you do things a certain way simply because they don't understand the alternatives. Don't be afraid to suggest a different way, ESPECIALLY if you are going from DOS to Windows! For example, you could still give them different screens as they currently have, and if their screen resolution is high enough you could keep them all active at the same time and just change the data on the 'child' screens as needed. Or any number of different ways. Do not be afraid to suggest a different way especially if it will make your and their life easier - in fact, it is your duty as a good programmer.
 
Thank you Mike and Olaf.

Looks like I have to learn lot. Pageframe is not my option at least here. Either grid or container looks to be the choice.

I wish to display the Officers' list and the history of repairs in two square boxes side by side. Since the user has nothing to input there than scrolling up and down, I have to see which one could be more easy for the client. (Most of the time the user even won't look at what's displayed there, but in case if he wants to, he should be able to.)

The thing is the list of owners should not look like a table, but a paragraph. What comes to my mind is I'll have two edit boxes one below one closely aligned (one for the past owners and one for the present owner). By this way I can format the name of the present owner bold or highlighted or whatever.

The other data (history of repairs) can be a grid or even just a container with a table 'browse noedit nodelete noappend' option filtered for that particule vehicle, because the entire history is in a single table.

The biggest challenge for me in this project is I have to train an automobile mechanic who is just used to keyboard while using PC. For him, ENTER key should terminate the input of a field and up / down arrow keys should scroll. He is so used to the DOS version of this project.

Slowly I am training him to use the TAB key to terminate from a field. MOUSE?? aaahhhh... (Slowly he moves the pointer to the button, and... and.. when clicking moves the pointer way off.)

-------------
Looking for knowledge from anyone, anywhere.
 
@TheProgrammerGuy

Thanks for your suggestions.

Not only the client, I myself am new to VFP switching from DOS version. I am learning and developing a project as well.

-------------
Looking for knowledge from anyone, anywhere.
 
In that case, you should quickly learn about the VFP Classes and how to use them to your advantage. Even if you don't think you will be changing any of them, you should always make your own copies because you WILL change many of them. :) And even if you don't, no harm done by masking your own copies.
 
A grid is the natural choice for something scrolling. You can turn off gridlines and then the main grid looks like an editbox, you still have lines and can choose to make one (current) owner font via DynamicFontBold, for example. It's not possible in an editbox, unless you use one editbox per owner. You can remove a lot of borders and let several controls look like one rectangle, but it's actually not the style of a visual Windows application to look like a DOS screen.

If you want to, then still don't use many editboxes or textboxes, use a grid for anything more complex repeating, since you have more options for the visual appearance there than with anything else, scrollbar is automatically included. It's actually hard to use a standalone scrollbar, even when you use an OLE scrollbar, you still need to program some shifting of controls then, that's all automatic in a grid.

Otherwise, the natural choice for lists of course is a listbox, but you hgave less options for the visual appearance of items. You could misuse the disableditem look but, well, it's misused then and a hack, the grid offers you a per cell styling if youÄd want to go as far. With backcolor, font, current control, font styles, etc. Only not per word, for that the RTF control would work best, ie when your owner list is just a CSV list on one paragraph, not one owner per line, then an RTF control allows to still just highlight one owner within this text. In theory you can puzzle together single boirderless textbox controls, but you don't generate output like you did in DOS, you compose forms of controls at design time, usually, not at runtime. The @say way of putting data at some position is really a legacy thought of a grid of character positions and the concept really goes back to when DIS fullscreen was only a character grid, just like C64 or IBM PET or older machines had.

I for example, only use the ? for printing on _screen, not on a form. A form canvas could also be used with ?, but a) if you set AllowOutput to .T. and then ? on the active form, you actually overdraw or even shift the controls with the text you'd print, so the form canvas isn't used like that anymore, this is the past, you use controls to display anything, the right control for the data type and in complex list cases usually the grid.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Thank you guys.

I am trying to completely change the project to Windows style, but I try to minimize the need for mouse usage, The user is most likely to be the kind of people I said above, automobile mechanic or petrol pump operator or sometimes security guard.

I was building it using @...say in DOS version, but here it makes move the objects on the form. (Hee.hee. on the first day itself I tried. Before asking here, I also tried to define a window to look as if it's inside the form but the control shifts entirely out from the form.)

The disabled item formatting of a listbox also seems nice, but I have to check whether the width of the item goes beyond the listbox width. As I observed there is no horizontal scroll bar in a listbox.

I have to learn a lot about the grid control. Previously in another form I tried to bind with a table just as a test. I encountered two issues. One was the heading for each column displayed 'column1', 'column2' etc. (Or A,B,C. I don't remember exactly.) The other thing was I couldn't figure out how to change the order of columns.

-------------
Looking for knowledge from anyone, anywhere.
 
You change the column names by editing the properties of the grid and changing them. I think you have to drill down a couple of layers to get to the level of the column headers (you can right click on the grid and choose 'edit' to do this). And while you're there you simply grab a column and move it right or left as you wish.

I remember switching to VFP - I was not a happy camper at first. Programming in DOS was SO easy. It will not be so easy for you for a while :). Luckily, I did it the same as you, while working for a client with bottomless pockets, so they didn't care about the cost. Before you do too much experimenting you really should learn about and understand the basic concepts of Classes, Objects, Properties, etc.

You can still code more or less the same way in VFP, but if you do, you're missing the whole point of it, and probably crippling your program.
 
The default header caption is field names, and that suggests the easiest way to change column order is having your table or cursor fields in the order you want to display them.
And while we're at that, in the usual case you don't want to display an ID of a record, you only want to display relevant columns and so you barely ever list a table you list a query result into a cursor.
And there you simply specify the fields you want in your SQL-Select.

Besides, column order changing is even possible for the user, when you allow moving columns, it's just a mouse drag&drop kind of thing you won't want in a keyboard intensive application. Anyway, I think you want to determine columns. Even if you bind to a table, the grid.recordsource is just the starting point, the root of the binding. Each column has a controlsource and you can specify the field to display there. To have that easier, right click on a grid and start the builder. Then go along that dialog.

The most important thing to know about the grid only is, it takes its recordsource serious if it doesn't exist when it starts displaying data. It goes blank in that case - its column object will be lost. So if the cursor or table specified as recordsource would only be used (opened) or queried later, ie by click of a button, the grid won't get alive and display that workarea then, when it went blank, it also stripes off any controlsource binding. So using the grid means preparing data for its first display at least in form.init.

Many problems are raised by that sensitivity of the grid. The other side of it is, even if you don't preset the recordsource, a grid will simply take the current workarea as its recordsource. You can see that, if you put a table into the dataenvironment of an SCXX form or a USE some.dbf into the form.Load() event, put a grid on the form, don't define anything for it, not even column count and run the form.

So this is very strict from both sides: You don't already have prepared what the grid shoudl bind to according to its recordsource and column controlsources? Then the grid gies blank. You don't specify something, as you want to set this at runtime: The grid just takes what it can get.

There is a simple way out of that, and it's very useful, when you want to start selecting and collecting all the data to display by init parameterization of a form, when the controls already are live objects and the form.init code has everything at hand: The parameterization for queries or parameterized queries or views, the controls to act on. Well, you can, if you set the forms BindControls to .F., then you have no control, that'll be "impatientl".

The next step then is to switch data in grids. A novice error is to simply USE another table and set recoirdsoruce, or query into the same workarea. This again breaks the grid. What works flawless is cursors, that means both views you parameterize and requery and cursors from cursoradapters, they inherit that same nice behavior: They keep the workarea they feed allive. Even just a SELECT x FROM table WHERE &dynamiwhereclausse into cursor (grid.recordsource) causes that workarea to be closed and then used again, the grid will notice and go blank.

It's a strong reason to use no tables as recordsource directly because the solution to that, if you want to avoid going into views and cursoradapters is ZAP in the grid.recordsource and refilling the still constantly used workarea with new data not by SELECT ... INTO CURSOR (grid.recordsource) but by INSERT INTO (groid.recordsource) FROM SELECT...

Well, or go to views and cursoradapters and use REQUERY. I prefer that over complications of query code for grid recordsources. It's also to the point of using databases as intended with SQL and cursoradapters or views are easier to later change to remote database usage, that means SQL Server on the LAN but also MySQL in some cloud or hosted by your domain.

And last not least, once you know that behavior the easiest way even if you only want to display data after the user made some choice, some navigation or search and start empty, then use a query WHERE .F. or simply CREATE CURSOR to have an empty cursor for the grid to start with any use throughout the form session.

Ao, in essence: Don't avoid grids as too complex controls. Nothing gives you better options to list data.
Form.BindControls and views or cursoradapters are the natural nicely behaving data sources for grids, the next best solution is still using cursors and ZAP and repopulate them.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top