Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Articles
Recherche: 

Considerations when building Web applications Part II
Michel Fournier, January 1, 2003
This article is a follow-up with more advanced details in regards to the first article of this series in our December issue which included a tip on dealing with stylesheets. This one allows you to customize your HTML code based on the user, assuming each user has some ways to setup some specific sty...
This article is a follow-up with more advanced details in regards to the first article of this series in our December issue which included a tip on dealing with stylesheets. This one allows you to customize your HTML code based on the user, assuming each user has some ways to setup some specific style in his profile within your application. This article contains code in Visual FoxPro but can easily adapted to fit any other development environment.

Cascading style sheets

In the first article, we saw how to assign a stylesheet based on the user's browser. This is good as it allows you to concentrate specific way of doing those styles in separated stylesheets. On top of that, you can also add a stylesheet customized as per the user settings. That assumes that you have some style settings per user in your Web application stored in a member's table, for example.

Usually, I will put all my styles in one stylesheet. Then, I will rely on a user specific stylesheet for specific style based on the user. This process is then called "cascading stylesheet". As the styles are already defined in the main stylesheet, you are just repeating here specific styles in regards to the user which will take priority over the pre-defined styles. Or, another good way is to define only generic styles in your main stylesheets. Then, you just add the specific user's style after. There are some goods and bad things in this. The first one allows you to benefit of all styles no matter is the user is logged or not. The second one will only make specific styles available when the user is logged. This is why I prefer the first approach.

Saving user's value in a member's table

So, we know that specific styles are defined in each user's record in your members table. Lets assume that the following field values are defined for a specific user:

FieldValue
Font13
Table626262

We can then assume that we have our main stylesheet loaded and what needs to be done in order to have it fully completed is to incorporate the following values in our user stylesheet. Our user stylesheet may looks like the following:

.Texte
{  
   Font-Family: Arial, Helvetica, sans-serif;
   Font-Size: <%=Font%>px;
   Color: #000000;
}

TABLE.Test
{
   Border: 1px #626262 solid;
   Background: #<%=Table%>;
   Border-Collapse: collapse;
}
Assuming you have a framework such as West Wind Web Connection or any other framework which contains some methods to parse the values into a form, you will then be able to obtain those two styles based on the user's settings.

The following code may return some HTML which takes care of the styles:

FUNCTION GetStyle
LOCAL lcHtml
lcHtml=''
lcHtml=lcHtml+'<script language=JavaScript src=/Javascript/Stylesheet.js>'
lcHtml=lcHtml+Response.ExpandTemplate(gcClientFat+'StyleSheet\UserSpecific.html',,,.T.)
RETURN lcHtml

In this example, it is assumed that the JavaScript line returns a proper stylesheet based on the user's browser. See the first part of this article for the details. Then, we have a gcClientFat variable which holds a FAT equivalent of your Web site root. UserSpecific.html contains the two styles as defined earlier.

So, this means, whenever a user is logged to your Web application, you are in position to have the styles to be adjusted on that user. For every process, you can then call GetStyle() which will return the proper style header in your HTML code.

Improving performance

But, what is wrong with all this? Well, at first, nothing terrible, it's just that some considerations need to be taken, especially if you have a lot of user's styles. Lets assume we have UserSpecific.html to have a size of 4k. It's not mostly the process of handling all this from the record level which is intensive but the aspect that this 4k file will be downloaded for all transactions. If you have users using your application intensively, that represents an additional bandwidth of 4k for every transaction. You will soon discover that you would like to have something better in order to obtain the same result but with a better flexibility.

Well, there is always a good way to do things. Here is one in this case. Browsers are smart enough to read from cache. Despite the fact that this is usually a source of problems, in this case, we can benefit of it greatly. Using the base approach, nothing is cache as all this style code is returned on top of each transaction you are doing so this doesn't allow a chance to the browser to cache it as a file as it's not a file. We need to find a way to make it cached. In order to obtain that, we need to deal with the style as a file in its entire entity. The concept is simple. Generate a user's style file when necessary and make reference to that file instead.

Keeping dynamic capabilities

I can already here some that say "Well, it has to be dynamic! What would happen when the user will change styles?". If being done with care, you will take care of all those individual issues in a flash. Lets start by creating a directory called "StyleSheet" where each individual stylesheet files for each user will exist. The first rule is to check if a stylesheet exist for that particular user. If it doesn't exist, we will create it. The following enhancements in our GetStyle() function can be implemented:

* expN1 Member ID
FUNCTION GetStyle()
PARAMETER tnNoMember
LOCAL lcMember,lcHtml,lcHtmlStyle
lcMember=PADL(tnNoMember,6,'0')
lcHtml=''
lcHtml=lcHtml+'<script language=JavaScript src=/Javascript/Stylesheet.js>'

* If the stylesheet file exists
IF FILE(gcClientFat+'StyleSheet\'+lcMember+'.css')

   * Do something if necessary
   lcHtml=lcHtml+''

   ELSE

   * The stylesheet doesn't exist, lets create it
   lcHtmlStyle=Response.ExpandTemplate(gcClientFat+'StyleSheet\UserSpecific.html',,,.T.)
   STRTOFILE(lcHtmlStyle,gcClientFat+'StyleSheet\'+lcMember+'.css')

ENDIF

* Add the stylesheet
lcHtml=lcHtml+'<link rel="STYLESHEET" href="'+gcClient+'StyleSheet/'+lcMember+'.css" type="text/css">'

RETURN lcHtml
It is assumed that gcClient contains the URL to your Web site. We can have something like http://www.mywebsite.com/.

Browser specific

Back to our initial purpose, we wanted to return styles based on the browser. As for the user specific stylesheet, we are confronted with the same situation. So, lets add some rules in our logic to take care of that. Another important point we have to consider is the fact that the user may switch browser thus we need to know about it in order to overwrite the existing user specific stylesheet with one that fits within the specific browser. The detection of a browser change relates to saving the last transaction browser used and verify at each transaction if a switch occur. When this is the case, we will regenerate the user specific stylesheet based on the browser.

* expN1 Member ID
FUNCTION GetStyle()
PARAMETER tnNoMember
LOCAL lcMember,lcHtml
lcMember=PADL(tnNoMember,6,'0')
lcHtml=''
lcHtml=lcHtml+'<script language=JavaScript src=/Javascript/Stylesheet.js>'

* If the stylesheet file exists
IF FILE(gcClientFat+'StyleSheet\'+lcMember+'.css')

   * If the user is not using the same browser as the one he used for the last transaction
   IF NOT glIE=Member.IE
      CreateStyleSheet(tnNoMember)
   ENDIF

   ELSE

   * The stylesheet doesn't exist, lets create it
   CreateStyleSheet(tnNoMember)

ENDIF

* Add the stylesheet
lcHtml=lcHtml+'<link rel="STYLESHEET" href="'+gcClient+'StyleSheet/'+lcMember+'.css" type="text/css">'

RETURN lcHtml

* expN1 Member ID
FUNCTION CreateStyleSheet
PARAMETER tnNoMember
LOCAL lcHtml,lcMember,lcUserSpecific,lnOldSel

* Set the user specific style sheet based on the browser
IF glIE
   lcUserSpecific='UserSpecific.html'
   ELSE
   lcUserSpecific='UserSpecificNonIE.html'
ENDIF

lcHtml=Response.ExpandTemplate(gcClientFat+'StyleSheet\'+lcUserSpecific+'.html',,,.T.)
lcMember=PADL(tnNoMember,6,'0')
STRTOFILE(lcHtml,gcClientFat+'StyleSheet\'+lcMember+'.css')

* We replace the value of the IE field in the members table
* This assumes we are on the user record in the members table
lnOldSel=SELECT()
SELECT Member
REPLACE IE WITH glIE
SELECT(lnOldSel)

At this point, we have a user specific stylesheet which will be updated if it doesn't exist or if we detect that he is switching between Internet Explorer browser and another browser.

So far so good, but when there is a need of generating a new stylesheet, there is no guarantee the user will benefit of that immediately. This is because of the cache handling issues by several browsers. Unless the user manually forces a browser refresh, and there is no guarantee that this will work either, he will then force the browser to get the latest version of his stylesheet.

Forcing a browser refresh is one way, in most setups, to get the latest version of a stylesheet. One other consists of just closing and starting the browser again. Depending on your settings, this is likely to work as well. But, we need a bulletproof mechanism which will always work immediately independent of the user browser settings.

Sequencing the user specific stylesheet

I have implemented a technique which works at 100% so far and this has resolved that issue once and for all. The technique consists of sequencing the user specific stylesheet. It is just a matter of adding a number at the end of the file name. So, at first, the stylesheet might be named 0000011.css. The first six digits represent the member ID. The last digit represents the sequence. When we will update the user stylesheet next time, it will be 0000012.css. This is based on the fact that our member ID table won't exceed six digits. You can adjust that based on your specific needs. So, as a new file name is used, the browser won't read from the cache as this file doesn't exist in its cache. Otherwise, the same file name is used and the browser is likely to grab a copy from its cache instead of downloading the latest version.

But, this is not something you will leave as is. You will probably want to set a limit to the sequence and start back to 1 when it is reached. Otherwise, you will end up with large set of numbers without any specific purposes. I usually set it to 20. So, once we reach 20, we start back to 1.

As users are usually not changing browsers that much, the stylesheets usually remain intact for a while. Another thing that would influence the need to update the stylesheet is when the user changes something in his profile within your application. Based on what he changes, you might want to trigger an update of the stylesheet. As this is not something that changes a lot, the sequence will also remain pretty stable.

As by the time you reach 20, a few days would have probably elapsed (and that's quite unlikely to happen unless the user is playing a lot with his settings for specific purposes) and the browser is not likely to remember the specific stylesheet file which had the sequence 1. So, on immediate update of a stylesheet, no matter the local settings, the user will get the latest version of his stylesheet. And, that works well for users switching from different browsers from office to home, for example, as the same rule will apply.

I am not detailing that process here. This is quite easy to implement. For faster process, you can also save the current sequence in the member's table. If it exists, you will read that sequence and see if a related file exists. If yes, you grab it. Otherwise, you create a stylesheet and you update the sequence field with 1.

Cleanup stylesheets

This creates a situation that a lot of stylesheet files remain on the server drive. For those users that are regular users to your application, it doesn't matter that much. But, for those who came to your application once and will only come back on occasional basis or never, this will mean that unnecessary files will remain on the server drive.

It doesn't represent that much of a problem but I prefer to clean something that is not useful. Following the robot approach, as described in the first article of this series, you can easily add a task in it to cleanup files older than 5 days in that directory.

Remember that a stylesheet which doesn't exist will be created on the fly. So, even if you would cleanup all the files in that directory without any timeframe, on the next hit by each a user, the related file will be created. That would then mean that once a day per user, a new file would be created. That is nothing big to worry about it.

Summary

In overall, I've been using that approach on the Universal Thread since a year now. The difference is noticeable as we are saving several kilobytes of transfer on every hit and at the end of the day, this would represent megabytes. Add to that the fact that users are getting their HTML pages faster, you then have a professional stylesheet implementation to benefit of.

Michel Fournier, Level Extreme Inc.
Michel Fournier is a professional, visionary, perfectionist, mostly known for his renowned realizations over the years, designer, architect, owner of the « Level Extreme Platform », formerly known as the « Universal Thread », recognized as one of the longest running Web sites of the planet, also known as a precursor to social networking, product manager, Internet serial entrepreneur, practiced Lean Startup techniques long before they were known, out of the box thinker, using the tenth man rule, specializes in building entire virtual data center solutions, has provided high end IT consulting worldwide, has owned and operated three companies, delivered worldwide renowned e-commerce Web sites, designed and architected two world class top level development frameworks, wrote over 100 IT articles for various sources, presented at user groups, conventions and corporations nationwide as well as in the US, has provided his contribution in political and legal issues to provide a better world, Owner and Senior IT Consultant at Level Extreme Inc., former Architect Software/Application & Project Manager, 7 times Microsoft Most Valued Professional for VB.NET, 7 times Microsoft Most Valued Professional for Visual FoxPro, Developers Choice award for best site at VFP DevCon 2000 Connections in New Orleans, featured in Acadie Nouvelle on October 2003.
More articles from this author
Michel Fournier, February 1, 2007
From the Level Extreme .NET Framework, this small class allows a developer to manipulate easily the content of a directory by the use of a dataset. With the setup of a few properties, a call to the method and the access to the object dataset, you can have access to the file properties of the directo...
Michel Fournier, August 1, 2001
It is interesting to see how something new can evolve. This is the case for the Universal Thread Magazine. We are now at our 3rd issue and we are already overbooked by scheduled articles and hot stuff we have to cover for the upcoming issues. Publishers are sending request for book reviews, wri...
Michel Fournier, October 1, 2002
UTMag/RapoZine team Editors Michel Fournier Claudio Lassala Co-editor Martín Salías Translation coordinators Claudio Lassala Martín Salías Translators Eduardo Vidigal Rodolfo Duarte Fábio Vazquez José Cavalcanti Moacyr Zalcman Fábio Vieira M...
Michel Fournier, May 1, 2006
In this article, Michel Fournier is providing a small introduction to manipulating XML data from VB.NET. The use of XML is now widely used for various purposes such as exchanging data between application, platforms and other environments. XML is a simple and very flexibile text format that can be ma...
Michel Fournier, October 1, 2001
In our daily things we do, sometimes we find ourselves in unexpected situations. Such situations, either in our personal life or from our professional work, require some adjustments in order to walk through them. The ability to take some time to take an overall look of what is happening, apply a bas...
Michel Fournier, March 1, 2007
In this small article, Michel discusses a problem he recently encountered when converting a dataset into XML to be used later on with a XSL transformation to export into an Excel sheet. When null values were present in the dataset, this was creating weird result. This article provides a quite alte...
Michel Fournier, February 1, 2006
This article discusses a simple banner fonctionalities function which can ease the display of banners on Web sites. If your Web site displays banners in GIF, JPG of Flash format, this function could be useful to you.
Michel Fournier, January 1, 2006
There are various ways to authenticate a user to a Web Service. This article discusses one way to do it by the use of Cookies. As it could the case with a Web page sending a cookie to the browser, the same can be used from within a Web Service.
Michel Fournier, February 1, 2006
This article is a follow up on the first part of this article which appeared on our January 2006 issue. In this one, Michel discussed further implementation of getting the authentication from a members table as well as setting up a session per user.
Michel Fournier, December 1, 2003
Visual FoxPro and .NET are two great environments to build business applications with. But, fantastic they are when you combine them together in order to increase the strenght of the flexibility to respond to your client needs. In this article, I will demonstrate a case study in regards to a new ser...
Michel Fournier, December 1, 2002
Over the years, I have been involved in several types of desktop and Web applications. Every time you start a new project, there is always something new you will learn. In this article, I would like to detail some of the issues which are to be considered when delivering a Web based application. Thos...
Michel Fournier, March 1, 2003
The first two articles of this series have been published in the issues of December 2002 and January 2003. In this one, I will talk about graphic issues, how to negotiate with a form to launch his transaction to either within the same window or a new one, how to gather values from one page to anothe...
Michel Fournier, April 1, 2003
In this article, I will proceed with considerations about HTTP server variables being received from a browser and about considerations for opening new windows in your Web application. Relying on the protocol or not When it first started, we didn't ask that question to ourselves as to know ...
Michel Fournier, April 1, 2009
This articles describes the use of CDO.Message to gain the ability to retrieve a URL as a MHT file. It also covers an interesting approach to retrieve a URL even if this one requires a login.
Michel Fournier, January 1, 2006
Data dictionaries has its use and also for Web applications. I see many developers building Web applications who forget about many structured that used to be in place when developping desktop applications. The same should apply for Web applications as it is no different. This article discusses some ...
Michel Fournier, June 1, 2003
DevTeach was held in Montreal from May 10-13, 2003. It presented a new breed of conference. Sessions included both presentation material and, whenever possible, hands-on training. DevTeach brought under the same roof the best speakers available for .NET, SQL Server and Visual FoxPro as well as Micro...
Michel Fournier, May 1, 2002
The Essential Fox conference was held this weekend in Independence, MO. Once again, the Universal Thread team was on site to do the official coverage of the event. It has been a great success, well planned by Russ Swall, the event owner, and his team and well appreciated by the attendees. A total of...
Michel Fournier, April 1, 2002
UTMag/RapoZine team Editors Michel Fournier Claudio Lassala Translation coordinators Claudio Lassala Martín Salías Translators Eduardo Vidigal Rodolfo Duarte Fábio Vazquez Claudio Rola José Cavalcanti Moacyr Zalcman Ricardo Soares Fábio Vieira ...
Michel Fournier, September 1, 2001
Ever wonder how to successfully and rapidly display HTML lists to your users? Well, we all probably already did. However, its implementation differs a lot from sites to sites as we all have our own different approaches. Delivering Visual FoxPro data to the Web as if you would be in Visual FoxPro is ...
Michel Fournier, November 1, 2001
A lot of things happened recently in the Visual FoxPro world and for related technologies. The Great Lakes Great Database Workshop was being held in Milwaukee from Sunday October 27 to Wednesday October 31. That conference which primaly focused on Visual FoxPro has covered a lot of technologies...
Michel Fournier, December 1, 2002
UTMag/RapoZine team Editors Michel Fournier Claudio Lassala Co-editor Martín Salías Translation coordinators Claudio Lassala Martín Salías Translators Eduardo Vidigal Rodolfo Duarte Fábio Vazquez José Cavalcanti Moacyr Zalcman Fábio Vieira M...
Michel Fournier, November 1, 2002
UTMag/RapoZine team Editors Michel Fournier Claudio Lassala Co-editor Martín Salías Translation coordinators Claudio Lassala Martín Salías Translators Eduardo Vidigal Rodolfo Duarte Fábio Vazquez José Cavalcanti Moacyr Zalcman Fábio Vieira M...
Michel Fournier, January 1, 2003
UTMag/RapoZine team Editors Michel Fournier Claudio Lassala Co-editor Martín Salías Translation coordinators Claudio Lassala Martín Salías Translators Rodolfo Duarte Fábio Vazquez Moacyr Zalcman Martín Salías Antonio Castaño Fabián Belo Rafae...
Michel Fournier, November 1, 2001
I have been following several threads on the Universal Thread recently about FTP from Visual FoxPro. I have used an ActiveX for a while to do such a task. I have found that years after years, the problem is that you have to maintain that ActiveX for your own workstation and for every servers or work...
Michel Fournier, July 1, 2002
UTMag/RapoZine team Editors Michel Fournier Claudio Lassala Co-editor Martín Salías Translation coordinators Claudio Lassala Martín Salías Translators Eduardo Vidigal Rodolfo Duarte Fábio Vazquez José Cavalcanti Moacyr Zalcman Fábio Vieira M...
Michel Fournier, January 1, 2006
With the beginning of the new year, Michel resumes some of the highlights of the Universal Thread and what is coming up for the new season.
Michel Fournier, March 1, 2006
When comes time to display the content of a memo field on a Web page, one common task we have to do is to hyperlink specific content. This article discusses about a technique which can be used to hyperlink various types of links as well as email addresses.
Michel Fournier, April 1, 2009
This article describes some basic techniques to manipulate some images in .NET. It covers image resizing, image cropping and the ability to save an image into a JPG high resolution format.
Michel Fournier, May 1, 2007
This short articles provides an approach of important data from an Excel sheet into your application without having the requirement of having Excel installed on the server.
Michel Fournier, August 1, 2002
UTMag/RapoZine team Editors Michel Fournier Claudio Lassala Co-editor Martín Salías Translation coordinators Claudio Lassala Martín Salías Translators Eduardo Vidigal Rodolfo Duarte Fábio Vazquez José Cavalcanti Moacyr Zalcman Fábio Vieira M...
Michel Fournier, July 1, 2001
Recently, I was having problems while working on several projects on my PC. The problems were happening when I had several applications open at the same time. When the problem occured, I had to reboot my PC and then was able to work for a few hours up to a few days until the next reboot. As I was wo...
Michel Fournier, June 1, 2002
UTMag/RapoZine team Editors Michel Fournier Claudio Lassala Co-editor Martín Salías Translation coordinators Claudio Lassala Martín Salías Translators Eduardo Vidigal Rodolfo Duarte Fábio Vazquez José Cavalcanti Moacyr Zalcman Fábio Vieira M...
Michel Fournier, September 1, 2002
UTMag/RapoZine team Editors Michel Fournier Claudio Lassala Co-editor Martín Salías Translation coordinators Claudio Lassala Martín Salías Translators Eduardo Vidigal Rodolfo Duarte Fábio Vazquez José Cavalcanti Moacyr Zalcman Fábio Vieira M...
Michel Fournier, January 1, 2001
Xitech (Europe) produces tools for the Windows software developer. They specialize in FoxPro Developer tools, data and code recovery and security. In this article, we will see an overview of 5 of their tools. You will find more details about each of them from Xitech documentation. To get Xitech cont...
Michel Fournier, April 1, 2006
This article discusses the ability to use Visual FoxPro to schedule a list of tasks to be executed at specific intervals. While there could be the approach of using the Windows Scheduler to execute those tasks, it is always interesting to be able to control everything from within VFP. A small VFP sc...
Michel Fournier, April 1, 2006
This article describes an overview of sending an email from VB.NET. It covers the basis of creating the email functionality in a class and using an instance of that class to define and send the email. The class includes the ability to send to multiple recipients as well as sending attachments. Sendi...
Michel Fournier, July 1, 2002
This is a follow up on my previous article on using SOAP protocol for authentication that appeared in our December 2001 issue. That article was mentioning the use of the SOAP header for authentication such as being able to identify the user for any upcoming hit to your Web Service as soon as the Log...
Michel Fournier, May 1, 2002
UTMag/RapoZine team Editors Michel Fournier Claudio Lassala Translation coordinators Claudio Lassala Martín Salías Translators Eduardo Vidigal Rodolfo Duarte Fábio Vazquez José Cavalcanti Moacyr Zalcman Fábio Vieira Martín Salías Antonio Castañ...
Michel Fournier, July 1, 2002
From recent discussions I had, with several persons from my team, about common patterns which occur in the evolution of the Universal Thread, I thought it would be nice to write an article about it. Basically, within the evolution of a product, there are some similitudes which are sometimes interest...
Michel Fournier, June 1, 2001
Welcome to our first issue of the Universal Thread Magazine. We kept receiving many requests to have such a media available on the Universal Thread, so we decided to release our first issue this month. Many people have mentioned an interest to either have such a magazine for the pleasure to read abo...
Michel Fournier, December 1, 2001
The Visual FoxPro Zone evolves As many of you may have seen, the Universal Thread Visual FoxPro Zone is evolving quite fast. In the last month, we added new content in it. As usual, the most popular option is the Toledo Wish List. Several entries are created every day. This is the place to co...
Michel Fournier, January 1, 2002
It's January 3rd, 2002, I am writing this editorial at 20h32 EST. The Christmas break is over but was it really a break? More and more, years after years, I keep seeing a lot of persons online during Christmas day or a few minutes before the new year. And, I mean, they are online as per their own ti...
Michel Fournier, January 1, 2004
In December 1993, a great history started when a small Web site known as the Visual FoxPro Yellow Pages started. Basically, a site providing ads for Visual FoxPro developers such as jobs and consulting services. Known also as the first Visual FoxPro site, it has evolved quite fast during the first t...
Michel Fournier, January 1, 2006
In the recent months, I have been involved in settings various projects at client sites, as well as for Level Extreme Web sites, which involved the support of uploading image files from an Internet browser. The process of supporting that capability in your application, either from a desktop of from ...
Michel Fournier, December 1, 2001
The Microsoft SOAP client provides access to any Web Service. Once the object is instantiated and the location of the WSDL file given, you are ready to go to access any method. Thus, based on what is supported by the Web Service, you can query to obtain various types of content such as string and bo...
Michel Fournier, February 1, 2002
On January 15th, 2002, an important joint took place for our magazine. The Universal Thread Magazine and RapoZine magazine, an online magazine available for the Portuguese developers community, joined to create UTMag/RapoZine. Effective from this issue, both magazines will offer the same technical c...
Michel Fournier, July 1, 2002
Show seconds in a readable format If you need to check elapsed time with seconds() or a datetime value, this function allows you to display the elapsed time in a human-readable format, that is, hours:minutes:seconds, instead of the total number of seconds. Just pass a number of seconds as...
Michel Fournier, August 1, 2002
Updating your DLL on IIS This has been a common question in the recent months on the Universal Thread. More and more, developers have the need to use a DLL under IIS. However, the fun part comes when you need to update it. As soon as it kicks in, you can't update your DLL anymore as it re...
Michel Fournier, November 1, 2002
Use MemLines() to wrap text lines When you need to wrap some text at a given width (say 75 characters per line), you do it easily with: SET MEMOWIDTH TO 75 lcMemo = lcNewMemo = "" _MLINE = 0 FOR i= 1 TO memlines(lcMemo) lcNewMemo = lcNewMemo ; + MLINE(lcMemo,1,_MLINE...
Michel Fournier, September 1, 2002
Getting image width and height Probably the most flexible way to extract the width and height of an image is by the use of the image object. All is needed is to load the image in the object and get the values from the Width and Height properties. LOCAL loImage,lnWidth,lnHeight loIma...
Michel Fournier, October 1, 2002
Extracting BMPs from general fields As a complement with last issue's article on image handling, yo can find useful this little function. If you got convinced that using general fields to handle images is a bad idea, you can decided go back to independent image files. But then you'll...
Michel Fournier, June 1, 2001
It was a year ago. The DevConnections team was holding the Visual FoxPro DevCon 2000, the SQL Server Connections and the DevCon 2000 in New Orleans, Louisiana from May 14 to 18, 2000. For the first time, attendees were able to attend sessions from more than one conference at the same time. This offe...
Michel Fournier, September 1, 2001
Is there a speed limit on the Internet? Probably not, because there is so much things we can do in a short time about delivering various type of content to the community. I remember a week ago we shared an idea about helping the promotion of user group activities around the world. A week ago it was ...
Michel Fournier, March 1, 2002
In the last month, we received dozens of emails from satisfied persons in regards for our initiative of opening the magazine and the Universal Thread in general for additional communities such as the Portuguese and Spanish communities. Regulars members of the Universal Thread, new members, Microsoft...