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

CLICK EVENT not executing from WAIT 1

Status
Not open for further replies.

timdobie

Programmer
Nov 6, 2013
5
AU
Hi
I have an issue with trying to pause execution and restart it again based on a specific button press.

Here's what's happening.

Part of my code triggers a container to show.
The container slides onto the screen using a timer. [slide('up')]
The container holds 2 command buttons. 'Accept' and 'Decline'
The buttons change the value of a variable (m.confirm_data) when clicked where 'Accept'=1 and 'Decline'=2

The problem is that when you click the mouse the WAIT is cleared and the code begins to execute again as expected
but the 'click' event does not trigger for the command button so the value of m.confirm_data does not change
so the 'if' statement is always false.

Any ideas?

Code:
*some code*

m.confirm_data=0

slide('up')

WAIT ''
*at this point the user clicks either accept or decline. 
*either one will take the code out of wait mode
*but neither buttons click event will be triggered so m.confirm_data will remain as 0

if m.confirm_data=1
    *more code*
endif
 
The click is 'consumed' by the wait.
You can't use WAIT to wait for a click. As it itself waits for a click, and that click then is not forwarded to anything you click on.

Normally you would just use a messagebox with Yes/No buttons.

Bye, Olaf.
 
How about putting *more code* into a separate form method "Accept", then in the accept Button do Thisform.Accept and This.Parent.Visible = .F. (if the accept button parent object is the container), that's all to it.

Bye, Olaf.
 
Using Mikes solution, the Decline Button has to set m.confirm_data too, to a value other than 0 and of course another value than 1, eg -1, otherwise you will only exit the WHILE loop with an Accept.

Bye, Olaf.
 
Forget about it, you already said Decline sets it to 2, so that would work. I still would rather separate the accept code (and maybe also Decline code) into their own methods, that's what methods are for, to separate the different tasks to do and have an easier codeflow than with such a waiting while loop. This is an unnatural construct reimplementing a kind of read events.

Besides that I think you won't be able to assign 1 or 2 in accept or decline button to same the m.confirm_data variable you create in your code above. A private variable will be available down the callstack, but not down the parent/child object "stack". Making that a public variable is no good choice, but a form or container property would be addressable from your calling code and the buttons in the container.

Last not least to separate the code into one or two more methods relieves you of the variable, the code flow will make it more natural, don't you think?

You have a click event and you specify what happens, if the user clicks in there, eg you make a call Thisform.Accept(). If you just set a variable or property to 1, future developers looking inside the button will not find out by merely looking at it's click code what it causes, they only see a variable is set to 1. This is not well designed, therefore.

If you use a variable because you use the Accept/Decline container for many occasions doing many different things, you still could do this more generic and add a container property telling what object to call back, let's say the button container get's a property named oCallbackObject, Before sliding up he container you set container.oCallbackObject= THISFORM, the accept button calls This.oCallbackObject.Accept(). In that case it's the same as Thisform.Accept. If your accept/decline container should call another accept method, you initially set container.oCallBackObject = Thisform.ContainerXyz, for example, which also needs to have an accept method then, but it can do different stuff related to that other container on your form.

This is just one idea, it's not even ideal from certain point of views, as it still intertwines all the logic on the UI level, the real deal would be separating the user interface from the business logic and put code acting in any way on data or statuses into classes separated from the visual controls into business logic classes. The visual controls in turn would react to data or status changes, eg via refresh().

Bye, Olaf.
 
You need to turn your thinking about how VFP works on its head. You're trying to insert wait states into procedural code when you should instead be writing code that responds to events. It's a fundamental mindset change. The longer you're trying to force procedural code to do things it wasn't meant to do (like this), the more problems you'll have.

It just so happens that VFP provides an easy way to have code run in response to a click on a button (the button's click method), and if you put the code there you don't even need the variable.
 
thanks so much for your feedback guys.
I agree the way this code hangs together is counter intuitive and wrong in so many ways. I am setting about changing that for the better.
When I inherited the project it was ALL coded at the UI level with O class implementation or external functionality of any kind and not as single PRIVATE variable YIKES!!
I'm in the process of changing all that but its a big job and as you guys know with commercial software you get it to work and put it out there and everything else is secondary.
In time I will extract all the code that resides in the UI and replace it with, as Olaf calls it, 'business logic' classes.
For now I have stumbled a cross a solution that is not pretty but I'll share out of interest anyway.

As Olaf pointed out the click that WAIT is anticipating is not forwarded to anything so the code behind it is not triggered.
BUT I realized after bumbling around for a while that the code behind a MOUSEMOVE event IS triggered in spite of the WAIT condition and so I put the variable in there and as a result the state of the variable (1 or 2) is changed according to the button you are hovering over when you click.
Granted, not the best solution but at least I can move on and tackle bigger issues like moving the entire data environment from inline code that is cut and paste into each form into a proper class structure that can be called by form events.
Thanks again for your insights.
Tim
 
I understand.

One warning: Your solution will assume the button pressed, on which the user last hovered over, even if he moves away from both buttons (being indecisive) and clicking elsewhere.

If you need a quick fix, I'd rather take Mikes solution, removing the need for the WAIT is essential.

Bye, Olaf.
 
if you want to leave the code as is: then pickup mouse co-ordinates and validate against where your 'Accept button' co-ordinates.
To read mouse co-ordinates you could use mcol(), mrow().

everything else is 'Decline' even on key press.

another way could be: instead of the slide('up'), create a form and accept the value as per button pressed.
do form xyz .... to m.Accept_data

you do not need "wait ' '" as Olaf said.

if m.Accept_data = 1
* do something
else
endif

nasib
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top