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

automate command button 1

Status
Not open for further replies.

Mandy_crw

Programmer
Jul 23, 2020
578
0
16
PH
Hi newbie here... i just need help for my program. How can i execute program after entering id number? I mean, every time a valid idnumber is inputted, i dnt have to click the command button to execute. thanks in advance
 
You can do many things, the question is what makes most sense.

The textbox InteractiveChange event happens after any single change of the textbox value, ProgrammaticChange likewise happens when this value change is caused programmatically. Then you could act on Valid and LostFocus events triggered by TAB or ENTER. That also will depend on SET CONFIRM ON/OFF. So there are your technical aspects to consider and solve this. I think they are self-explanatory by their name, mostly. SET CONFIRM means your input will need to finish with ENTER, you confirm your input to be complete by ENTER, not by TAB or even moving focus by mouse click.

In the simplest "hack" call button.click as the code of the InteractiveChange event of the ID input textbox and you have your automation.

Let me argue a bit further, though: In an interface where TAB and/or ENTER finish input of an ID and move focus to that execute command button, all you actually save by automatic execution is pressing SPACE and TAB or ENTER. Because notice, SPACE does trigger the click event, too. You don't need to switch from keyboard to mouse to enter your id. Besides that, ENTER is a usual way to signal complete input and as said you can make ENTER cause events of the textbox, too. You could also check for ENTER key in the KeyPress event. And yes, you can also spare that if you go for the InteractiveChange processing any ID.

But then think of an even worse case that's also quite common: If valid IDs are from a sequence of numbers. Wanting to enter 10432 you go through 1,10,104,1043 and finally 10432. Do you really want to automatically trigger the execution of actions for all the smaller and all valid IDs, too?

So some signal of complete input is not only necessary but also usual in any case, I don't see where that wouldn't matter. There is a category of programs that don't let you enter every input: Games. You affect your current state with some joysticks or such, you don't ENTER after every joystick movement, of course. But then there are a lot of point-and-click interfaces in games, too. But that's a different situation, you don't depend on the exactness of inputs, as you interactively change and correct them. Different beast of an interface, but that doesn't translate to business applications.

I'd recommend SET CONFIRM OFF even though it solves the ENTER=confirming input elegantly, it stops the user from interrupting his id input and do something completely different (in the same VFP application), maybe because a phone call comes in. So I recommend to never put the user into some enforced workflow they have to finish before starting anything else, even such a simple workflow as finishing the id input. And there a command button actually is the easiest way to separate the confirmation of input and action that should cause.

In a touch interface, you may have a barcode scanner for the actual input and it's easy to configure them to send ENTER after the scanned barcode, too. ENTER or TAB/SPACE or ENTER/SPACE is easy to get into your finger memory, too.

I would accept the strategy or specification to react on ENTER anyway. But let it be softer than SET CONFIRM ON, let it work through normal focus change. You could also set the input max length to fit an id/barcode length, by the way. Or specifically handle ENTER in Keypress, as said.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Thank you so much for your answer, i really appreciate it.... if i may just send this codes for you to have a better look of my program. I want that every time an idnumber is put, it will automatically retrieve info from a database name sms.dbf, after doing so it will send a message to the registered number which is also found in the database sms, and goes back to asking another idnumber again. all these without clicking the send button.
thanks in advanced. God bless.

DEFINE CLASS mypage2 as Page

FontBold = .T.
Caption = "Send SMS"

ADD OBJECT label1 AS myLabel WITH ;
Caption = "Id Number :", ;
Height = 17, ;
Left = 35, ;
Top = 23, ;
Width = 128

ADD OBJECT label2 AS myLabel WITH ;
FontBold = .T., ;
Caption = CHR(13) &&* (Max. 160 Char(s))", ;
Height = 17, ;
Left = 20, ;
Top = 135, ;
Width = 149

ADD OBJECT label3 AS myLabel WITH ;
Caption = "Message :", ;
Height = 17, ;
Left = 35, ;
Top = 80, ;
Width = 44

ADD OBJECT label4 AS myLabel WITH ;
Caption = "Name of Student:", ;
Height = 17, ;
Left = 250, ;
Top = 23, ;
Width = 128

ADD OBJECT label5 AS myLabel WITH ;
Caption = "Mobile #:", ;
Height = 17, ;
Left = 250, ;
Top = 47, ;
Width = 128

ADD OBJECT label6 AS myLabel WITH ;
Caption = "Grade:", ;
Height = 17, ;
Left = 35, ;
Top = 47, ;
Width = 128

ADD OBJECT text1 AS textbox WITH ;
Height = 23, ;
Left = 105, ;
Top = 18, ;
Width = 90

ADD OBJECT text2 AS textbox WITH ;
Height = 23, ;
Left = 350, ;
ReadOnly = .T., ;
Top = 18, ;
Width = 132

ADD OBJECT text3 AS textbox WITH ;
Height = 23, ;
Left = 350, ;
ReadOnly = .T., ;
Top = 45, ;
Width = 132

ADD OBJECT text4 AS textbox WITH ;
Height = 23, ;
Left = 105, ;
ReadOnly = .T., ;
Top = 45, ;
Width = 132

ADD OBJECT edit1 AS editbox WITH ;
Height = 55, ;
Left = 35, ;
ReadOnly = .T., ;
MaxLength = 160, ;
Top = 100, ;
Width = 321

ADD OBJECT command1 AS commandbutton WITH ;
Top = 114, ;
Left = 390, ;
Height = 27, ;
Width = 84, ;
Caption = "Send"


* --------------------------------------------------------------------------

PROCEDURE command1.click

SET safety off
SET CONFIRM off


USE sms ALIAS tsulat

INDEX on idnum TO idnumx
SEEK TRIM(this.Parent.text1.value)

IF FOUND()
WITH this
this.Parent.text1.value = TRIM(tsulat.idnum)
this.parent.text2.value = TRIM(tsulat.fname) + + "," + CHR(13) + TRIM(tsulat.name)
this.Parent.text3.value = TRIM(tsulat.mobile)
this.Parent.text4.value = TRIM(tsulat.grade)
nctr = ctr
ENDWITH
DO case
CASE ctr = 1
this.Parent.edit1.Value = "message" + " " + TIME()
nctr = nctr + 1
replace ctr WITH nctr
CASE ctr = 2
this.Parent.edit1.Value ="message 2."
nctr = nctr + 1
replace ctr WITH nctr
CASE ctr = 3
this.Parent.edit1.Value ="message 3"
nctr = nctr + 1
replace ctr WITH nctr
CASE ctr = 4
this.Parent.edit1.Value ="message 4"
nctr = 1
replace ctr WITH nctr
ENDCASE
ELSE

=MESSAGEBOX("No record found in the Database",16,"Message not sent!")

ENDIF

thisform.sms.sendsms(ALLTRIM(this.Parent.teXT3.Value),ALLTRIM(this.Parent.edit1.Value))
* =MESSAGEBOX("Message sent to registered number!",64,"SCMS Attendance Sender!")
*ELSE
* =MESSAGEBOX("Message has NOT been sent",16,"ERROR")
*ENDIF
ENDPROC
ENDDEFINE
 
Well, there you have your case of why it's a bad idea.
While you type an ID and while your input is not complete, calling button1.click from the InteractiveChange would cause an SMS to multiple IDs. Well, okay, you didn't ask for that specifically, to be fair, but you do have the need for an confirmation the id entered is complete. So the way it is is already a good way. TAB and SPACE after you entered an Id and you're done without any code change. It's not too complicated, is it?

This code is also not showing any tab order set nor names of textboxes making sense. I see label1 is about the ID Number, but would have to see what coordinate would make sense for the corresponding textbox. We get no deal in extending this code that way. Edit: It's easier to spot where the id is seeked in the command button code, later...I'd still recommend:

Use the visual designer, double-click on a control and you get to its code, the object of the code editor will be the control and the click method is likely to be shown. Depends a but, which method, but now you can use the procedure combobox to get to any other method or event of the control and program it.

Another good way to directly get to edit a certain method or event of a control is have the class designer and properties window open together. You'll see what that does, whenever you click on a control in the visual design, that will be the object in the properties and you can use its methods tab to get to any specific method or event by double-clicking it. You can see which methods and events have code already, too.^
You'll also have intellisensee giving a list of properties, for example after typing this and a dot. But that procedure combobox is giving you a list of method and events defined for tha control and that's a service no text editor gives you unless intellisense can infer what a specific name is, what control or other class it is.

So in contrast, in a program like the posted coming from the viewcode tool, I guess, you obviously never see which methods and events even exist and could be programmed. If that's all you have, then just leave it as is. The advantage that all code of that class is in one text is not big in comparison of how wrongly you could extend it. Just have a typo in an event name and it'll just be a user defined method not triggered by the actual correctly spelled event.

Looking at the code referencing all the unchanged names automatically given, like test1-text4, it isn't even feasible to make names changes to make this more manageable, without forgetting any place. It's true that a test of the whole form is enabling you to do such changes throughout all places as it's then one text and search&replace can be used on it, that's the advantage of one text file. But in this case, you only have a page class and don't know what other portions of the form code depend on the names as they are, so you actually don't have a text file of all code of the form that finally has this page,

The simplest thing that reveals which textbox is the Id Number text boss is its usage in finding the data for that id: SEEK TRIM(this.Parent.text1.value), so text1 is the Id Number textbox. I'll give you a starting point: Add this at the end:

Code:
PROCEDURE text1.valid()
    MessageBox("id:"+transform(this.value))
    Return .t.
ENDPROC

Bye, Olaf.

Olaf Doschke Software Engineering
 
Thank you so much!!! you're so kind.... ok i'll try to put the code at the end... thanks more power and godbless...
 
This will not automate the click but display a messgebox (should be clear by the code itself).

The question is, whether you see this happening and when.
Experiment #1: Input an ID and finish with ENTER
Experiment #2: Input an ID And finish with TAB

Ideally the ENTER should trigger the valid event.

Then you should know what to do instead of the Messagebox.

One thing must remain: The valid must return .t., or you can never leave the textbox.

And this whole thing is still only the sketch of an idea, as the valid happens whenever you leave the id textbox. Also when you actually are finished with entering IDs and sending SMS and just want to leave the box.
The best thing really is to keep it the way it was. Because you will have to find a way to differentiate when the leaving of the textbox should mean to cause the action or the control is just changed to modify something else, the message for example, before sending it.

That's the crux with such automations.

Bye, Olaf.

Olaf Doschke Software Engineering
 
And finally experiment #3: Input an ID and click somewhere else, for example on the message to send.

And there you have three causes for valid to happen and you won't want to let all of them always trigger the button action. So, once more, just stay with the unautomated button, that way it'll be easiest.

You have to apply a lot more thoughts on what-if scenarios to just get it to react to ENTER. There is LASTKEY(), but don't think you're finished by checking that in the Valid code. It has a corner case, LASTKEY() stays 13 even when you then only click around and change focus, you'll again trigger the action though you didn't press ENTER this time but clicked elsewhere.

Next thing you may want is returning or staying in the text1, so you can enter the next id right away. This causes the problem how to get out at all, when any valid causes the sendsms and goes back into the textbox.

So actually you also need to care for changing LASTKEY(), and that solution is also quite well known to VFP developers for another case of focus control, when incorporating ESC into the hotkeys of a general way of canceling out of a form. To allow that, here's code described that also takes into account the persistence of LASTKEY() to only change when another key is pressed:
But I really beg you, please stay off the route of such trickery. You only gain saving one keypress per SMS, you would save much more in batch processing some id list, if you're really serious about saving time. In the simplest case process the text1 value as a comma-separated list.

And the code you leave behind, that would only react to a current ENTER, allow canceling out of the form with ESC, would only put question marks on the next novice VFP developer, who doesn't know about this technique. Again, we're picking up my favorite anti topic about micro-optimizations that don't pay off, this time not in code performance or strictness, but in UX. You have a more or less codefree way this works and that is easiest to maintain, just get used to tab and space allowing you to get the button and "click" it, without changing to the mouse and then apply the idea of the coomma-separated values to really enhance the processing speed by needing even less clicks instead of just optimizing away one met per SMS sending. Oh, and when you now see that this is just an exchange of space for a commma more per id, you forget that once you caused the action all SMS are sent you don't have a wait time before you can enter the next id, you're finished, can change to the next form and do something else while that processes the list. Have a very large list? Run it in a separate process.

You know, there are articles and book chapters or paragraphs about it praising the elegance. I'd say you need a hck to get a textbox acting sensible about ESC and the whole valid mechanism used in the sense it is intended to disallow leaving a textbox without a void value is a flaw in contrast with UX guidelines. Many other languages have simpler event models of controls that allow you to use then without any code and act sensible. And the interface as you have it was good at that, too, by not having special handling. Just leave it as it wss.

I'm closing my case here.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Couldn't agree with you more Olaf. Don't try to solve a problem that doesn't exist.
 
Thank you Dan,

what I can understand is that it's really a seemingly easy task to implement, unless you know the event model of VFP. It finally still is just a few lines, but just take the trick in the wiki to replace LASTKEY by "pressing" CTRL+A, that also is the key combination to select all. So even that may have to be adjusted to really just a useless key. And the keyboard command doesn't allow simply to cause SHIFT or CTRL without combining it with another key. It's really the simplest to keep it stupid.

Unless you would get hands on a application framework that offers control classes incorporating such and more ideas into its valid event handling. Provided you find one.

Bye, Olaf.

Olaf Doschke Software Engineering
 
thank you so much dan and olaf... i really appreciate all of your help... thank you for the enlightenment... i will have to let it be,...godbless and more power...please continue to be a blessing to everyone...[glasses]
 
Well, after all these ramblings about valid, there is a completely different route with keypress event, you can check for keycode 13 there. Unlike LASTKEY this will really be the currently key pressed and then you can react to that.

Code:
PROCEDURE text1.keypress()
   LPARAMETERS nKeyCode, nShiftAltCtrl
   IF nKeycode=13
      Noefault
      Thisform.Command1.Click()
   Endif
ENDPROC

That would be side effect free, I think. You can now still level the textbox with TAB or clicking elsewhere. ENTER keeps you inside by the nodefault not causing the valid event. Anyway, The commands click code could also set focus back to text1 for entry of the next id with thisform.text1.Setfocus().

It's handling on an alternative route. There's a slight change form.keypreview changes processing, but in any case the text1 keypress event will be running, too.
Now you could hide the command button or put its code into a form method, but I'd argue even in the internet submit button is the default interface even for just single field entry. For example I see some two step logins where you first enter your name and submit that and then enter password and submit that and even though these are single input field "forms" they work with a submit button. The interface where ENTER is the entry point usually is a common shell or console application only. Where you're going through a completely linearly process asked one single input after the other only.

Bye, Olaf.

Olaf Doschke Software Engineering
 
thanks olaf... i really appreciate it... this code gave me an idea... my program is now working as how i wanted it to be... god bless and more power... i hope you'll not get tired of helping...

PROCEDURE text1.keypress()
LPARAMETERS nKeyCode, nShiftAltCtrl
IF nKeycode=13
Noefault
Thisform.Command1.Click()
Endif
ENDPROC
 
i just want to know how to make it a standalone exe? thanks again
 
You need a pjx with all relevant PRG and other files.
You will have more, as the prg you posted only has a page class defined, there is more necessary to have a form.
You will also nee to know what prg is the one to start, that must be made the main program of the project.

You might already have such a project (PJX/PJT file pair) to work on.

And then it's simply clicking a Build button in the project manager.

Unless you're using something else, legacy Foxpro, but I think it must be at least VFP5 code when you define a Page class. Older VFP versions had screens and other ways of defining them without controls like the pageframe with its pages.

It should actually be VFP8 or 9 as I think a page class was only available with that.

So you might really just be sitting in front of a project manager window already all the time and just need to be pointed to the Build button.

Bye, Olaf.



Olaf Doschke Software Engineering
 
I assume the silence means you found it. But feel free to ask what you don't understand.

It's not easily determined wha needs to become part of a VFP project to compile an EXE that in the end really is working standalone, ie. without any other prg or fxp files, and all further things part of the sources, also images, header files with constant definitions, forms, reports, classlibararies, etc, etc.

If you're unsure what belongs into the EXE and only know the PRG you start does all it should, create a new project with CREATE PROJECT ? and then just ad that one PRG.
When you compile it may see which further files are referenced and add them, too. In the simplest case though, rather have too much than too less in the project. And it's easy to even add a whole bunch of files via drag&drop. Make the VFP Window half-size perhaps open up Windows explorer and just drag files or a whole selection (CTRL+A for a whole dir) of files into project manager inner main region and they'll sort into the tabs.

Bye, Olaf.



Olaf Doschke Software Engineering
 
hi olaf... not yet done with my program, still doing some final touch, im actualy still putting a picture header, but it doesnt show up, it shows as at the back, i cannot put it at foreground...

LOCAL oForm as Form

oForm = CREATEOBJECT("FormSMS")
oForm.Show(1)

RETURN

DEFINE CLASS FormSMS AS form
Picture = "C:\Users\mandy\Downloads\SCMS\Untitled-1.jpg"
DataSession = 2
Height = 440
Width = 526
AutoCenter = .t.
Caption = "SMS!"

ADD OBJECT sms as mysms WITH Visible = .f.

ADD OBJECT pageframe1 as mypageframe1

and this is how it looks like...[bigsmile]
2020-07-30_2_latbme.png


how to put the picture inside the blank rectangle on top, still trying to figure it out...
 
You can't turn an editbox transparent or partly transparent. And that box is an editbox. Likely the one showing the SMS message to send.

So there isn't a solution for this other than making the box smaller or moving it elsewhere, if that part of the picture is important to you, leave the upper form area blank - free of controls - and move controls down. I'm just stating the obvious things you can do about it as you can't turn controls transparent, just like the white small textboxes below.

VFP isn't HTML with CSS enabling things like transparency. You can make a PNG picture with transparency and put it into the front, but that renders controls below unusable. So this already is your best solution, if you want to see more of the picture in the background, make it bigger overall and keep areas you want to see from the picture free of controls, position them elsewhere on an overall larger form, size them down.

Bye, Olaf.

Olaf Doschke Software Engineering
 
wow!!! u really is a genius!!! thanks olaf.... im enjoying this programming because of you... thank you... i'll try it...

by the way,
have i said that this suggestion of yours made my program work to what i want it? youre really really good.. thank you and godbless.... more power...

PROCEDURE text1.valid()
code
code...
Return .t.
ENDPROC
 
Fine Mandy,

Also that sounds very fine, have fun doing so and I wish you all the best. Testing whether a build works won't hinder you to make further changes and rebuild a new exe, by the way. So it would be nice if you look into that as it'll be more important you build up a working project able to build as EXE than any final touches.

And if you have further questions, please start a new thread. It's okay for me to answer a side question not related to the oringal one to round things up and make them work, but actually the question about creating a standalone.exe and about the picture not showing through controls are worth their own thread.

Bye, Olaf.





Olaf Doschke Software Engineering
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top