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

Clickable label/variable to website 3

Status
Not open for further replies.

SitesMasstec

Technical User
Sep 26, 2010
502
BR
Hello colleagues:

I have a memory variable and I am able to show it in a form, that's ok (Label box, Caption: =lblNome)

Now, I want to transform it as a link to a website, that is, the lblNome label to be clickable, and when I run the form and click on the label, it opens the default browser and go to a website.

I already do this with images, for many years. Now I want to do the same with a variable. Is it possible?


Thank you,
SitesMasstec
 
Take a look at the Hyperlink Label Foundation class in the classes that come with VFP.

Tamar
 
Wow! It worked fine.[pre][/pre]

Nice tip, Tamar! Thank you.

I have already used the hyperlinkimage, but had never used the label (I had not thought it existed!).


Thank you,
SitesMasstec
 
It's also quite easy to construct your own hyperlink. I've got this in my main class library.

It's simply a label, with FontUnderline set to .T., ForeColor set to 0,0,255 (blue), and MousePointer set to 15 (hand). You can put anything you like in the Click event, but as you want it to go to a particular website, you could ShellExecute() the relevant URL.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Looking into the code of the hyperlinklabel and the hyperlink foundation class makes you wonder what's going on on the minds of those Microsoft programmers.
All that code, and still if you set a URL starting with https:// the validurl method of the hyperlinkbase class prepends " to it, not recognizing https:// as valid scheme of the URI.

If you just put in the method prepends http:// and any internet server usually redirects http requests to https, if that's what's used for a domain, but that's not the best way to get to the final target, ideally you nowadays surf only to https sites and not get there by redirection.

Besides that problem you also need setobjrf.prg

If I set default to my project home directory and not the VFP Home() folder, the mouseenter event on the hyperlink label will error when not finding setobjrf.prg. It's a dependency you have to cater for when finally building your EXE.

I'd rather go for Mike Lewis solutiuon. The hyperlink label in the end also uses ShellExecute, unless iexplorer.exe is found to be the default internet browser, then it uses InternetExplplorer.Application automation, whereas that has no big advantage, other than being enabled to specify the target frame of the navigation (if you know how little that means). Shellexecute will also use the IE, if it is the default browser, anyway.

The only advantage of the hyperlink label class that becomes obvious to the user is that a visit of the hyperlink turns the color from blue to violet. VFP forgets that visited state when you restart the form, though, so that's not implemented thoroughly, either.

I don't know, I'd recommend you use Mike Lewis' idea, but when it works okay for you, no need to change it, of course.

Chriss

PS: how to fix the validURL code? You can't just replace http with https, unfortunately sites still running on http won't be reached when navigating to https:\\ there's no automatic redirection for that, too. So the best to do is just to also accept https:// as start of the lcURL, too. It's not enough, though, as the code also examines the 5th position to be :, which only is true for http: linkes, not https.

So in short: Here's a fixed validurl code for the _hyperlinkbase class of the _hyperlink.vcx in VFPs ffc folder (FoxPro foundation classes):
Code:
LPARAMETERS tcURL
LOCAL lcURL

IF EMPTY(tcURL)
	RETURN ""
ENDIF
lcURL=ALLTRIM(tcURL)
IF NOT LOWER(LEFT(lcURL,5))=="http:" [highlight #FCE94F]AND NOT LOWER(LEFT(lcURL,6))=="https:"[/highlight] AND NOT LOWER(LEFT(lcURL,5))=="file:" AND ;
		NOT LOWER(LEFT(lcURL,4))=="ftp." AND (LOWER(LEFT(lcURL,4))=="[URL unfurl="true"]www."[/URL] OR ;
		INLIST(LOWER(RIGHT(lcURL,4)),".com",".gov",".net") OR ;
		(NOT SUBSTR(lcURL,2,1)==":" AND NOT LEFT(lcURL,2)=="\\"))
	lcURL="[URL unfurl="true"]http://"+lcURL[/URL]
ENDIF
IF SUBSTR(PADR(lcURL,5),5,1)==":" [highlight #FCE94F]OR SUBSTR(PADR(lcURL,6),6,1)==":"[/highlight]
	lcURL=STRTRAN(STRTRAN(lcURl,"\","/"),"///","//")
ELSE
	IF NOT LOWER(LEFT(lcURL,4))=="ftp."
		lcURL="file://"+STRTRAN(STRTRAN(STRTRAN(lcURL,"\","/"),"///","//"),"//","/")
	ENDIF
ENDIF
RETURN lcURL

Much more could be done, but that's the least you should change to use it correctly with https:// based URLs, too. There's a hint on accepting some ftp links, though the start of ftp:// is not checked. There's only a small subset of TLDs (gov, com, net) accepted, but once you have a full URL beginning with either http or https this can also be org, country specific and any other type of top level domains, anyway, so that's not needing to be extended, it's only there to accept short URLs with neither https nor http to also work with the http:// prefix. As already said it won't necessarily work to then automatically prepend so that still is just http://

Why does https vs http matter? If you log in through a web page targetting a http URL your user/password will be transferred unencrypted as plain text and thus this request is susceptible for hacking your password. But the security concern starts earlier than that, if you navigate to a URL with https instead of the http protocol the connection is started by a process that not only establishes encrypted communication between your PC and the server, it also ensures you connect to that server. You might say how could a URL go to any other server, no matter if I navigate to it by http or https? To explain that I would need to dive in deeper into the topic of cryptography and certificates used for the https protocol that not only are the basis of the encryption but also a signature certifiying the source or target of the communication is to that exact domain and not hijacked somewhere else. It starts by a DNS lookup over https also being more secure than over http.

All that said, many browsers will warn when you visit a server by http and you can trust the link to continue anyway, but you see that's already a mechanism that pushes the usage of https for any website.

Important disclaimer: This change only gets rid of the wrong prefixing of http:\\ to URLS starting with https:\\, it does not provide more security, it does not enforce https usage, nor does it check whether a website uses https vs http, that would also beyond the scope of the method, so it leaves the job of warning about navigation to an unsecure site to the web browser and that's fine. But now you can simply already specify https:// URLs and not get wrongly corrected.
 
One of the reasons I created my own hyperlink class was so that it could do more than simply visit websites.

For example, I've got an invoice form, showing all the usual details you would expect, including the basic customer details. But the customer's name is a hyperlink, and when the user clicks on that link, it opens the customer's own form.

I use this sort of device throughout my user interface. It works well because it is familiar to the user: it behaves exactly as they would expect. I could achieve the same goal with a command button, but the hyperlink has the added advantage of often being able to convey more information while taking up less space.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike,

I think that's one more reason in your favor. I also wonder if it's worth fixing the https:// issue in the ffc class, because once you just shellexecute a URL it will turn out to work or not, be automatically expanded or not, the browsers have their own means of accepting a www. link to mean http(s)://www, for example, or even prefixing www. if the URL ends in one of the major top level domains like .com and others.

It's even a bit questionable whether a validURL method should correct things like turning backslashes to slashes, etc. That's not the job of a hyperlink, that's either the job of the browser used or the server to accept or reject things like that.

So your mechanism isn't only simpler, it's also offering more options. I am reminded of how the VFP taskpane project establishes an internally used scheme of "vfps:" in the BeforeNavigate2 method of the panebrowser class of the foxpane.vcx

So, to add in to the topic of how to add a clickable link to a VFP form, you could also embed a webbrowser control. That's quite over the top, to just have a link, though.

There's also the EnableHyperlink property of the Editbox that allows links within any text to become active, depending on the _VFP.Editoroptions the usage of the link then requires pressing CTRL or not needing to do so. And you could turn an editox transparent, remove the border and scrollbar and make it look like a label that way. It's not too far fetched to make use of that.

Chriss
 
Mike: so, you can create a hyperlink which can do the same as the label hyperlink class. Good! VFP 9 is very flexible to do things.

Chriss:
1) setobjrf.prg is always in my projects (I have not put it there, it appears in the project as soon as I run the main program in the project). My projects are always in folders other than VFP Home() folder.

2) about http/https: in the LabelHyperlink my ctarget property is: =yEndePortos1
and the variable yEndePortos1 is: freightanchor.com/resources-sea-ports-codes
I do not need to put http:// or https:// in front of the site address

Note: I am using VFP 9 SP2


Thank you,
SitesMasstec
 
http or https depends on what the server provides, it does not at all depend on your foxpro version.

When I put this address into a browser (again, it doesn't depend which browser and which version of it) it turns out this serves the result page via https, so the full address will have https:// in front.
If you use that the VFP hyperlink class will not work and put http:// in front. If you leave it at freightanchor.com/resources-sea-ports-codes the hyperlink code puts http:// in front, which is "good enough" to find the website, but your browse will be redirected to https:// address and so you actually should start at https:// in the first place, also for the reasons about https I explained above.

That it works is not telling that it's not important. Yes, it works, because both servers and browsers correct things that are not initially completely right.

What's bad about Microsofts hyperlink class code is that even back when it was programmed https was already a thing, so shame on that code. It was already clear your address needed to either use https:// or no full URL to work based on the hyperlink label as using it with https:// URLs which are the norm today would cause an error. You can continue to use it, but never prefix with that would break it, and that is a shame, actually.

Chriss
 
A label acting as a link is as simple as this in its click event:

Code:
DECLARE INTEGER ShellExecute ;
 IN SHELL32.dll ;
 INTEGER nWinHandle, ;
 STRING cOperation, ;
 STRING cFileName, ;
 STRING cParameters, ;
 STRING cDirectory, ;
 INTEGER nShowWindow 

ShellExecute(0,'open',This.Caption, "", "", 1)

And, as Mike said:
Mike Lewis said:
with FontUnderline set to .T., ForeColor set to 0,0,255 (blue), and MousePointer set to 15 (hand)

It can be as simple as that. Just add the https:// to your link. If you only want to display freightanchor.com/resources-sea-ports-codes you could put into a new label property, like cURL or just use the tag and change the code above to use that property and you're also having the feature of links in browsers being a more user friendly caption than the technical address.

In the end, the hyperlinklabel does the same with ShellExecute. You can incorporate more features like URL completion, but I just tested and ShellExecute itself also recognizes the cFilename parameter is a URL, if it at least starts with no matter if you add or not, so even pure ShellExecute without all that surrounding code of the hyperlink class is working fine for most cases, unless you butcher your URLs too much, like shortening it to just freightanchor.com/resources-sea-ports-codes, also a httprequest class would not accept that as a URL, check it out:
Code:
loHTTP=CreateObject("WinHttp.WinHttpRequest.5.1")
loHTTP.open('GET','freightanchor.com/resources-sea-ports-codes')

This will display the error messge "OLE IDispatch exception code 0 from WinHttp.WinHttpRequest: [highlight #FCE94F]The URL does not use a recognized protocol[/highlight]". Every URL has to start with a scheme or (as the error message refers to it, here) protocol. Just inform yourself and read a wikipedia article each day. Like
That a url without something as http:// or ftp:// or other schemes works in a browser is merely a convenience for users typing a URL. Technically the browser then will try what works. But also technically, a class like WinHttp.WinHttpRequest.5.1 or also MSXML2.ServerXMLHTTP won't accept an incomplete URL. The usage of hyperlink with the shortened URL only works based ion the error tolerance of it. Unfortunately that error tolerance is having errors, though. Besides it's much convoluted code to get a two liner working with questionable features.


Chriss
 
Just to mention:
MegaFox: 1002 Things You Wanted to Know About Extending Visual FoxPro - page 119 said:
Creating your own hyperlink classes (Example: frmHl02.scx)
In fact, when we started to look into this topic in more detail we quickly realized that the
best way to implement a browser-independent hyperlink class [highlight #FCE94F]was not to try and utilize the
hyperlink base class at all[/highlight]. Instead we turned our attention to the Windows API in general, and
the SHELLEXECUTE() function in particular.

Thank you,
SitesMasstec
 
Indeed,

and that's what Mike suggests and I agree with, after having found a bug in the FFC hyperlink classes.
So will you change to what Mike and I suggest? Or why did you post this quote?

By the way, Microsofts classes also are not magic in terms of how the finally start the standard browser, in case it's not Internet Explorer the FFC hyperlink class also uses ShellExecute.

There also is one reason to not only validate but also try to autocomplete a given URL: If ShellExecute doesn't recognize a string to be a URL it will try to find a file to open and fail. That's another reason to feed in complete URLs into ShellExecute, because it's only the function that's most famously able to execute the associated application for a file type. ShellExecute can also start the default browser, when the filename parameter is a URL. It also accepts some shortenings, but something with .com in the string is not enough, for that matter, so when you switch to using the core solution of ShellExecuting URLs, you better not work with shortened forms of URLs, even if browsers work with them. The difference of a browser vs ShellExecute getting the URL as a parameter is that when you enter something into the address box of a browser it knows it's meant to be a URL, even when it's a short format a browser will try to make the best of it, guessing it could prefix ShellExecute mainly expects a filename, not a URL, it's not the major use of ShellExecute to start a browser and let that navigate to a URL. Therefore you need to make it obvious to ShellExecute the passed in parameter is a URL and not a filename. A .com somewhere in the string and usage of slashes instead of backslashes is not unmistakenly pointing out a URL.

Starting the filename parameter of ShellExecute with http:// or https:// is not only a little hint for ShellExecute, it makes it total obvious and ensures, ShellExecute will deal with that as a URL and find the standard browser to start it and pass in that URL to navigate to it.

So when you switch to that simple solution, just ensure the URLs you use are interpreted as such, there's no parameter like a flag or a boolean true/false pointing out whether the ShellExecute parameter is a filename or a URL, so the URL has to point out being a URL, which it easily does by starting with http:// or https:// - do you now understand why I stress this so much? You don't want to end up with something that works for some URLs, but not every URL and not know why.

Chriss
 
I still wonder why you quoted MegaFox, but perhaps it's because I mentioned the hyperlinkbase class in a previous post.

Notice: There is a _hyperlinkbase class in the library HOME()+"Ffc\_hyperlink.vcx", that's not what MegaFox is talking about, they talk about a base class or better native class you have in FoxPro, those base/native classes are the list of classes VFP has from which any further class has to inherit, these are all the classes you get listed into an array by ALANGUAGE(arrayname,3):
Code:
For lnI  = 1 To ALanguage(laClasses,3)
   ? laClasses[lnI]
EndFor

So, if you meant to say that the error I found is unimportant, because as MegaFox says it's not based on the hyperlink base class, you're wrong, the _hyperlinkbase class is the basis of all the final FFC classes _hyperlinkimage, _hyperlinkcommandbutton and _hyperlinkimage. Just sorry, I forgot the underscore. And so this error is important to know, because every link starting with https:// you'd use with these FFC classes will result in the validurl method to prefix http:// so the link it tries to visit then will start with both and that won't ever work. You will know better than me what MegaFox actually talks about, but I guess it's their own take on a hyperlinklabel class, neither the FFC nor the hyperlink native bae class.

What does work with the _hyperlinklabel and the other FFC hyperlink classes all based on _hyperlinkbase are all URLS that NOT have https:// in front. So http:// URLs work as that's not changed by the validurl method, but also URLs like your URL, that are shortened. It's still not universally usable and it has so much unimportant sidefeatures, I'd not recommend it, even with my fix, because who knows what else is wrong in there. I already scratched that a validurl method not just validating but acutally autocompleting URLs is not the job of a hyperlink, that's bad programming style and a sign for more problems in the design of it.

And, to come back to VFPs native base classes, if you run above code, there also is a Hyperlink class. VFP has a native Hyperlink class, which is also the basis of the FFC classes, because in their _base.vcx they subclass every class possible, also _hyperlink, which is inherited in _hyperlinkbase.

Confusing? Well, ask MS what's the deal with that, I'm just the messenger of all of this. I can just say that the FFC classes actually extend the features the native hyperlink class also already has, so it's not worthless, but the URL validation simply has a problem and you can, as said often enough, rather just use ShellExecute() and its feature to start the standard browser, if the filename parameter of ShellExecute is a URL, or more precise, is considered a URL by ShellExecute. That means more attention to what URLs you can passs in.

And another alternative to the FFC _hyperlinklabel ...image or ...commandbutton actually is the native hyperlink class that VFP also has and which you also could use directly, without the added code of the FFC classes, it will just use IE and on modern OSes fail to do so, as you'll be informed Microsofts browser now is Edge. It's not funny, but indeed the FFC classes avoid calling the navigateto() method of the base class they all inherit. Conclude what you like from that.

If you're fine with all your URLs, stick to what you have got working, if you encounter problems, you know where to look for a simpler and better solution.

Chriss
 
Chriss:

I used _hyperlinklabel class.(There are also _hyperlinkcommandbutton, _hyperlinkimage and _hyperlinkbase classes from the library _hyperlink.vcx)

I went to Magafox to read basic information about the hyperlink classes (as I am not experienced in using VFP classes) as you and Mike advise me to avoid. And I mentioned it just to show you that other experts advise the same.

We know that much has changed in the web since Megafox was published, in 2002.

So, of course I will follow your and Mike's advice (to use ShellExecute). Thank you for opening my eyes.

If I could shout something loudly to be heard, it would be: "Microsoft, please, we are waiting for VFP 10!"


Thank you,
SitesMasstec
 
SitesMasstec,

thanks for pointing that out.

Indeed what changed since 2002 is how many sites use https (in short secure http). That alone perhaps was enough to not find the error in the past and easily, today.
I hope you also understand what to do and that it's part of the change towards using ShellExecute to mend your URLs, because
Code:
DECLARE INTEGER ShellExecute ;
 IN SHELL32.dll ;
 INTEGER nWinHandle, ;
 STRING cOperation, ;
 STRING cFileName, ;
 STRING cParameters, ;
 STRING cDirectory, ;
 INTEGER nShowWindow 

? ShellExecute(0,'open','freightanchor.com/resources-sea-ports-codes', '', '', 1)
Will result in 2 and not start a browser.

Either complete your URLs or write a URLcompletion routine that works better than MS validurl method. If you're not sure about that, the most important thing is that ShellExecute will at least indirectly tell you, whether your URL completion works, if it returns a value below 33 that means it didn't work, so you could always start with your unmodified URLs, then in the next step try to prefix " then " Though, it may finally be a browser that gets started and fails to navigate to a URL.
Ideally, when you successfully arrive at the intended web page, just compare whether the URL shown in the browsers address bar is actually the URL you initially passed in, if not, you better use that final URL in your link collection, that at least spares a few redirections.

Chriss
 
SitesMasstec,

Good to see that you are making progress with this.

I went to Magafox to read basic information about the hyperlink classes (as I am not experienced in using VFP classes) as you and Mike advise me to avoid.

Just to be clear, I wasn't really advising you to avoid the hyperlink class. It's just that I often find it easier to create my own class than to try to understand a generic class from elsewhere. The foundation hyperlink label class is a good example of that. It has around 15 custom PEMs, with maybe a hundred lines of code, whereas my version only requires the setting of three properties and at most just a few lines of code.

But that's just my preference. I know other developers who make good use of the foundation classes.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike,

have you read about the bug in the validurl method? It does make a big portion of links that start with https:// unusable. Even if you fix that, I would rather use the direct Shellexecute method and my own URL completion routine that's tailored to the URLs I would like to use. Or rather have a go to complete URLs I have in shortened form as at best you pass in full URLs to ShellExecute.

Chriss
 
Yes, Mike, Chriss, it is working fine, thank you!

I put an image in a form and in the

ToolTipText=Cadastro de Portos


Then in the image:

Click event:
Code:
DECLARE INTEGER ShellExecute ;
 IN SHELL32.dll ;
 INTEGER nWinHandle, ;
 STRING cOperation, ;
 STRING cFileName, ;
 STRING cParameters, ;
 STRING cDirectory, ;
 INTEGER nShowWindow 

ShellExecute(0,'open','[URL unfurl="true"]https://freightanchor.com/resources-sea-ports-codes',[/URL] '', '', 1)


MouseEnter event:
Code:
LPARAMETERS nButton, nShift, nXCoord, nYCoord
this.MousePointer= 15   && Hand


MouseLeave event:
Code:
LPARAMETERS nButton, nShift, nXCoord, nYCoord
this.MousePointer= 0   && Default



Thank you,
SitesMasstec
 
Fine.

You don't need to program MouseEnter and MouseLeave, you can just set the image.MousePointer property to 15 and the mnouse pointer will automatically change to the hand while the mouse hovers over the image and back to normal when the mouse leaves.

Chriss
 
Oh, nice tip, Chriss, thank you!

I did the change and it works the same good, with less code!


Thank you,
SitesMasstec
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top