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

Setting variable value in a Form 5

Status
Not open for further replies.

SitesMasstec

Programmer
Sep 26, 2010
523
Brasil
Hello dear colleagues!

I created a simple form (Form1), just with a Label (Label1).

In Label1, Properties, Caption I want to use: =Customer_Name

Somewhere in the Form I must declare User_Name="John Doe"

For some reasons, I do not want to declare in Label1, Properties, Caption:John Doe

Where in the Form I must declare this variable? I tried in the Form, Procedure, Init (and also in the Load) this declaration: User_Name="John Doe", but without success.

Where to write this declaration of variable?


Thank you,
SitesMasstec
 
Hi,
Unless PUBLIC, variables created in a VFP method disappear at the end of this method.
You need to create a property (eg. "user_name") in the form (menu > form > new property) and store the value there.
Then add this code to label1.refresh():
Code:
this.caption = thisForm.user_name
 
A label is not a control with a controlsource, you can't display a variable value with a label.

The second thing is you don't use variables as controlsource, that may have been legacy style, but you avoid public variables and neither local nor private variables have a scope and lifetime of the form. bind to a form property. and once you do that, you can also simply set the label caption, there is no point in having this variable bound.

you would have a reasoning to have something bound to a controlsource, if the controlsource can be something changing like a table field is. these are the most valuable controlsources as simply skipping forth and back in a table or coursor can change display (at least after refresh/requery).

The easiest thing to do is prepare a textbox to look like a label.
Make it transparent: .backstyle=0
make it borderless: .borderstyle=0

Now you can bind to the, controlsource and/or set the value.

You generally don't bind to variables because of the available scopes, you CAN bind to variables, you can set .controlsoruce to either field name or variable name, but this variable will need a scope existing as long as the control exists. Therefore you always bind to data, tables, views, cursors, workareas (whatever name you understand, it's all the same, in the end). And to have control about when data is stored you use buffering.

Bye, Olaf.



 
You asked where in the form you declare the variable. You then gave the example: User_Name="John Doe". But that is not a declaration. It is an assignment. The declaration declares the existence of the variable. The assignment assigns a value to it.

Based on what you have told us, what you need is a form property. You declare a form property in the form (or class) designer, using the "New Property / Method" option in the Form (or Class) menu. You can then assign its value in either the form's Init or the label's Init.

But as Olaf has pointed, even that is not what you want. A label cannot be bound to a variable or a field in a table. The nearest you can get to that is to determine the value that you want to show in the label, and then assign it each time you refresh the form.

Perhaps what you really want is a not a label, but a text box? If you want it to look like a label, you can adjust the text box's appearance accordingly. You can also make it read-only, just like a label,

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
What I have been done for many years is:

Example:
The main program is Myprog.prg

in it, there is:
Code:
ACTIVATE WINDOW BlueScreen
...
 User_Name="John Doe"
 User_Adress="Sky Street"
...
@15,16 SAY ' Press <enter> '
READ 
DEACTIVATE WINDOW BlueScreen
DO FORM MyForm

and in MyForm there is a Label (which will display the User_Name). In this label Properties the Caption is: =User_Name
and so on

I would like to eliminate the Myprog.prg program, and execute the form MyForm directly.




Thank you,
SitesMasstec
 
But you're not using READ in a VFP application.
So any scope but PUBLIC is not having the necessary duration.

If you still do READ (It's only there for downward compatibility), you are keeping private and even local variables in scope. But that's not compatible with using forms and control events. You're stuck in legacy style programming then and don't work the Vfp way.

Bye, Olaf.
 
To go back to your original question. You want to display a user name on a form. Is that correct?

If the user name is fixed, and is known at design time, just add a label to the form, and set its Caption property to the required name. You can do that in the form designer (type the name in the Caption property in the Property Window).

If you don't know the name at design time (which is more likely), and if the name does not change for the life of the form, set it in code. You can do that in the label's Init ([tt]THISFORM.Label1.Caption = NameVar[/tt], where NameVar is a variable holding the name).

If you don't know the name at design time, and you need to change the name during the life of the form, execute the same code as above, but this time do it whenever the name changes. You can also do it in the form's Refresh.

If you need to obtain the required name from a table (in other words, if you want the name to be bound to a field in a table), then don't use a label. Use a textbox, and set its ControlSource to the table.fieldname containing the required data. Set the ReadOnly property to .T. If necessary, adjust the BackColor, BackStyle, BorderStyle, etc. to make the textbox look a bit more like a label.

Do any of the above suggestions cover your requirements?

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 

Mike: I have some users of my software. Sometimes I have to distribute new versions, so when the user X (for example, John Doe) calls me and asks for the new version of the software, I, within minutes, change the user name, address name, etc in a PRG file (Set as Main program) and built it in an EXE format (the application I will send to John Doe).

At executing this application (as the PRG file has all user data ---name, address, etc) , it executes (DO FORM...) the main program, showing, among other things, the user's data.

If I put these user data in a table, it will be easy for hackers to use my software, just changing user's data in the table, so I avoid using table for the user's data.

According to advices from Olaf, FoxinCloud, and yours, I think I will remain continuing to use a PRG program (with explicited variables) to execute before calling a Form. I had thought I could write these command in some part of the Form, like Init or Load. I think it would not be practical, in my case, to use Form Properties to explicit user's data.

I want to thank you all very much for your patience.


Thank you,
SitesMasstec
 
If you are launching the form from the PRG, why not do something like this:

Code:
* Put this code in the PRG
LOCAL lcUser, loForm

* Alter this line for each user
lcUser = "William Shakespeare"

DO FORM TheForm NAME loForm
loForm.Label1.Caption = lcUser


Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Code:
ACTIVATE WINDOW BlueScreen
...
 User_Name="John Doe"
 User_Adress="Sky Street"
...
@15,16 SAY ' Press <enter> '
READ 
DEACTIVATE WINDOW BlueScreen
DO FORM MyForm

In that kind of code I don't see a dependency of Bluescreen, so let's simply remove it and look at the remaining outset:
Code:
User_Name="John Doe"
User_Adress="Sky Street"
DO FORM MyForm
You want to use the variables you assigned here within MyForm, and you can at least in Init. Whether you can bind controls to them depends on whether the form is modal or not. Because the moemnt this PRG ends (and it will do so immediately, if the form is non modal), the variables are released.

It's a bad idea in terms of encapsulation, as the form only works when some required variables are set as prerequisite of calling it.

A form should be able to run without any prerequisites and without any restrictions on its modal state (with exceptions where it makes sense). This is driving with the handbrake on.

You say you do this for sake of customization and protection. It's wrong to think data put into a PRG can't be changed. All you need is a hex editor and you can change all string literals used in code and compiled into the EXE. Also data in a DBF encrypted can be changed, but not to something decrypting to the wanted values. The topic of software protection is vast, I'll not go into details here, but you're wrong in feeling safe.

The ease of customization also is given with a DBF with a list of rows having a key and value column. Include it in the EXE, compile with encryption and you have a base protection of the EXE on disk. It's not a strong protection, as it's automatically decrypted when run and in memory you have clear text again. You need stronger protection and licensing for the aspect of copy protection.

Bye, Olaf.







 

Mike: Yes, it is what I have been doing for many years with additional "...Press <enter> to continue..." in the PRG file. I think I could avoid using the PRG. But now on I will take out the "...Press <enter> to continue"... command from PRG, following Olaf's and your advice. Thank you.

Olaf: the Form I am using is Modal. I will follow your advice, thank you.

It's wrong to think data put into a PRG can't be changed.
I am very alarmed now for what you said above! I will research about it.

Thank you,
SitesMasstec
 
Given that your form is modal, then the code I suggested won't work. That's because program execution will pause at the DO FORM, so there will be no opportunity to set up the caption before the form closes.

In that case, it would be better to put the code in the form's Init. Given that you would have to rebuild the app anyway when sending out a new version, it won't take any more effort to modify the Init than to modify the PRG. So just do something like [tt]THISFORM.Label1.Caption = "Whatever"[/tt] in the Init.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 

Mike: it worked fine (PRG file and then Form), like you and Olaf advised me, and the Form I am using is (WindowType=) 1-Modal.



Thank you,
SitesMasstec
 
Mike: it worked fine (PRG file and then Form), like you and Olaf advised me, and the Form I am using is (WindowType=) 1-Modal.

The only way Mike's code would work with a modal form is if it's a top-level form. Top-level forms cannot ever be modal no matter how you set WindowType.
 

Hi Dan!

My form property for "ShowWindow" is "0-In Screen (Default)".


Thank you,
SitesMasstec
 
You have a form with ShowWindo=0 (In screen) and WindowType=1 (Modal)?
Is that still the case, when it runs?
Because if so, the line [tt]DO FORM TheForm NAME loForm[/tt] would only come back after you close the form and the next line [tt]loForm.Label1.Caption = lcUser[/tt] would then fail, as the form already is gone.

So you certainly moved this line into form init or elsewhere, so it could work.

And what I am saying is not advice, it's an observation of a bad situation. Modal forms are forcing the user to use only them, you're restricting the freedom of a poweruser to work with multiple forms at the same time, so the whole concept doesn't work out well, as it depends on a modal form to keep the variables created before running it alive.

In regard to seeing changing text within an EXE with a hexeditor: VFP itself comes with one, so this can easily be demonstrated:
1. main.prg with one line: Messagebox("Hello, World!")
2. Build as helloworld.exe
3. Open up in Hexedit and search for "Hello, World!":
hexedithello_guazg2.png

4. Edit Text and Save Edit:
hexeditbye_remk1n.png

5. Changed Text is shown:
hexeditmsgbx_njelhv.png


Bye, Olaf.
 
SitesMasstec, you said at the outset that your aim was to prevent hackers from using your software. You do that by branding the form with the legitimate user's name and address.

If I put these user data in a table, it will be easy for hackers to use my software, just changing user's data in the table, so I avoid using table for the user's data.

I don't want to denigrate your software, but I must ask if it is really likely that some nefarious person will try to use it without your permission; and that such a person would be discouraged from doing that by seeing someone else's name and address on the screen.

Furthermore, if that person was knowledgeable enough to hack a DBF, they are just as likely to be able to hack an EXE (as Olaf has shown).

Personally, I would store the name and address in a simple text file, and have the program read and display that data at start-up. But if you are really worried about unauthorised use of the software, the best solution would be to set up a user table, containing encrypted passwords, and require the user to log in with a user and password at start-up. That's what many commercial software packages do, and it's not at all difficult to implement.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
A protection even of a simple text file is possible by cryptographically signing it.
What this means is not write protecting the file, but enabling to detect any changes made to it.

VFP has the _crpty.vcx in ffc with the _cryptapi class, this has the methods signfile() and verifyfilesginature().
The solution sample "Add encryption to applications" within the "Foundation Classes" section of the solution sample shows how to make use of these methods:
signandverify_yrr8kp.png


What you do is sign a file you want to verify being unchanged, then store both the signature and public key separate, this time putting it within your code would be fine. Even if someone would identify which bytes of your final EXE store this signature and public key, changing both would be required because the signature can only be created with a private key, which is not output here and also shouldn't ever be output, as it's your secret. It's autogenerated by the _cryptapi class. And generating a new signature with a new key pair requires to both change signature and public key to be able to pass that verification test again.

Now at the start of your application, you verify the file signature and if it's invalid simply quit. This still enables to run a copy and as Mike said nobody would be discouraged by a message or splash screen showing someone else's name, so it's quite useless as protection, unless you can store and sign something, which is necessary to run and would need to be changed on another computer, like serial numbers. The problem with that is you don't know in advance what the CPU hard drive or other serial numbers of your customer are, so you'd need to provide the signing procedure and your private key, which you never should distribute. Instead, there would be a process at installation or the first start transferring such information to you, so you can sign it at your computer and return back the file generated from this information and its signature.

This still is quite unsatisfactory in the process for your customers. Also, I faintly remember one of the signature standards was broken and since VFP9 is over ten years old it's likely you better use something more modern for secure encryption including signing data.

So for real protection I'd always go for an expert on this, and though I know about that _crypt.vcx and have implemented encryption and signing in a POS system this year, this used a library from a vendor trusted by austrian government and not something from VFP FFC, so such things are better not written yourself, even not on the highest level of using well-known cryptography algorithms, as an insecure usage of highly secure algorithms still is insecure overall. In this case, the autogeneration of keys remains some secret, I don't see how to use _crytpapi methods to retrieve the private key to store it for repeatably signing information with the same key pair, for example. While you should never distribute it, you should be able to maintain it for yourself. That also opens other possibilities, eg decryption of messages sent from your application to you encrypted with the known public key. You'll need to know your private key for decryption, though.

Overall, there are commercial products for software protection and they exist for a good reason. You should use something from a third party, from a vendor which is expert on that field.

Bye, Olaf.
 
Hello dear colleagues!

Olaf (about your last 29 Nov 17 post):
- Yes, my form property for ShowWindow is 0-In Screen (Default) and the property for WindowType is 1-Modal.
Maybe I will have to change these properties as the program is being developed, but by now it has worked the way I need.

This is the PRG code:

Code:
UsuarSigla="ABCR"   
*UsuarSigla="DEFG"   
*UsuarSigla="HIJK"   

IF UsuarSigla="ABCR"   
   EMPRESA="ABC REPRESENTAÇÕES LTDA."
   EMPRLOGOP="ABCLOGOP.BMP"
ENDIF
IF UsuarSigla="DEFG"   
   EMPRESA="DEFRAG CORPORATION"
   EMPRLOGOP="DEFLOGOP.BMP"
ENDIF
IF UsuarSigla="HIJK"   
   EMPRESA="HARRYSON COMPANY LTD"
   EMPRLOGOP="HCLLOGOP.BMP"
ENDIF
.
.
.
DEACTIVATE WINDOW TelaPadrao

DO FORM CRIPTVEN

ENDDO


This is the form CRIPTVEN.SCX when executed:
telacripto1_erghd9.jpg



Form CRIPTVEN.SCX code:
telacripto2_sfchjs.jpg



- Now I will concentrate in the your and Mike's posts about code protection, and practice the examples.




Thank you,
SitesMasstec
 
OK, it shows you're not using Mikes advice to set the caption after the doform, that's what we all were puzzling about. The ENDDO is wrong, you only do ENDDO for DO CASE DO WHILE, not for DO FORM, DO FORMis just a single command.

The load is empty, fine. The variable names have to appear somewhere anyway, when you use Code References and search the whole project, most probably any other method (besides Load there are more) or you set an expression within the Caption. What puzzles me about that then is, why you had your initial question at all. You already use variables within the form, did you forget how? Code References search result will show you, perhaps it'll show properties in the search results. Also, once the captions are set, they won't depend on the variables existing, then, so you could change the form to non modal and the captions still would already be set before the variables get out of scope and release. Their value then is copied to the label captions and they are not used anymore.

Aside from that it now becomes a little strange, when the subject of the form and application is about encryption and you're using very unsafe methods of customizing the forms captions, when you care about that being fixed values.

Another thing, that comes to mind when it comes to captions of labels is the need to internationalize an application. That's mostly not about names of owners, but any label text and tip texts etc. and that typically also is done data driven. The process to set the captions then typically runs within the init of any single control having some way to determine it's own caption text from a table of translations in a currently active set language. A positive side effect of that is all those captions and other texts then are not simply hardcoded texts within the source code or control properties, which all will be somewhere in the EXE and are subject to simply be hackable by hex-editing the EXR. DBFs can be filled with encrypted data you can decrypt at runtime and for things that won't change and grow at runtime such data can easily also be included in the EXE encrypted, be decrypted after querying into cursors and then be used on captions.

Bye, Olaf,
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top