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!

FoxPro button status

mmerlinn

Programmer
May 20, 2005
739
6
18
US
Is there a way in FP (and maybe VFP) to test the status of a push button, that is to return whether a button is ENABLED or DISABLED?
 
mmerlin,
This is a case where (and you did say FP2.6 - VFP, I just haven't had a chance to respond to this yet).
As many have pointed out the key difference between FP2.x and VFP is object orientation.
What is of course, cool, about FP though is that it has some of those "pre-cursors" to OOP, and that it has an EVENT MODEL.
So when you have something like READ EVENTS (and I'm going back almost 30 years here... I haven't thought about this in a long time, but still have some bits I maintain), that READ EVENTS is a loop that continues until you get to CLEAR READ if I recall correctly.

So, the way you can control this in FP2.6 is to have (usually) a global variable (don't beat me up everyone), that once you initiate "editing" you set some value like M.Editing = .T.
You keep this state until you're not editing any longer, when you do something like click a SAVE or CANCEL button, where you set M.Editing = .F.

REFERSH() is still a call we make A LOT in FP2.x. (And even at FP2.x)

On the Button's VALID clause, you can sate
*
IF M.Editing
MYBUTTON = DISABLED
ELSE
MYBUTTON = ENABLED
ENDIF

I believe the button has an m.memoryvariable to identify it, but I could be wrong, it's been a LOOOONG time since I had to do one of these, and the machine I'm on at the moment only has VFP applications on it, I'm not in my office where the archive for the old FOX apps are.
 
It's not really plausible to me, though, why you could create a button rendered disabled, to not have anything that could enable it but removing it and replacing it with a new enabled button. The only justification for a disabled button is to show there is a way to enable it. The only reason a button stays disabled for a user not having permissions to ever use the button is envy on users with higher priviledges :^). Well, seriously, it would only tell such a restricted user there is a feature to be unlocked, be it with added/highered permissions or an upgraded license.

So I can understand how mmerlin has this question, because disabled buttons in a UI have very limited purpose when they can't be enabled, don't they?

It's plausible if there is another way to set a disabled buttton enabled somehow.

There's this line in the help:
To disable a single push button, place two backslashes (\\) before the button's prompt.
So maybe when that's used you could change the prompt to the same without \\ prefix and enable a button that way. The question now is how to change a button prompt or make it dynamically depend on a variable you can change.

The only other area of VFP where prompts ring a bell to me are menu item prompts and isn't there a way to change a menu item prompt without redefinig the item?
 
Chris,
That's fine for VFP, but that option didn't exist for FP2.6.
You couldn't hide objects on the form. Buttons have a minimal set of "Events" and being enabled or disabled is one of them.
There's no OOP in FP2.6. Buttons are a special "object" in the environment, which had (If I recall correctly), 4 events associated with them. VALID, WHEN, READ, and CLEAR? (Sorry it's been ages). We had to do things like DO SCATTERVARS, DO SHOWGETS in order to "refresh" the form.
But the button did respond to a mouse click, but that was really controlled by VALID there wasn't a "click" event.
In any case, Object.Property.property doesn't exist in FP2.6.
 
I already got aware of that, I think in the abilities of the help topic for lkegacy@...GET and prompts being prefixed \\ to disable a button. If you could make a prompt be a variable that changes, when the variable changes, you could use that to en/dis-able the button, but I doubt that's available. Perhaps a function that retuns the prompt with or without \\ prefix? I doubt that works, too, as you have no event that would call that function at specific times. So I guess the prompt is as given with the @...GET command and can't dynamically change, unless there' s some SYS() or SET command. But how would you refer to which button? It would need a name or any identifier and I don't see anything like that, the only thing you have is the button number from the nummber of prompts, but then you'd still need to somehow address the button number of which @...GET command button group. I don't see how it could work, so it seems Joes solution is the only way to get there.

Or switch to VFP. Of course that's not available on a Mac.
 
Hi Chris, like I mentioned, the ability to enable/disable a button exists in FP2.6, but the ability to Hide/Show the button (Visible = .T./Visible = .F.) does not.
You set up a control variable in the screen (it still uses .SCX) (called screens instead of "forms") which holds a "global" variable. I always called mine M.EDITING. I'd then check the status of that variable (it would initially be set to .F.) If M.EDITING is False, then the "Edit" button would be enabled, but the "Save" button would be Disabled, because there is nothing to "save". Once you click "Edit" the first thing it would do would be to change the "state" (status) of the form to M.EDITING = .T. One of the last bits of code that would be executed in the "Snippet" would be a call to DO SHOWGETS (which was a routine much like the code you'd use in the "Refresh" event. FP2.6 essentially has Methods, but not Events (or at least the Event model is fixed by the READ EVENTS).
So you have some control, and FP2.6 would "grey out" your disabled buttons. IN FPW2.6 you can still give it a picture clause to determine what image is shown based on the state. You couldn't do this in FPD2.6 though.
Surprisingly the "leap" is there, but because FP2.6 had implemented a limited event model, (It was "Event Driven") The VALID and WHEN clauses where key to program flow, unlike (exactly like) they are in VFP, but in VFP we rarely use them because there are better events, for other than "rejecting" entry to the object.
Man, this is REALLY making me think back. :)
 
but the ability to Hide/Show the button (Visible = .T./Visible = .F.) does not.
I didn't talk about hiding or showing buttons. I don't know where you have your eyes, Scott, I quoted the lagacy help expliitly mentioning how you can enable/disable (that's not showing/hiding) Buttons done with @...GET by setting prompts (that's captions, I think) with \\ prefix or not:

To disable a single push button, place two backslashes (\\) before the button's prompt.
I think you can only set the prompt when issuing the command, it can't be dynamic. Maybe you can, but mmerlin should know that better than me.

I appreciate your mentioning of DO SHOWGETS, maybe that can be used to also refresh the prompts, I don't see how, though and what triggers it.
 
Hi Chris,
I recall the \\ but I don't remember exactly how that was implemented. I'm still not in the office that has all my legacy FP code on it, and an environment I can run it it to see how it works. >< Thinking about it, I think you could set the default value of a button's keyboard command with a \ or might have been \< (all from memory, I don't have the Helpfile for FP on me either), but one of those would do that so that if you wanted "Edit" for example to have a keyboard shortcut of "d" the label would be set as "E\dit" or "E\<dit" there was some "shortcut" for this, which \\ was part of. But for VFP I think they moved that to text processing so it would not be backward compatible any longer. (I know that's not a goal, just having a bit of mental fun moment remembering all this).

As I mentioned, there is a limited event model. There isn't a "Refresh" method/event, so at the end of any updating or change at a field level, that could impact how other data is displayed, your own routine would need to be called (since functions/procedures are supported, even a the form level). So you'd call something like a "DO SHOWGETS" where you'd build a procedure into the form (every form would then have one, and it was unique to that form), where you would update the behavior. And as I mentioned, buttons have a variable like M.EDITBUTTON, you can then set that to .T. or .F. making it enabled or disabled.
I'm not sure where it would be desired do always have a button disabled, as the \\ would seem to indicate that... how would that value if its embedded (assuming) in the button's definition ever get changed?

Polymorphism doesn't exist in FP2.6.
 
Scott,

To disable a single push button, place two backslashes (\\) before the button's prompt.
That comes from the help. And it's the third time I post this, you're not noticing much.
 
Last edited:
Yes, I know it came from the help file. I did read it 3 times. Just didn't think it needed to be mentioned, since, as you said, it came from the help file.
What I was trying to recall, is how that actually works.
 
It works with the setting of the prompts that you have to provide with the @...GET command to create push buttons. I have linked to the help topic about that, it has the full syntax description, if you can't read that, I don't know how to better illustrate it. The problem is not setting the prompts while you create the buttons, but to change them later. Because there is nothing as obvious as in the object model of controls like a cption or prompt property.

The small event model and the Refresh like event you mentioned might help with that and I think mmerlin could figure that out, as he's knowing legacy FoxPro much better than anyone of us. On the other side there's nothing from the persepctive of VFP that could help you, mmerlin, I think. In VFP everything on a form is an object and can be addressed, properties can be set and changed, it's simple to do that, in legacy screeens it seems to me you have to just clear out controls you need in another state and recreate them in the new state rather than cahging their state. If that's possible you'd need to be the one explaining that to non legacy FP developers.
 
Last edited:
Back to mmerlin's original proposition, is there a way to get the "state" of an Enabled/Disabled button on a screen.

For future help, regarding not providing a version to get a broader view of results, a lot of times that is a reasonable approach. But in this case, because FP is so different to VFP especially in overall flexibility, specifying the version would reduce some of the confusion in the question. I will be "back" with my code base and an install of FP that I have running in another machine, so I can better address this question.

As an extension to just checking it's state, I do recall "hiding" buttons in the past, but I don't recall what trickery was applied in order to do so. Suffice to say, it changed significantly between FP and VFP.
I need to actually open an FP screen and see where code exists and what it does. But my sense is, this is controlled through a memory variable that you set and then manipulate. So it can be done, but it's not "baked into" the button control itself.

(Note intentional non-use of OOP terminology in this post... screen, and control which was the terminology used in FP, as opposed to Form and Object).
 
Hi mmerlin,
I found some "old code" in a screen that I have (since I don't have FP installed on this laptop I'm working from, I remembered I can open the screen as a DBF, so I did).

I found that in one of my "DO SHOWGETS" procedures (which is part of the screen codec that can be called at any time while processing, just like a "Refersh()" in fact, if one really wanted, you could create the function "REFRESH" the same way, if you want to seem in line with VFP code.
The key is, I found this bit of code, which is impacting the buttons on my screen:
Code:
...
PROCEDURE SHOWGETS
*
IF M.EDITING OR M.ADDING  && If either of these are true .T.
*
    SHOW GET M.SAVERECORD ENABLE
    SHOW GET M.CANCEL ENABLE    
    SHOW GET M.NEWRECORD DISABLE
    SHOW GET M.EDITRECORD DISABLE
    SHOW GET M.QUITSCREEN DISABLE
    SHOW GET M.CONTROLPOS DISABLE
*
        IF NOT DELETED()
            SHOW GET M.DELRECORD,1 PROMPT '\<Delete' DISABLE
        ELSE
            SHOW GET M.DELRECORD,1 PROMPT '\<Recall' DISABLE
        ENDIF
ELSE    && User is in Browse mode... Both are False .F.
*
    SHOW GET M.SAVERECORD DISABLE
    SHOW GET M.CANCEL DISABLE
    SHOW GET M.QUITSCREEN ENABLE
    IF DELETED()
        SHOW GET M.EDITRECORD DISABLED
    ELSE
        SHOW GET M.EDITRECORD ENABLE
    ENDIF
    SHOW GET M.NEWRECORD ENABLE
    SHOW GET M.CONTROLPOS ENABLE
    SHOW GET M.COPYRECORD ENABLE
*
    IF NOT DELETED()
        SHOW GET M.DELRECORD,1 PROMPT '\<Delete' ENABLE
    ELSE
        SHOW GET M.DELRECORD,1 PROMPT '\<Recall' ENABLE
    ENDIF
*    
ENDIF
*
So I have a REGIONAL variable defined in the screen code that sets M.EDITING = .F. and M.ADDING = .F.
Note that what we monitor is not the state of the button, rather the state of a variable. So you could always check for the state of the record you are looking at at the moment. While the fields being viewed should be memory variable from the database populated with SCATTER MEMVAR <MEMO> if you have a MEMO field.
Now since I can't test it at the moment, you should be able to test the value of the button's memory variable as well. Looking at this code the M.DELRECORD,1 suggests that this may be an array. Where the Array,1 holds the PROMPT for the button. (I am guessing, like I mentioned I don't have FP in front of me at the moment). It may be able to check another element of the array like ,2 to see if it holds a value that make the button ENABLED/DISABLED.
Prompts can be changed interactively as this code demonstrates, so some limited form of Polymorphism is supported, but not in a traditional "OOP" way, just a method of overloading a button, and it's keyboard shortcut.
Sorry, I'll dig more into this probably on Sunday when I'm back in front of that machine. You've got me really curious about this now, I feel like I know this answer, but it's buried deep.
 
mmerlin,
Don't know if you are still here as this thread has gotten unnecessarily long, but if you've made your way to page 2, I can now shed some light on this.

I am assuming you are using the screen builder within the IDE of FoxPro for Windows. When you "build" the app, what it actually does is create a .SPR file, which is the "code" that the screen builder generates. You will notice a lot of funky _0s346SDly type function in the file if you open it and read it. These are the "Clauses" that Fox generates for each of the "events" that it supports. As I mentioned, Fox.2x supports a limited "Event driven" model, which also supports limited "properties", but these properties aren't managed in the same way in Fox2.x as they are in VFP, hence you can't just "query" the state of the "Visible" property or the "Enabled" property, because it really is a kind of "trickery" that is performed to give the illusion that these states exist.

NOW, that said, you have the opportunity to "take control" of some of these, and it just so happens that Enabled/Disabled is one such opportunity.
In the screen's "Layout" under "Options" there is a button called "Code". This allows you to create functions that you can call yourself. So you can create a variable for the button you want to test against, let's call it M.EDITSTATE = "ENABLED" you then create a routine that I call SHOWGETS and in that code you place in the "CLEANUP and PROCEDURES section under the "Screen Code" button, you can create a PROCEDURE called SHOWGETS. (You could call it REFRESH if you wanted to, because it's here that you control the state of everything).
Now if you Click the EDIT button, (In the Edit button's Valid, it's equivalent to what happens when you "CLICK" the button/object) it will run the code you want. Here you change the state now, if you've clicked the EDIT button you don't want it to be enabled any longer. The first thing you do is you change "M.EDITSTATE" to M.EDITSTATE = "DISABLED".

In the SHOWGETS procedure now you do this:

SHOW GET M.EDITBUTON = &EDITSTATE

Now when your screen compiles, it will automatically put in "DISABLED" or "ENABLED" depending on the state of the M.EDITSTATE value.
You can then TEST M.EDITSTATE at ANY time anywhere in your code to understand what it is. (I would create in #SECTION 1 REGIONAL M.EDITSTATE so you scope the variable.
So you can take control of testing that state at any time, to know if it's enabled or disabled. This is true of any "object" on your screen. A Field, a Button, but you have to be responsible for the variable (property) of the object.. And if you use good naming convention you can make this common for all your objects.

Note it IS also to have an "INVISIBLE" button. This is a separate type, though the builder treats them the same. The trouble here is, this is one of the things that is built by the compiler. So if you wanted to make it dynamic, you'd have to take control of the code AFTER it is built. Here is an example where I have an "EDIT" button that is invisible:
1727026917494.png

I've defined it as "Invisible" in for screen (by setting the Type radio button to "Invisible". Not that the Picture clause then is PICTURE "@*IHN "
Interestingly, the Help file is NOT helpful here, as it doesn't mention the specialized value in the picture clause "I" to be INVISIBLE. (For text it is "Italic", but that's not in the picture clause).
Since "Style" is imbedded in the definition of the @ GET, you can't control it in code in the SHOWGETS, as you'll note in the snippet above, the _6fo03c0i0() reference is one of those generated values I mentioned. But you can modify this code and recompile the .SPR

You could create something like M.EDITVISIBLE = "@*HN "
And when you want to make it invisible you change that value to "@*IHN", replace the PICTURE clause with &EDITVISIBLE and you could then dynamically turn the button on or off programmatically even in FP2.x. HOWEVER, make sure you DISABLE it as well, because an invisible button that is ENABLED can still be clicked!

It will take some work, but what you want to do can be done, if you take responsibility for the control of it.
 

Part and Inventory Search

Sponsor

Back
Top