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!

How do i add browse button? 4

Status
Not open for further replies.

Mandy_crw

Programmer
Jul 23, 2020
578
PH
Hi everyone.. I have a page in my application that edits a record... I want to put a browse button and look for the picture of the owner of the record and rename that picture which should be desame with its idnumber.... Would you please help me how to start or give sample code that i can adapt? Thanks and God bless....
 
Mandy, once again we have to use guesswork to understand what your question means. (It would really help us if, before you click the Submit Post button, you read your question back and check that it makes sense.)

That said I will have a shot at understanding it. I'm guessing that you want to arrange things so that when the user clicks a certain button, they will be able to browse their file system for an image file. If so, that part is easy. Use the GETPICT() function. This works like GETFILE(), but is specific to image files. The full syntax is documented in the Help.

You than talk about renaming the picture with its ID number. If you mean that you want to rename the image file, then that works just like renaming any other file. Use the RENAME command. I don't know what the ID number is, but presumably you do.

Finally, it's not at all clear what you want to do with the renamed file. Do you want to display it on a form? Or what?

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike has given a good answer at the outset of your sparse description and I interpret it the same way.

I just wonder about the case a users record already has an associated image, then you can still use the same solution to first get a picture file name and then rename it, but you could end up with the conflict of two image files with the same name if the new user photo is in the same folder as the old one. When a user already has an image associated with his record, that image should be either renamed or deleted to allow a new image to take the same name as before.

It would also be a good idea to copy the image from anywhere you picked it into the folder of your database or a subfolder. Users will have access permissions there, as they by default must have access to the DBC and its DBFs, so it's natural to put the images there, too. Then copying a new image can just overwrite the old one, but you have to temporarily SET SAFETY OFF so this copy can be done without a question to the user whether to overwrite the existing file.

I'd also not move the file you picked if it is somewhere else than in the database folder. That way you retain the original in case anything goes wrong.


Chriss
 
Another way of interpreting your question would be that, when the user "browses" the images, you want them to see the actual images rather than just the filenames. You can longer do that with GETPICT(). It used to be the case that the GETPICT() dialogue had a preview pane, where you could actually see the images as you are browsing, but, as far as I can see, that is not available in the most recent version. (Someone please correct me if am wrong about that.)

An alternative would be to create a cursor which holds the images in a General field. You could then create a grid to display the contents of the cursor. The grid would include an Image control, bound to the General field. This would allow the user to browse the images and to make a selection.

I could give you some more details about how to do that. But I'll only do that if I have correctly understood your requirements.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Thank you Mike and Chriss so much for taking time to answer my question... and so with i want to say sorry also for really im having a hard time exaplaining my question... Please give me another chance... I'll try my best again to explain what i need Mike and Chriss and everyone...

i have a page that when idnumber is entered it shows details of the record including picture, ( the picture is manually renamed same with the idnumber, so that it will appear when the idnumber is entered, and it is stored to a specific folder)

my problem is, since i am the only one who knows how to renamed and put the picture to its dedicated folder, my co user/worker always ask me to do the updating of the picture.... having said those, i want the user to have the power to change or update the picture whenever possible.... i want to have a "browse" or explore the computer hdd or ssd and look for the new picture, and once new picture is found, it will be selected by the user, and automatically it will be renamed its filename to the same idnumber entered and finally be put to a dedicated folder.... I am hoping that you have gotten my problem.... Thanks in advanced.... God bless and happy new year!

 
Okay, this is still just a short click method with the two function calls:

Code:
* browse button click
Local lnUserID, lcUserPicture
lnUserID = 42 && Users.Id && adapt this to your need. 

lcImagepicked = GetPict()
If File(lcImagepicked) && checking whether the user did pick an image and not canceled out.
   * You need to adapt the target path to your needs
   Copy File (lcImagePicked) To (Textmerge("<<Justpath(DBC())>>\<<PadL(lnUserID,4,'0')>>.<<justext(lcImagePicked)>>"))
Endif
You have to adapt this to your needs. This won't work 1:1, as I neither know the field name of your user id nor your specific folder for the user images, this code assumes the user id is found in Users.Id and the users table is open already and the record pointer is on the current user. It puts the picked image into the folder of the database by using JustPath(DBC()).

In the end, it's mainly a GETPICT and a COPY FILE. It's not that complicated. You also won't necessarily need Tetmerge to build the target file name, This could be YourSepcialfolder+transform(USer.Id)+".jpg" and you could only allow jpg images.

I just fear, Mandy, you'll still struggle with the details, as showing you the getpict() function hasn't clicked with you alone. And building the target file name may need another expression, as you didn't tll exactly how the user id is turned into a file name already. You can always provide info about what you already do. In this case how you turn the user id into the file name you set as the image control.picture property is what we need to create the needed file name again.

Always remember, Mandy, we only have, what you post. And since it takes a bit before the next turn and reply, you only get to your solution slowly, if you don't think about that aspect of your questions. You can still do better at that, alone.

Chriss
 
The code that Chris posted is more or less the same what as I had in mind. Just keep in mind that GETPICT() only displays the names of the files: it doesn't show the actual images. If that's not what you want,yo will have to do something like my earlier suggestion, of building a cursor with the images and displaying them in a grid. But that's a lot more complicated.

Another small point: In Chris's code, I would test for lcImagepicked being an empty string, which is what you get if the user cancels the GETPICT() dialogue (although FILE() will also work in that case).

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I use File() to check both that it's not empty and a file. You could pick a file and edit the name in the lower textbox before clicking OK and then have a non-empty lcImagepicked variable that still is not an existing file. Thus I use FILE() to check for both non-empty and correct file selection. You could always ask "who should do this for which purpose?" but some peopole just want to test how trouble-safe an application is.

I was not as paranoid as checking whether the file is an image, actually. Because even if you pick a valid image file name it could be any other file type renamed with a picture file extension outside of the application and beforehand. Again, for the same reason of troublesome users you might go as deep, but that's also a reason to keep this to users you can trust not trying to break things.

There are always other ways of doing the same or similar things and room for improvement.

Chriss
 
Thank you so much Chriss and Mike... I tried it.. and it worked as i neet it...studying it welll so that it will fit my needs.... Thank you so much Chriss and MIke.... God bless....
 
Chris, I must admit I never thought of using FILE() to check that the user didn't cancel (as well as checking that they chose an existing file). Sounds like a good idea.

My only hesitation is that the user feedback would be different in those two cases. If the user simply cancels the dialogue, the action of the program would be to do nothing. But if the user specified a non-existent file, I would think you would want to give an error message or warning of some kind rather than just ignoring it. Just a thought.

Mandy, good to hear that you are making progress. Don't get too bogged down in this detail about checking for a non-existent file. It isn't central to your problem.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike,

thanks for thinking about details. In this case I would just "punish" a user by handling a wrongly edited file name just like not picking a file with ignoring that.

Mandy,

Mandy said:
studying it welll so that it will fit my needs.
this is absolutely necessary, the code works, but only if a database is open and DBC() is a path, it will just copy any image to a file named 0042.jpg (or whatever image type it is), because of the hardcoded 42. The comment after that is a suggestion of what this could be in your real case.

It would be helpful to know the code in the form, that sets the user image.picture property to see how you process the userid into a name. You could do this in several ways, not only turning the ID into a number without or with more or less leading zeros, it's interesting where to get the userid from, and whether you only allow one image type jpg or also png or gif or whatever is available. That's all details. So hopefully you understand that this code is not meant as a solution but just as a usage demonstration.

I even think this is a thread, which demonstrates, how ineffective a forum can be in a case a user can't just take the hint on GETPICT() and do this himself or herself (of course). The usage demonstration code has more parts that need to be adapted than it is a complicated code structure you could only come up with, if you are an expert. Without any checks it's mainly just two lines:

Code:
lcImage = GETPICT()
COPY FILE (lcImage) To ...where you want the image to be with the name you want it to have.

I know that you already know the COPY FILE command and I know I already explained name expressions to you, the reason why COPY FILE needs brackets around the variable name. Otherwise, it looks for a source file that literally is called lcImage in the current directory.

So the only ingredient you really needed is GETPICT(). And even that is optional, as you could also use GETFILE('jpg'), to only pick jpg files. And I think you know GETFILE(). So you could have come up with this on your own, just the GETPICT() function was a useful hint to you that there is a GETFILE() specific for picture file types. If you ask me, it allows too many image types that have no good use case for user photos.

Chriss
 
Thank you so much Mike and Chriss... Its now working according to my needs... You are all great!! My coworker and I no longer argue who will do the copying and renaming of the picture file...

Local lnUserID, lcUserPicture
lnUserID = 42

IF EMPTY(this.Parent.text1.value)
MESSAGEBOX("Please choose a record for image edit!" + CHR(13) + "Click Ok to retry!",0+16,"Information")​
RETURN​
ENDIF

lcImagepicked = GetPict()
If FILE(lcImagepicked)
Copy File (lcImagePicked) To "c:\Graphics 2021\Pictures\" + this.Parent.text1.value + ".jpg"​
MESSAGEBOX("Picture marked and copied to Pictures folder!",0+64,"Information")​
ENDIF

Im not sure if this is correct but its working as i need it....

Thank you so much Mike and Chriss.... and to all.... God bless
 
Well, now the variable lnUserID is not needed. Also - but that is my error - the variable lcUserPicture is declared but the GetPict() result is stored to lcImagepicked.

And let me ask you: What is this.Parent.text1.controlsource?


Chriss
 
Hi Chriss, that is the idnumber chriss Which should be desame with the filename of the picture... so that it will be located by the application to desplay the picture... Thanks Chriss....
 
I know Mandy, you already said that,

but I'd like to see the technical expression, not just the description of what it is.. What do you set as the controlsource of "this.Parent.text1."? That's the question.

Because you should take the controlsource of that textbox, not the textbox value. That's more direct, always make the distinction of data (the dbfs) and presentation of data. The source of data always is the dbfs, not control values, even if control values are coming from dbf fields anyway. That's not a good construct, because at some point the form layout can change and you won't oversee this dependency, while the sorce field in your user table will still exist, it's the better source than using text1.value.

Chriss
 
Don’t use IF FILE(), as it’s not 100% reliable; use ADIR(xx,xx) instead. See VFP Help.

Regards, Gerrit
 
Oh I see chriss… i actually have a combobox, that is link to cursor… that when a name is chosen, The textbox would appear or show the idnum which is the “this.Parent.text1.value” but with what you have said, i’ll try to understand and change it Chriss… thanks so much….

Thanks Geritt
 
Gerrit, why do you say FILE() isn't 100% reliable? What in particular is wrong with it?

I know that some people are confused because they don't realise that the function will find a file if it exists anywhere on the FoxPro search path rather than just the current directory (unless you specify an absolute or relative pathname with the file), but that has nothing to do with the function's reliability.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I tried what I find people say - that the FILE() function reports false positives. Let me check...

It's true that FILE() will report the existence of a file if that file is also part of the EXE. You can then specify a path at which the file does not exist and even specify a path that doesn't exist in itself. VFP will first only look for JUSTFNAME() within the EXE and return .T., if it finds the file within.

To cover that concern, ADIR() is a good function to ensure the file is only searched at the specified path. I don't expect user photos to exist within the EXE, but in some cases, they might be brought to Mandy and her coworker with generic names like "1.jpg", which could also likely be the name of a jpg included in the EXE as part of the UI design.

So, it's a valid concern, Gerrit, thanks for pointing it out. Still, the false positives are of low concern, COPY FILE will only copy from hard drive, so even if 1.jpg exists within the EXE but also exists and is picked from a folder on the hard drive, that is what will be copied, since COPY FILE doesn't first look for the file of that name within the EXE. Actually, to copy a file from within the EXE to somewhere else you need to use FILETOSTR(), which reads a file from within the EXE, not COPY FILE. That makes the concern less hard, but since I had a concern with tempering of the filename which already is not usually happening from the two users who want to use their application correctly and don't need to break it, as they own and maintain and program the source code.

Nevertheless, this is how it can be used overall:
Code:
Local lcUserPicture

IF EMPTY(this.Parent.text1.value)
   MESSAGEBOX("Please choose a record for image edit!" + CHR(13) + "Click Ok to retry!",0+16,"Information")
   RETURN
ENDIF

lcUserPicture = GetPict()
Local Array laDir[1]
If Adir(laDir,lcUserPicture)=1
   Copy File (lcUserPicture) To "c:\Graphics 2021\Pictures\" + [highlight #FCE94F]this.Parent.text1.value[/highlight] + ".jpg"
   MESSAGEBOX("Picture marked and copied to Pictures folder!",0+64,"Information")
ENDIF

I'd only consider not keeping this UI dependency, as the source of the file name should be the id field of the user table, not the textbox that displays it. Aside from the fact a user id should be just the key the database and code and programmer sees and knows, not a field displayed to the application users at all. It's not data you show or even enter or modify, it is a key created by the database and to identify a record for code, not for an application user.

If you get there and understand the importance of that, Mandy, you'll eliminate these fields from forms. And then your image browse button stops working as you don't remember it took the user id from this text box instead of taking it from its source, the table.field.

Face it, once you have a user id as autoinc, it's a readonly field. Cyopiying it to a textbox, the textbox.value is editable, you could use an edited value to name the user image and that will not be writable to the user id field in the DBF, so you have a mismatch there. Take the user id from the usertable field that stores it, from nowhere else. It could even be worse and you use a char field for the user id that actually is editable.

Chriss
 
Chriss said:
FILE() will report the existence of a file if that file is also part of the EXE

I don't dispute that. But my question to Geritt is: Why do you say FILE() is not 100% reliable? The fact that it finds files within an EXE is documented behaviour; there is nothing unreliable about it.

Regarding the use of ADIR() as an alternative to FILE(): the problem there is that ADIR() can only search one directory at a time. If the target file can exist anywhere on the search path, you would have to loop through all the directories returned by SET("PATH").

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top