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

Variable Creation. (I'm sure this will be the dumbest question...) 3

Status
Not open for further replies.

Scott24x7

Programmer
Jul 12, 2001
2,828
JP
Sorry to have to start this out with, "I used to do this this way....", but it helps me learn this stuff...

Here is my problem. I have an image that keeps track of how many times it has been clicked on a form, because the image displays a different message every time it is clicked. So, what happens in the Click Event for this image is:

nNumClick = nNumClick + 1

DO CASE
CASE nNumClick = 1
WAIT "A Click Message" WINDOW TIMEOUT 5
CASE nNumClick = 2
WAIT "Another Click Message" WINDOW TIMEOUT 5
.
.
.
ENDCASE

The problem I am having is how to initialize the nNumClick. The only thing I have gotten to work so far is to put:

PUBLIC nNumClick
nNumClick = 0

in the Load event of the form. This works, but I hate the thought of creating a Public. I used to use Regional in 2.6, and this worked fine. But it does not work here. (Even if I declare it as "Local"). I get the message: nNumClick is not a variable this way. I also tried putting nNumClick = 0 in the object's INIT EVENT, but that didn't work either... still received "nNumClick is not a variable" message.
Any thoughts???
Thanks,
-Scott
 
Dear Scott:

You could easily add a property to your form at design time and also initialize it at design time.
Since I'm using VFP Spanish version I'll try to translate menus as close as posible

Go to Form Menu
New Property
In the Name textbox write NnumClick
Push Close

Now in the properties sheet of the form you will see at the bottom NnumClick. Change this propertie's value to 0.
Now you have a property you can use as a variable.
Instead of using

nNumClick=nNumClick+1

now use

Thisform.nNumClick=Thisform.nNumClick+1

Hope that helps

Rianeiro
rianeiromiron@yahoo.com

 
OR if you are using classes, you could add the property to the image class and add a method to the image class that helps you leep track of the times clicked.
You can call this method from the click event of the image.

HTH,
Weedz (Wietze Veld)
My private project:CrownBase source code can be downloaded !!
 
Weedz,
Ok, I created a class based on the Image type, I added a property called "nNumClick", should I add an "Assign" method automatically? Is that what I use to control it, and what should I set the "Visiability" to?
Thanks,
-Scott

P.S.... wow, I may actually be getting the hang of this...
 
If you are only using the property from within a custom method in the image control, you could set it to protected.

Example:

DEFINE CLASS imgImageControl

PROTECTED nNumCLicked = 0

PROCEDURE GetNumclicked
RETURN THIS.nNumCLicked
ENDPROC

PROCEDURE SetNumClicked
THIS.nNumCLicked = THIS.nNumCLicked + 1
ENDPROC

PRCEDURE ResetNumclicked
THIS.nNumCLicked = 0
ENDPROC

PROCEDURE Click
LOCAL llRetVal
llRetVal = DODEFAULT()

IF llRetVal
THIS.SetNumClicked()
ENDIF

RETURN llRetVal
ENDPROC

ENDDEFINE

In this example you have protected your property from being set by any other object that you image control. If the property is set, it has to be done via ResetNumClick() or SetNumClick().

Good luck,

HTH,

Weedz (Wietze Veld)
My private project:CrownBase source code can be downloaded !!
 
Weedz,
Cool, I see where this is going, now for the final part of this dumb question set, and then I think I'll have it... in my click event, a message is displayed based on the number of clicks. (Different for each click). Do I have to reference them with:


DO CASE
CASE THIS.nNumClick = 1
WAIT 'FIRST MESSAGE' WINDOW TIMEOUT 5
CASE THIS.nNumClick = 2
WAIT 'SECOND MESSSAGE' WINDOW TIMEOUT 5
(etc.)
ENDCASE

Or, can I do what I would prefer which is:

DO CASE
CASE nNumClick = 1
WAIT 'FIRST MESSAGE' WINDOW TIMEOUT 5
CASE nNumClick = 2
WAIT 'SECOND MESSSAGE' WINDOW TIMEOUT 5
(etc.)
ENDCASE

I know this seems like a trivial difference, but it just looks so much cleaner to me...

Thanks,
-Scott
 
You can do this:

PROCEDURE Click
LOCAL lnNumClick, llRetVal

llRetVal = DODEFAULT()

THIS.SetNumClick() && Be sure to update the number of clicks

lnNumClick = THIS.GetNumCLick() &&we do not need to refer to the property immediately

IF llRetVal
DO CASE
CASE lnNumClick = 1
WAIT 'FIRST MESSAGE' WINDOW TIMEOUT 5
CASE lnNumClick = 2
WAIT 'SECOND MESSSAGE' WINDOW TIMEOUT 5
(etc.)
OTHERWISE
*- Nothing....
ENDCASE
ENDIF

RETURN llRetVal
ENDPROC

As you can see, I declared lnNumClick (local numeric NumClick, this is just a way of making the code readable) as a local, since we only need lnNumClick within the click method. Use locals as much as possible. Using privates can cause trouble in the chain of events and methods called.
Since we are able to use properties, there is actually no need (in 99% of the cases) to use privates.

Locals have a scope to the current method/procedure and do not exist in sub procedures like privates do.

HTH,


HTH,
Weedz (Wietze Veld)
My private project:CrownBase source code can be downloaded !!
 
Weedz,
How stupid of me... thanks, I get it now! (Duh, assign value to local variable...) thanks.
-Scott
 
One more point.

As a rule of thumb, I try to keep processing code in a seperate method and keep interface-related code as clean as possible:

PROCEDURE Click
DODEFAULT()

THISFORM.CountImageHits(.T.)

RETURN

*********************
METHOD CountImageHits && in THISFORM
LPARAMETERS tlShowImageHits

LOCAL lnNumClick

THIS.SetImageHit() && Be sure to update the number of clicks

IF m.tlShowImageHits
lnNumClick = THIS.GetImageHits()

DO CASE
CASE lnNumClick = 1
WAIT 'FIRST MESSAGE' WINDOW TIMEOUT 5
CASE lnNumClick = 2
WAIT 'SECOND MESSSAGE' WINDOW TIMEOUT 5
(etc.)
ENDCASE
ENDIF


There are two advantages to this type of processing:

1) The related processing (in this case, counting and displaying the number of image hits) is seperate from the interface. It gives you more flexibility in terms of how you can use the related processing. Additionally, if someday you need to run the related processing independent of the trigger control (i.e. you wanted to run the image hits processing from some other button, or even independent of any control) access to the process is trivial (just call the method) and you will not have to deal with processing intrinsic to the trigger control.

2) Someday you may want to move to another interface, maybe even another language (i.e. VB). If your related processing code is irretreivably bound to some event of a VFP control, you're going to have to re-write that process. If you keep the related processing seperate it will make any down-stream translations infinitly easier.
Developing with this kind of encapsulation is the first step in working towards the holy grail of n-tier processing.

Regards,
Thom C.
 
ThomC,

You are absolutely right.
I am also used to this type of programming, but sometimes...;-)

A bit of nitpicking:

I always try to return or use the return value of DODEFAULT()


PROCEDURE Click
LOCAL llRetVal
llRetVal = DODEFAULT()

IF llRetVal
THISFORM.CountImageHits(.T.)
ENDIF

RETURN llRetVal

RETURN


Cheers,
Weedz (Wietze Veld)
My private project:CrownBase source code can be downloaded !!
 
Thom,
Wow, you illustrate here is really elegant! This is the kind of "Stuff" I'm looking for. I will admit that I don't fully understand all of the philosphy involved in your message, but it is painting a clearer picture, espeically about how to "Do" encapsulation. I'm going to start a new thread about "DoDefault()", as I am unclear about it, but this thread has gotten long, and I dont' want to jump topic late in the game here. :)
Thanks,
-Scott
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top