Mastering Delphi 7 [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Mastering Delphi 7 [Electronic resources] - نسخه متنی

Marco Cantu

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
توضیحات
افزودن یادداشت جدید

Converting Data

As mentioned earlier in this chapter, Delphi includes a new conversion engine, defined in the Conv Utils unit. The engine by itself doesn't include any definition of actual measurement units; instead, it has a series of core functions for end users.

The key function is the conversion call, the Convert function. You simply provide the amount, the units it is expressed in, and the units you want it converted into. The following converts a temperature of 31 degrees Celsius to Fahrenheit:

Convert (31, tuCelsius, tuFahrenheit)

An overloaded version of the Convert function lets you convert values that have two units, such as speed (which has both a length unit and a time unit). For example, you can convert miles per hour to meters per second with this call:

Convert (20, duMiles, tuHours, duMeters, tuSeconds)

Other functions in the unit allow you to convert the result of an addition or a difference, check if conversions are applicable, and even list the available conversion families and units.

A predefined set of measurement units is provided in the StdConvs unit. This unit has conversion families and an impressive number of values, as shown in the following reduced excerpt:


// Distance Conversion Units
// basic unit of measurement is meters
cbDistance: TConvFamily;
duAngstroms: TConvType;
duMicrons: TConvType;
duMillimeters: TConvType;
duMeters: TConvType;
duKilometers: TConvType;
duInches: TConvType;
duMiles: TConvType;
duLightYears: TConvType;
duFurlongs: TConvType;
duHands: TConvType;
duPicas: TConvType;

This family and the various units are registered in the conversion engine in the initialization section of the unit, providing the conversion ratios (saved in a series of constants, such as MetersPerInch in the following code):

cbDistance := RegisterConversionFamily('Distance');
duAngstroms := RegisterConversionType(cbDistance,'Angstroms',1E-10);
duMillimeters:=RegisterConversionType(cbDistance,'Millimeters',0.001);
duInches := RegisterConversionType(cbDistance,'Inches',MetersPerInch);

To test the conversion engine, I built a generic example (ConvDemo) that allows you to work with the entire set of available conversions. The program fills a combo box with the available conversion families and a list box with the available units of the active family. This is the code:


procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
begin
GetConvFamilies (aFamilies);
for i := Low(aFamilies) to High(aFamilies) do
ComboFamilies.Items.Add (ConvFamilyToDescription (aFamilies[i]));
// get the first and fire event
ComboFamilies.ItemIndex := 0;
ChangeFamily (self);
end;
procedure TForm1.ChangeFamily(Sender: TObject);
var
aTypes: TConvTypeArray;
i: Integer;
begin
ListTypes.Clear;
CurrFamily := aFamilies [ComboFamilies.ItemIndex];
GetConvTypes (CurrFamily, aTypes);
for i := Low(aTypes) to High(aTypes) do
ListTypes.Items.Add (ConvTypeToDescription (aTypes[i]));
end;

The aFamilies and CurrFamily variables are declared in the private section of the form as follows:

aFamilies: TConvFamilyArray;
CurrFamily: TConvFamily;

At this point, a user can enter two measurement units and an amount in the corresponding edit boxes on the form, as you can see in Figure 3.3. To make the operation faster, the user can select a value in the list and drag it to one of the two Type edit boxes. The dragging support is described in the following sidebar "Simple Dragging in Delphi."


Figure 3.3: The ConvDemo example at run time








Simple Dragging in Delphi


The ConvDemo example, built to show how to use the conversion engine, uses an interesting technique: dragging. You can move the mouse over the list box, select an item, and then keep the left mouse button pressed and drag the item over one of the edit boxes in the center of the form.

To accomplish this functionality, I had to set the DragMode property of the list box (the source component) to dmAutomatic and implement the OnDragOver and OnDragDrop events of the target edit boxes (the two edit boxes are connected to the same event handlers, sharing the same code). In the first method, the program indicates that the edit boxes always accept the dragging operation, regardless of the source. In the second method, the program copies the text selected in the list box (the Source control of the dragging operation) to the edit box that fired the event (the Sender object). Here is the code for the two methods:


procedure TForm1.EditTypeDragOver(Sender, Source: TObject;
X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
Accept := True;
end;
procedure TForm1.EditTypeDragDrop(Sender, Source: TObject;
X, Y: Integer);
begin
(Sender as TEdit).Text := (Source as TListBox).Items
[(Source as TListBox).ItemIndex];
end;











The units must match those available in the current family. In case of error, the text in the Type edit boxes is shown in red. This is the effect of the first part of the form's DoConvert method, which is activated as soon as the value of one of the edit boxes for the units or the amount changes. After checking the types in the edit boxes, the DoConvert method performs the conversion, displaying the result in the fourth, grayed edit box. In case of errors, you'll get an appropriate message in the same box. Here is the code:


procedure TForm1.DoConvert(Sender: TObject);
var
BaseType, DestType: TConvType;
begin
// get and check base type
if not DescriptionToConvType(CurrFamily, EditType.Text, BaseType) then
EditType.Font.Color := clRed
else
EditType.Font.Color := clBlack;
// get and check destination type
if not DescriptionToConvType(CurrFamily, EditDestination.Text,
DestType) then
EditDestination.Font.Color := clRed
else
EditDestination.Font.Color := clBlack;
if (DestType = 0) or (BaseType = 0) then
EditConverted.Text := 'Invalid type'
else
EditConverted.Text := FloatToStr (Convert (
StrToFloat (EditAmount.Text), BaseType, DestType));
end;

If all this is not interesting enough for you, consider that the conversion types provided serve only as a demo: You can fully customize the engine by providing the measurement units you are interested in, as described in the next section.

/ 279