Welcome to Foxite.COM Community Weblog Sign in | Join | Help
<March 2007>
SuMoTuWeThFrSa
25262728123
45678910
11121314151617
18192021222324
25262728293031
1234567

Post Categories

Navigation

Syndication




VFP can do Double Byte Character Sets

Much has been written about the double byte character sets already.

Steven Black has an excellent article on his site written by margaret Duddy, look at http://www.stevenblack.com/INTLUsingAsianCharacters.asp

 

Also Rick Strahl has written about his thoughts and solutions about this, in one excellent article on http://www.west-wind.com/presentations/foxunicode/foxunicode.asp

 

Both articles helped me in creating the solution I offer here.

About this article.

This article is written with three goals in mind.

First and for all I want to show that it is rather easy to create VFP applications that can display MULTIPLE Double Byte Character Sets AT THE SAME TIME.

Secondly I want to show that accessing non - VFP sources is relatively easy.

Third, I hope to show that “thinking outside the box” can give you results that you cannot achieve with VFP alone.

About the customer.

Some time ago I was approached by a company in the Netherlands that needed an application.
This company manufactures products for leather processing, think of leather tanning, conservation, coloring et cetera. These products are shipped worldwide.

Due to the divers nature of the products they ship these products with product information, information on health issues when using the products, handling of the containers, security descriptions and more.

They ship these products to all kinds of countries, from western countries as well as to Asian countries and Eastern European countries.

 

This brings a special requirement to the labeling process. The labels need to display the text in the written language of the country they ship the products to.

As a matter of fact, Chinese people are really familiar with Chinese characters, Indian people really are far more familiar with Hindi than with English, German or Dutch.

These, and other languages are written in what we call Double Byte Character Sets, from now on I refer to this as DBCS.

I encourage you to read the above articles by both Margaret Duddy and Rick Strahl to get a better understanding on DBCS and unicode.


The challenge.

We all know that VFP does NOT do unicode or DBCS by nature.

What it DOES do is datahandling, like no other!

I did receive an excel spreadsheet with many languages.

That triggered me. A sheet with both Single Byte Character Sets (SBCS) as well as DBCS.

My first little experiment was to copy/paste one of the DBCS fields from the excel-sheet on a word document. That worked well.

My conclusion was that Windows’ memory did NOT alter the content AND that office controls do display the DBCS data well.

 

I did first create a database from the spreadsheet in  Access. (ok i wash my mouth later on). You can also use SQL Server, Oracle or MySQL for storing DBCS values.

The reason for me was that this application had to be low cost and the amount of data was not that much.

I did check the values in the table in the database among those in the excel sheet, they matched. With this the storage problem was solved. No tweaking needed for that, using other databases can thus be a solution for storing these values in a correct way.

 

The second problem was to display the data in the table.

As we all know the VFP controls cannot display DBCS values, what you see then is ??????????.

As I was determined to use VFP forms for this I had to come up with a solution that was available without much or no costs.

After some research I found that there is an ActiveX file that contains everything we need.

I speak about the FM20.dll in the system folder of your machine.

The controls? Microsoft Forms 2.0 xxx controls. Like Checkbox, Textbox, Listbox, SpinButton and others. a picture of the dialogue can be found here

 

These controls do not have the same possibilities as the VFP controls (did you really expect something else? Dream on!) but they are sufficient for most of the stuff like displaying data.

 

And of course, you can always subclass these controls, which I did, for good reason, as I will show later on in this article.

 

Using ADO to access the database and retrieving the record(s) you want brings the data in a result set in memory.

I created one simple form first to see whether I could display the data in memory.

(Simple display form)

 

Subclassing the activeX control and a builder.

When adding activeX controls to forms you have to follow a number of steps.

First you select, from the forms controls toolbar, the OLEControl.

Then you select Insert Control.

From the list that appears select the control and click OK.

 

This adds the activeX control on your form. It might not quite look like what you want.

The form 2.0 controls (at least the textbox I use here) appear like a square box on the form.

You can see the picture of a form with inserted textbox here

As you can see it is not really suitable for one line in a textfield.

 

So I first subclassed the control after resizing it, storing it in a VCX and then tried to drop it on my form… 

Here you see the result.

Not quite my idea of a useful textbox…

 

So I came up with the idea of a simple builder.

The task of this builder would be as follows:

After dropping a VFP based control on the form the builder can be invoked.

It will replace the vfp control with the activeX control.

It will resize the ActiveX textbox with the sizes of the textbox.

It will remove the original textbox from the form.

It will rename the name of the newly added control with the name of the control that is removed form the form.

 

The code was very simple:

LPARAMETERS P1, P2, P3

 

* parameter statement is needed, NOT in use in this tiny builder prg.

 

Local Array laControls[1]

LOCAL lni as Integer, loCntr as Object, lcname as String, lcNewname as String, lofrm as Object

 

IF ASELOBJ(laControls)>0

   FOR lni = 1 TO ALEN( laControls,1)

 

      *Check whether the control is of bl_text class

      *

      IF UPPER(laControls[lni].class) == "BL_TEXT"

         loCntr = lacontrols[lni]

         lcname = loCntr.name

        

         * Create a temp name form the object to insert

         *

         lcNewname = "_"+lcName

 

         WITH loCntr.Parent

           

            * Add a new object

            *

            .NewObject(lcNewName,;

                       "bltext",;

                       "<drive>:\<folder>\blcontrols.vcx")

 

            * Replace drive and folder

            * with the folder of your own settings

 

           

            * Change the characteristics

            * With those of the control that will be removed at the end.

            *

            .&lcNewname..Visible=.T.

            .&lcNewname..left = loCntr.Left

            .&lcNewname..top = loCntr.top

 

            * adjust width and height a bit

            * for better alignment.

            *

            .&lcNewname..width = loCntr.width+4

            .&lcNewname..height = loCntr.height+2

            .&lcNewname..controlsource = loCntr.controlsource

         ENDWITH

        

         * Remove the old control (the normal textbox)

         *

         lofrm = loCntr.Parent

         lofrm.RemoveObject( loCntr.Name)

        

         * Give the newly inserted control the name of the old control

         *

         lofrm.&lcNewname..name = lcname

      ENDIF

   ENDFOR 

ENDIF

 

This builder has no interface at all, I fancy the saying from Alan Cooper, “there is no better user interface than no interface at all.”

You DO need to register the builder in the home()+”wizards\builder.dbf”

 

Since I want to use this builder with a single object as well as with multiple objects I inserted two records in the builder table.

Make sure that the builder itself can be found by VFP, it has to be in one of the folder in the VFP search path.

The code to register the builder is simple.

 

INSERT INTO wizards\builder (name, type, program) ;

     VALUES ("blbuilder", "bl_text", "blbuilder.prg")

 

INSERT INTO wizards\builder (name, type, program) ;

     VALUES ("blbuilder", "MULTISELECT", "blbuilder.prg")

 

The final result is a form that can display different languages in ONE form 

Published Monday, March 12, 2007 10:51 AM by Boudewijn
Filed Under: , , ,

Comments

No Comments

Anonymous comments are disabled
Powered by Community Server, by Telligent Systems