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

📄 ch11.htm

📁 好书《C++ Builder高级编程技术》
💻 HTM
📖 第 1 页 / 共 5 页
字号:

  AnimalsQueryMass->AsInteger =

    AnimalsQuerySIZE->AsInteger * AnimalsQueryWEIGHT->AsInteger;

}

</FONT></PRE>
<P>The code shown here assigns the value of the <TT>AnimalsQueryMass</TT> object
to the product of the 
<TT>AnimalsQuerySIZE</TT> and <TT>sqlWeightWEIGHT</TT> fields.
This kind of multiplication is legal to do because all of the fields are of the same
type. Furthermore, you could have used the <TT>Value</TT> property instead of <TT>AsInteger</TT>.
I 
explicitly declared the type in this example to help illustrate precisely what
is going on.</P>
<P><TT>OnCalcField</TT> methods are called each time a record is displayed to the
user. As a result, all of the <TT>Mass</TT> fields displayed in the grid 
are properly
filled in, as shown in Figure 11.4.<BR>
<BR>
<A NAME="Heading11"></A><A HREF="11ebu04.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/11/11ebu04.jpg">FIGURE 11.4.</A><FONT COLOR="#000077">
</FONT><I>The <TT>MASS</TT> field contains the product of the <TT>WEIGHT</TT> and
<TT>SIZE</TT> 
fields. </I><BR>
<BR>
A <TT>TDBImage</TT> control contains a bitmap from the <TT>BMP</TT> field of the
table.</P>
<P>To get the screen shot shown in Figure 11.4, I opened the <TT>Column</TT> property
in the <TT>TDBGrid</TT> object and selected Add All 
Fields. I then deleted the <TT>Area</TT>
and <TT>BMP</TT> fields and closed the <TT>Column</TT> property editor. I will talk
more about the grid object later in this chapter.</P>
<P>If you choose to never instantiate a particular field in the Fields 
Editor, the
current dataset you are working with no longer contains that field. It can't be accessed
programmatically or visually at runtime. Usually, this is exactly the effect you
want to achieve, and so this trait will generally be perceived as a 
strong benefit.
However, there are times when it might not serve your purposes, and in those cases
you should either create an object for all the fields in a table or stay away from
the Fields Editor altogether. Remember that you can hide fields 
inside a grid by
using the <TT>Column</TT> property, as shown previously. That way, you create objects
for all fields, but show only certain ones to the user.
<H3><A NAME="Heading12"></A><FONT COLOR="#000077">Lookup Fields</FONT></H3>
<P>You can use 
lookup fields to look up a value in one table that you want to use
in a second table. For instance, suppose you had two tables, one of which contained
a list of books, and the other contained a list of authors. It would be nice if you
could 
automatically view a list of the existing authors whenever you needed to add
a new book to the <TT>Books</TT> table. That way, you could enter the book's name,
look up the author in a drop-down list, and presto, you would be done. The <TT>Books</TT>

table would then automatically contain a reference to the appropriate author in the
<TT>Authors</TT> table. That is, the author number from the <TT>Authors</TT> table
would automatically be inserted in the <TT>Books</TT> table.</P>
<P>Another way to 
think about lookup fields is that they provide the ability to perform
a powerful kind of pseudo-join using the <TT>TTable</TT> object. Suppose two tables
called <TT>Authors</TT> and <TT>Books</TT> are related on a field called <TT>AuthNo</TT>.

<TT>AuthNo</TT> is the primary key of the <TT>Authors</TT> table, and it is a foreign
key in the <TT>Books</TT> table. When you are looking at the <TT>Books</TT> table,
sometimes you would like to be able to include the name of the author of each book

inside the book table. That is, you would like to perform a join on the book and
author table. You can't actually perform a join, however, because you are using the
<TT>TTable</TT> object, and not <TT>TQuery</TT>. The solution to this dilemma is
the 
lookup field. It will use the foreign key in the <TT>Books</TT> table to reference
the name of the author from the <TT>Author</TT> table. This technique does join one
better, however, because it will let you not only view a field from the 
<TT>Authors</TT>
table as if it were part of the <TT>Books</TT> table, but also enables you to drop
down a list of all the authors in the <TT>Authors</TT> table while you are still
viewing the <TT>Books</TT> table, as shown in Figure 11.5.</P>
<P>In 
short, lookup fields give you the same type of benefits you derive from performing
a join between two tables. In particular, they let you combine the fields of two
tables so that you can create one dataset with fields from multiple tables.

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



<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>Lookup fields are a bit like a combination
	of a one-to-many relationship and a calculated field. The techniques used to actually
	implement them, however, have 
more in common with calculated fields than they do
	with one-to-many relationships. There are significant differences between the three
	technologies, but I still tend to think of calculated fields, lookup fields, and
	one-to-many relationships as 
being interrelated concepts. <BR>
	<BR>
	Because lookup fields are so much like one-to-many relationships, it is usually not
	a good idea to use both techniques simultaneously with the same two <TT>TTable</TT>
	objects. For instance, if you have the 
<TT>Authors</TT> table related to the books
	table in a one-to-many, you wouldn't want to simultaneously do a lookup from the
	<TT>Books</TT> table to the author table. This problem, and its solution, are addressed
	in the <TT>Lookup</TT> example on 
the CD-ROM that accompanies this book. That program
	will be discussed throughout the rest of this section of the chapter. <BR>
	<BR>
	I should perhaps add that lookup fields are a great technique to use with relatively
	small datasets. If you are 
from the world of big iron, and work with tables that
	contain tens of thousands of records or more, you will probably find lookup fields
	are of only limited use to you. 
<HR>


</BLOCKQUOTE>

<P>Needless to say, BCB gives good support for using 
lookup fields. You can now perform
automatic lookups inside grids, list boxes, and combo boxes. In particular, the following
controls support lookups: <TT>TDBGrid</TT>, <TT>TDBCtrlGrid</TT>, <TT>TDBLookupListBox</TT>,
and 
<TT>TDBLookupComboBox</TT>.</P>
<P>The Lookup program shows how to proceed. The code for this application is shown
in Listings 11.1 through 11.3. Two views of the program are shown in Figures 11.5
and 11.6.<BR>
<BR>
<A NAME="Heading14"></A><A 
HREF="11ebu05.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/11/11ebu05.jpg">FIGURE 11.5.</A><FONT COLOR="#000077">
</FONT><I>The main form for the Lookup program.</I>
<H6></H6>
<P><A NAME="Heading15"></A><A HREF="11ebu06.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/11/11ebu06.jpg">FIGURE 11.6.</A><FONT COLOR="#000077">
</FONT><I>This form features 
a combo box that lets you perform lookups from the <TT>Books</TT>
table into the <TT>Authors</TT> table.</I>

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



<BLOCKQUOTE>
	<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>The first version of Delphi had
	a 
<TT>TDBLookupCombo</TT> control and a <TT>TDBLookupList</TT> control that had certain
	limited capabilities. Both of these controls are still present in some versions of
	BCB, but they have been moved off the Data Controls page onto the Win 3.1 page. 
They
	are being kept around solely for compatibility with legacy Pascal code, and you should
	not use them in new programs. <BR>
	<BR>
	The <TT>TDBLookupComboBox</TT> control and the <TT>TDBLookupListBox</TT> control
	now replace the old 16-bit 
controls, and they outperform them on several fronts.
	In particular, the <TT>TDBLookupComboBox</TT> and <TT>TDBLookupListBox</TT> will
	be filled up automatically with the data from the lookup table. Don't confuse the
	old control with the new ones! 
<TT>TDBLookupComboBox</TT> is the fancy one; the <TT>TDBLookupCombo</TT>
	is the old-fashioned one. You might use the following somewhat whimsical mnemonic:
	The <TT>TDBLookupListBox</TT> has a bigger name than the <TT>TDBLookupList</TT> because
	it 
has &quot;bigger&quot; capabilities. <BR>
	<BR>
	By the way, this is a classic example of why it is important to get things right
	the first time. In particular, it shows why it is sometimes better to cut a feature
	rather than trying to put in a hack 
that you will want to improve in later versions.
	In particular, the <TT>TDBLookupCombo</TT> was poorly implemented in the first version
	of Delphi, which was a 16-bit program. Because Delphi 2.0 promised to compile all
	your 16-bit programs, this 
component had to be left in the product even though it
	was replaced with a far superior tool. Now, this old nemesis lives on even in the
	C++ version of the product, because BCB advertises the fact that it supports all
	the legacy Pascal code you 
might want to bring into a project. <BR>
	<BR>
	Here's the summary: The original error was made back in Delphi 1.0, but the repercussions
	still echo even when the 32-bit version of the Delphi is ported to C++! Clearly,
	it is worthwhile making sure 
that things are designed right the first time, or else
	they should be left out of the product altogether. Of course, this is a rule that
	can be stated fairly easily, but is difficult to live up to. 
<HR>


</BLOCKQUOTE>

<P><A 
NAME="Heading17"></A><FONT COLOR="#000077"><B>Listing 11.1. The core functionality
for the Lookup program is done in the Object Inspector for the TDMod object and not
here in the code for Dmod1.cpp.</B></FONT></P>
<PRE><FONT 
COLOR="#0066FF">///////////////////////////////////////

// File: DMod1.cpp

// Project: Lookup

// Copyright (c) 1997 by Charlie Calvert

#include &lt;vcl\vcl.h&gt;

#pragma hdrstop

#include &quot;DMod1.h&quot;

#pragma resource &quot;*.dfm&quot;


TDMod *DMod;

__fastcall TDMod::TDMod(TComponent* Owner)

  : TDataModule(Owner)

{

  AuthorTable-&gt;Open();

  BookDetailTable-&gt;Open();

  BookLookupTable-&gt;Open();

}

void __fastcall TDMod::AuthorTableCalcFields(TDataSet *DataSet)

{

  
AuthorTableFirstLast-&gt;AsString =

    AuthorTableFirst-&gt;AsString + &quot; &quot; + AuthorTableLast-&gt;AsString;

}

void TDMod::RefreshBookDetail()

{

  BookDetailTable-&gt;Refresh();

}

AnsiString TDMod::GetCurBook()

{

  return 
BookDetailTable-&gt;FieldByName(&quot;Title&quot;)-&gt;AsString;

}

AnsiString TDMod::GetCurAuthor(void)

{

  return AuthorTable-&gt;FieldByName(&quot;FirstLast&quot;)-&gt;AsString;

}

void TDMod::FindAuthor(AnsiString S)

{

  
AuthorTable-&gt;FindNearest(OPENARRAY(TVarRec, (S)));

}

void TDMod::FindTitle(AnsiString S)

{

  AnsiString Temp(BookLookupTable-&gt;IndexName);

  BookLookupTable-&gt;IndexName = &quot;idxTitle&quot;;

  
BookLookupTable-&gt;FindNearest(OPENARRAY(TVarRec, (S)));

  BookLookupTable-&gt;IndexName = Temp;

}

void TDMod::BookLookupInsert()

{

  BookLookupTable-&gt;Insert();

}

void TDMod::BookLookupPost()

{

  if ((BookLookupTable-&gt;State == 
dsEdit)||(BookLookupTable-&gt;State == dsInsert))

    BookLookupTable-&gt;Post();

}

void TDMod::BookLookupCancel()

{

  if ((BookLookupTable-&gt;State == dsEdit)||(BookLookupTable-&gt;State == dsInsert))

    BookLookupTable-&gt;Cancel();

}

void 
TDMod::BookLookupDelete()

{

  BookLookupTable-&gt;Delete();

}

</FONT></PRE>
<P><A NAME="Heading18"></A><FONT COLOR="#000077"><B>Listing 11.2. Form1 gives you
a look at both the Authors table and the Books table. A drop-down in dbGrid2 lets
you 
view the lookup field.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">///////////////////////////////////////

// File: InsertEdit.cpp

// Project: Lookup

// Copyright (c) 1997 by Charlie Calvert

#include &lt;vcl\vcl.h&gt;

#pragma hdrstop

#include 
&quot;Main.h&quot;

#include &quot;DMod1.h&quot;

#include &quot;InsertEdit.h&quot;

#pragma resource &quot;*.dfm&quot;

TForm1 *Form1;

__fastcall TForm1::TForm1(TComponent* Owner)

  : TForm(Owner)

{

}

void __fastcall TForm1::Exit1Click(TObject 
*Sender)

{

  Close();

}

void __fastcall TForm1::EditBook1Click(TObject *Sender)

{

  InsertEditForm-&gt;ShowEdit(DMod-&gt;CurBook);

  DMod-&gt;RefreshBookDetail();

}

void __fastcall TForm1::NewBook1Click(TObject *Sender)

{

  
InsertEditForm-&gt;ShowInsert();

  DMod-&gt;RefreshBookDetail();

}

</FONT></PRE>
<P><A NAME="Heading19"></A><FONT COLOR="#000077"><B>Listing 11.3. The InsertEditForm
shows how to use DBLookupComboBoxes.</B></FONT></P>
<PRE><FONT 
COLOR="#0066FF">///////////////////////////////////////

// File: InsertEdit.cpp

// Project: Lookup

// Copyright (c) 1997 by Charlie Calvert

#include &lt;vcl\vcl.h&gt;

#pragma hdrstop

⌨️ 快捷键说明

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