⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch11.htm

📁 好书《C++ Builder高级编程技术》
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>

<HEAD>
	<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
	<META NAME="Author" Content="Steph Mineart">
	<TITLE>Ch 11 -- Working with Field Objects</TITLE>
</HEAD>

<BODY 
BACKGROUND="bg1.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/bg1.gif" BGCOLOR="#FFFFFF">

<P ALIGN="CENTER"><IMG SRC="sams.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/sams.gif" WIDTH="75" HEIGHT="24" ALIGN="BOTTOM"
BORDER="0"><BR>
<BR>
<A HREF="index-3.htm" tppabs="http://pbs.mcp.com/ebooks/0672310228/index.htm"><IMG SRC="toc.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/toc.gif" WIDTH="40" HEIGHT="40" ALIGN="BOTTOM"

ALT="TOC" BORDER="0" NAME="toc4"></A><A HREF="ch10.htm" tppabs="http://pbs.mcp.com/ebooks/0672310228/ch10.htm"><IMG SRC="back-1.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/back.gif"
WIDTH="40" HEIGHT="40" ALIGN="BOTTOM" ALT="BACK" BORDER="0" NAME="toc1"></A><A HREF="ch12.htm" tppabs="http://pbs.mcp.com/ebooks/0672310228/ch12.htm"><IMG
SRC="forward.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/forward.gif" WIDTH="40" HEIGHT="40" ALIGN="BOTTOM" 
ALT="FORWARD" BORDER="0"
NAME="toc2"></A></P>
<H2 ALIGN="CENTER"><FONT COLOR="#000077">Charlie Calvert's C++ Builder Unleashed</FONT></H2>
<P>
<H2 ALIGN="CENTER"><A NAME="Heading1"></A>- <FONT COLOR="#000077">11 -</FONT></H2>
<H2 ALIGN="CENTER"><A 
NAME="Heading2"></A><FONT COLOR="#000077">Working with Field
Objects</FONT></H2>
<P>This chapter covers a set of visual tools you can use to simplify database development.
The major areas covered are as follows:

<UL>
	<LI>The Fields Editor
	<P>
	
<LI><TT>TField</TT> descendant objects
	<P>
	<LI>Calculated fields
	<P>
	<LI>The <TT>TDBGrid</TT> component
	<P>
	<LI>Lookup fields
	<P>
	<LI><TT>MultiRecord</TT> objects--<TT>TDBCtrlGrid</TT>
</UL>

<P>These subjects are all related to databases, and 
to the <TT>TField</TT> and <TT>TDBGrid</TT>
objects in particular. BCB is a very sophisticated database tool, and it takes time
to get a feeling for the breadth and depth of the tools it provides for client/server
developers. One of the goals of this 
chapter is to give you some sense of the powerful
<TT>TField</TT> object and its impact on designing database applications.</P>
<P>One of the most frequently mentioned tools in this chapter is the Fields Editor.
By using the Fields Editor, you can 
create objects that influence the appearance
of data shown in visual controls such as <TT>TDBEdit</TT> and <TT>TDBGrid</TT>. For
instance, you can use the objects made in the Fields Editor to format data so that
it appears as currency or as a 
floating-point number with a defined precision. These
same changes can be accomplished through the Data Dictionary in the Database Explorer
or through the Database Desktop. These latter tools, however, have a global impact
on the field's potential 
values, whereas the changes made in the Object Inspector
affect only the current application.</P>
<P>If you want to dynamically emphasize a particular column or row in a table, this
is the chapter you should read to get the information you need. For 
instance, this
chapter covers the <TT>Columns</TT> property of the <TT>TDBGrid</TT> control. The
<TT>Columns</TT> property can be used to change the appearance of a grid so that
its columns are arranged in a new order or are hidden. You can also use 
the <TT>Columns</TT>
property to change the color of columns in a grid, or to insert drop-down combo boxes
into a grid.</P>
<P>The lessons you learn in this chapter will arm you with key techniques used by
most pro- grammers when they present database 
tables to their users. Much of the
material involves manipulating visual tools, but the basic subject matter is fairly
technical and assumes a basic understanding of the BCB environment and language.
Note that third parties such as TurboPower (<A 
HREF="javascript:if(confirm('http://www.turbopower.com/  \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address.  \n\nDo you want to open it from the server?'))window.location='http://www.turbopower.com/'" tppabs="http://www.turbopower.com/"><TT>www.turbopower.com</TT></A>)
and Woll2Woll (<A HREF="javascript:if(confirm('http://www.woll2woll.com/  \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address.  \n\nDo you want to open it from the server?'))window.location='http://www.woll2woll.com/'" tppabs="http://www.woll2woll.com/"><TT>www.woll2woll.com</TT></A>)
have grid objects that go beyond the capability of the native grids that ship with
BCB.
<H3><A 
NAME="Heading3"></A><FONT COLOR="#000077">The Fields Editor</FONT></H3>
<P>To get things rolling, it might be a good idea to take a close look at the invaluable
Fields Editor. This tool lies very much at the heart of BCB database programming.
To 
access it, you double-click or right-click on a <TT>TTable</TT> or <TT>TQuery</TT>
object.</P>
<P>The Fields Editor helps you associate custom objects with some or all of the fields
from a table. By associating a custom object with a field, you can 
control the way
a field displays, formats, validates, and inputs data. The Fields Editor also enables
you to add new fields to a table at runtime and then to calculate the values that
will be shown in the new fields. This latter procedure is referred 
to as calculated
fields. Another benefit of the Fields Editor is that it helps you create lookup fields.
Lookup fields perform a lookup from one table into another based on a foreign key.</P>
<P>It's important to understand that the Fields Editor is 
just a utility. Everything
done inside the Fields Editor could be done in code, although in this particular
case the code in question becomes a little complicated, or at least time consuming.</P>
<P>In this section and the next, you will be building a 
program called MASS, which
illustrates both the Fields Editor and calculated fields. This is an important program,
so you should try to use your copy of BCB to follow the steps described.
<H3><A NAME="Heading4"></A><FONT COLOR="#000077">Getting 
Started with the Fields
Editor</FONT></H3>
<P>You can access the Fields Editor from either a <TT>TTable</TT> or <TT>TQuery</TT>
object. To get started, drop a <TT>TQuery</TT> object on a data module, set up the
<TT>BCDEMOS</TT> alias, enter the SQL 
statement <TT>select * from animals</TT>, and
make the table active. (The <TT>BCDEMOS</TT> alias is created automatically when
you install BCB. It points at the data in the <TT>CBuilder/Examples/Data</TT> directory.
If you are having trouble with 
aliases, see the readme file on the CD or visit my
Web site.)</P>
<P>Drop down the Object Selector at the top of the Object Inspector. Notice that
you currently have two components in use: <TT>TDataModule</TT> and <TT>TQuery</TT>.</P>
<P>Right-click 
the <TT>TQuery</TT> object and select the Fields Editor menu choice
to bring up the Fields Editor. Right-click the Fields Editor and select Add Fields
from the menu to pop up the Add Fields dialog, as shown in Figure 11.1.<BR>
<BR>
<A 
NAME="Heading5"></A><A HREF="11ebu01.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/11/11ebu01.jpg">FIGURE 11.1.</A><FONT COLOR="#000077">
</FONT><I>The Add Fields dialog box from the Fields Editor.</I></P>
<P>By default, all of the fields in the dialog box are selected. Click the OK button
to select 
all five fields, and then close the Fields Editor.</P>
<P>Open the Object Selector a second time; notice that there are now five new objects
on your form, as shown in Figure 11.2.<BR>
<BR>
<A NAME="Heading6"></A><A HREF="11ebu02.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/11/11ebu02.jpg">FIGURE 
11.2.</A><FONT COLOR="#000077">
</FONT><I>The Object Selector lists the objects created in the Fields Editor. <BR>
<BR>
</I>You also can find this list in the <TT>TForm1</TT> class definition.</P>
<P>These objects help you hone and define your 
presentation of the <TT>Animals</TT>
table to the user.</P>
<P>Here's a complete list of the objects you just created, as they appear in your
header file:</P>
<PRE><FONT COLOR="#0066FF">TStringField *AnimalsQueryNAME;

TSmallintField 
*AnimalsQuerySIZE;

TSmallintField *AnimalsQueryWEIGHT;

TStringField *AnimalsQueryAREA;

TBlobField *AnimalsQueryBMP;

</FONT></PRE>
<P>The origins of the names shown here should be fairly obvious. The string <TT>AnimalsQuery</TT>
comes from the name 
I've given to the <TT>TQuery</TT> object, and the second half
of the name comes from the fields in the <TT>Animals</TT> table. This naming convention
I've adopted here can be very useful if you are working with several tables and want
to know at a 
glance which table and field are being referenced by a particular variable.

<DL>
	<DT></DT>
</DL>



<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>The names of the fields in the example
	shown here are capitalized only 
because the table in question is a dBASE table. dBASE
	tables automatically capitalize all letters in field names. If I had chosen to work
	with some other type of table, the capitalization of the letters in the field name
	would have followed the 
rules defined by the current database software. <BR>
	<BR>
	This principle appears again and again in BCB database programming. Whenever possible,
	the actual naming conventions and other traits of a server are surfaced inside of
	BCB. The developers 
of C++Builder did not aim to make all servers appear the same
	to you, but rather to give you access to their features as transparently as possible.
	Of course, generic tools such as the <TT>TTable</TT> object are also common in BCB.
	The VCL team, 
however, strove to find the right balance between expediting access
	to the database and unintentionally crippling the database by wrapping too many of
	its features inside objects. As a rule, the developers did whatever they could to
	ease the path, 
without ever going so far as to actually cut you off from a feature
	of the server you are accessing. <BR>
	<BR>
	This same principle applies to the VCL. The developers tried to do everything they
	could to make Windows programming simple, but they 
drew the line if a particular
	feature was so warm and fuzzy that it cut you off from direct access to the OS when
	and if you needed it. 
<HR>


</BLOCKQUOTE>

<P>Each of the objects created in the Fields Editor is a descendant of <TT>TField</TT>.

The exact type of descendant depends on the type of data in a particular field. For
instance, the <TT>AnimalsQueryWEIGHT</TT> field is of type <TT>TSmallIntField</TT>,
whereas the <TT>AnimalsQueryNAME</TT> field is of type <TT>TStringField</TT>. These

are the two field types you will see most often. Other common types include <TT>TDateField</TT>
and <TT>TCurrencyField</TT>, neither of which are used in this particular table.
Remember that these types were selected to correspond with the field types 
in the
table itself.</P>
<P><TT>TStringField</TT>, <TT>TSmallIntField</TT>, and the other objects shown here
are all descendants of <TT>TField</TT> and share its traits. If you want, you can
treat these objects exactly as you did the <TT>TField</TT> 
objects that you learned
about in Chapter 9, &quot;Using <TT>TTable</TT> and <TT>TDataSet</TT>.&quot; For
instance, you can write this:</P>
<PRE><FONT COLOR="#0066FF">S = MyIntegerField-&gt;AsString;

</FONT></PRE>
<P>and this:</P>
<PRE><FONT 
COLOR="#0066FF">S = MyIntegerField-&gt;Name;

</FONT></PRE>
<P>However, these descendants of <TT>TField</TT> are very smart objects and have
several traits that go beyond the functionality of their common ancestor.</P>
<P>The most important property 
you will see is called <TT>Value</TT>. You can access
it like this:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TForm1::Button1Click(TObject *Sender)

{

  int i;

  AnsiString S;

  DMod-&gt;AnimalsQuery-&gt;Edit();

  i = 
DMod-&gt;AnimalsQuerySIZE-&gt;Value;

  S = DMod-&gt;AnimalsQueryNAME-&gt;Value;

  i += 1;

  S = &quot;Foo&quot;;

  DMod-&gt;AnimalsQuerySIZE-&gt;Value = i;

  DMod-&gt;AnimalsQueryNAME-&gt;Value = S;

}

</FONT></PRE>
<P>The code shown here first 
assigns values to the variables <TT>i</TT> and <TT>S</TT>.
The next two lines change these values, and the last two lines reassign the new values
to the objects. It usually wouldn't make much sense to write code exactly like this
in a program, but it 
serves to illustrate the syntax used by <TT>TField</TT> descendants.
(If you bother to try to write code like this as a test, remember that the <TT>RequestLive</TT>
property for a <TT>TQuery</TT> object is set to <TT>False</TT> by default. You would

have to set it to <TT>True</TT> before the code would work.)</P>
<P>The <TT>Value</TT> property always conforms to the type of field you have instantiated.
For instance, <TT>TStringField</TT>s are strings, whereas <TT>TCurrencyField</TT>s
always 
return floating-point double values. However, if you show a <TT>TCurrencyField</TT>
in a data-aware control, it will return a string that looks like this: <TT>&quot;$5.00&quot;</TT>.
The dollar sign and the rounding to decimal places are simply part 
and parcel of
what a <TT>TCurrencyField</TT> is all about.</P>
<P>The preceding example might make you think that these variables are declared as
<TT>Variants</TT>, which indeed is the case for the <TT>TField</TT> object itself.
In the actual 
implementation, however, the <TT>TCurrencyField-&gt;Value</TT> is declared
as a <TT>Double</TT>. If you tried to assign a string to it, you would get a type
mismatch. Likewise, <TT>TIntegerField.Value</TT> is declared as a <TT>LongInt</TT>,
and so on. 
<TT>TSmallIntField</TT> and <TT>TWordField</TT> are both descendants of
<TT>TIntegerField</TT> and inherit the <TT>Value</TT> declaration as a <TT>LongInt</TT>.
However, they have other internal code that affects the <TT>Value</TT> field, just
as 
<TT>TCurrencyField</TT> rings some changes on its <TT>Value</TT> field to make
it look like a monetary value. If you have the source, look up <TT>DBTABLES.PAS</TT>
and <TT>DB.PAS</TT> to find the details of these constructions. (The Pascal source

ships with some versions of BCB.) At any rate, the point here is that the preceding
code is an example of polymorphism; it is not an example of relaxed type-checking.
The <TT>Value</TT> field has a specific type--it's just that it undergoes 
polymorphic
changes.</P>
<P>If you want the names of each field in the current dataset, you should reference
the <TT>FieldName</TT> property through one of the following two methods:</P>
<PRE><FONT COLOR="#0066FF">S = 
AnimalsQuery-&gt;Fields[0]-&gt;FieldName;

S = AnimalsQueryNAME.FieldName;

</FONT></PRE>
<P>If you want the name of an object associated with a field, you should use the
<TT>Name</TT> property:</P>
<PRE><FONT COLOR="#0066FF">S = 
AnimalsQuery-&gt;Fields[0]-&gt;Name;

S = AnimalsQueryNAME-&gt;Name;

</FONT></PRE>
<P>When using the <TT>ANIMALS</TT> table, the first two examples shown previously
yield the string <TT>&quot;Name&quot;</TT>, while the second two lines yield 
<TT>&quot;Query1NAME&quot;</TT>.</P>
<P>Special properties are associated with most of the major field types. For instance,
<TT>TIntegerField</TT>s have <TT>DisplayFormat</TT> and <TT>DisplayEdit</TT> properties,
as well as <TT>MinValue</TT> and 
<TT>MaxValue</TT> properties. <TT>TStringField</TT>s,
on the other hand, have none of these properties, but they do have an <TT>EditMask</TT>
property, which works just like the <TT>TEditMask</TT> component found on the Additional
page of the 
Component Palette. All these properties are used to control the way data
is displayed to the user, or the way that input from the user should be handled.

<DL>
	<DT></DT>
</DL>



<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> 
</B>I don't want to get ahead of myself,
	but properties such as <TT>MinValue</TT> and <TT>MaxValue</TT> are also used in the
	Data Dictionary, as will be explained later in this chapter. Changes made in the
	Data Dictionary will affect these values 
as seen in the Object Inspector, but changes
	in the Object Inspector will not affect the Data Dictionary. Don't worry if this
	doesn't make the slightest bit of sense yet, as I will get to the Data Dictionary
	in just a little while. 
<HR>



</BLOCKQUOTE>

<H3><A NAME="Heading9"></A><FONT COLOR="#000077">Calculated Fields</FONT></H3>
<P>You should be aware of one more thing about the Fields Editor. You can use this
tool not only to build objects that encapsulate existing fields, but also 
to build
objects that represent new fields. For instance, suppose you wanted to create a sixth
field, <TT>Mass</TT>, which contains the product of the <TT>SIZE</TT> and <TT>WEIGHT</TT>
fields, in the <TT>Animals</TT> table.</P>
<P>To create the 
<TT>Mass</TT> field, open the Fields Editor again, right-click it,
and select the New Field menu choice. In the top part of the New Field dialog, enter
the word <TT>Mass</TT>. Now set its type to <TT>Integer</TT>, and leave its field
type as 
Calculated, as shown in Figure 11.3.<BR>
<BR>
<A NAME="Heading10"></A><A HREF="11ebu03.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/11/11ebu03.jpg">FIGURE 11.3.</A><FONT COLOR="#000077">
</FONT><I>Creating the <TT>Mass</TT> field in the Fields Editor.</I></P>
<P>If you close the Fields Editor and 
add a <TT>TDataSource</TT> and <TT>TDBGrid</TT>
to your project, you will see that the <TT>Animals</TT> table now appears to have
six fields, the last of which is called <TT>MASS</TT>.</P>
<P>Of course, it's one thing to create a field, and another to 
fill it in at runtime
with an appropriate value. The act of placing a value in the new field you have created
involves a concept called calculated fields.</P>
<P>Calculated fields are one of the most valuable features of the <TT>TField</TT>
object and 
its related architecture. You can use these calculated fields for several
different purposes, but two stand out:

<UL>
	<LI>If you need to perform calculations on two or more of the fields in a dataset
	and want to show the results of the calculations 
in a third field, you can use calculated
	fields. A scenario describing this type of situation was set up at the beginning
	of this section.
	<P>
	<LI>If you are viewing one dataset and want to perform calculations or display data
	that involve 
lookups in at least one additional dataset, you can use the Fields Editor
	and calculated fields to show the results of these calculations in a new field of
	the first dataset. There is also a second, much better method for doing lookups.
	I will talk 
about that method later in this chapter. As a rule, you should do calculations
	in calculated fields, and lookups in lookup fields, though calculated fields are
	powerful enough to fill a number of different roles in your programs.
</UL>

<P>The MASS 
program illustrates one example of the first of the two uses for calculated
fields. You got this program started in the last section when you created the field
called MASS and displayed it in a grid.</P>
<P>To continue working with the MASS program, 
highlight the <TT>AnimalsQuery</TT>
object and set the Object Inspector to the Events page. Now create an <TT>OnCalcFields</TT>
event that looks like this:</P>
<PRE><FONT COLOR="#0066FF">void __fastcall TDMod::AnimalsQueryCalcFields(TDataSet *DataSet)


{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -